Merge "keystone: Add support for deploying httpd for federation"

This commit is contained in:
Zuul 2025-11-07 15:49:51 +00:00 committed by Gerrit Code Review
commit e94901d35d
10 changed files with 317 additions and 26 deletions

View file

@ -31,19 +31,6 @@ keystone_services:
backend_http_extra:
- "balance {{ 'source' if enable_keystone_federation | bool else 'roundrobin' }}"
- "option httpchk"
keystone-ssh:
container_name: "keystone_ssh"
group: "keystone"
enabled: true
image: "{{ keystone_ssh_image_full }}"
volumes:
- "{{ node_config_directory }}/keystone-ssh/:{{ container_config_directory }}/:ro"
- "/etc/localtime:/etc/localtime:ro"
- "{{ '/etc/timezone:/etc/timezone:ro' if ansible_facts.os_family == 'Debian' else '' }}"
- "kolla_logs:/var/log/kolla/"
- "keystone_fernet_tokens:/etc/keystone/fernet-keys"
dimensions: "{{ keystone_ssh_dimensions }}"
healthcheck: "{{ keystone_ssh_healthcheck }}"
keystone-fernet:
container_name: "keystone_fernet"
group: "keystone"
@ -57,6 +44,27 @@ keystone_services:
- "keystone_fernet_tokens:/etc/keystone/fernet-keys"
dimensions: "{{ keystone_fernet_dimensions }}"
healthcheck: "{{ keystone_fernet_healthcheck }}"
keystone-httpd:
container_name: "keystone_httpd"
group: "keystone"
enabled: "{{ enable_keystone_federation | bool }}"
image: "{{ keystone_httpd_image_full }}"
volumes: "{{ keystone_httpd_default_volumes + keystone_httpd_extra_volumes }}"
dimensions: "{{ keystone_httpd_dimensions }}"
healthcheck: "{{ keystone_httpd_healthcheck }}"
keystone-ssh:
container_name: "keystone_ssh"
group: "keystone"
enabled: true
image: "{{ keystone_ssh_image_full }}"
volumes:
- "{{ node_config_directory }}/keystone-ssh/:{{ container_config_directory }}/:ro"
- "/etc/localtime:/etc/localtime:ro"
- "{{ '/etc/timezone:/etc/timezone:ro' if ansible_facts.os_family == 'Debian' else '' }}"
- "kolla_logs:/var/log/kolla/"
- "keystone_fernet_tokens:/etc/keystone/fernet-keys"
dimensions: "{{ keystone_ssh_dimensions }}"
healthcheck: "{{ keystone_ssh_healthcheck }}"
####################
# Config Validate
@ -105,6 +113,10 @@ keystone_image: "{{ docker_image_url }}keystone"
keystone_service_tag: "{{ keystone_tag }}"
keystone_image_full: "{{ keystone_image }}:{{ keystone_service_tag }}"
keystone_httpd_image: "{{ docker_image_url }}httpd"
keystone_httpd_tag: "{{ keystone_tag }}"
keystone_httpd_image_full: "{{ keystone_httpd_image }}:{{ keystone_httpd_tag }}"
keystone_fernet_image: "{{ docker_image_url }}keystone-fernet"
keystone_fernet_tag: "{{ keystone_tag }}"
keystone_fernet_image_full: "{{ keystone_fernet_image }}:{{ keystone_fernet_tag }}"
@ -114,6 +126,7 @@ keystone_ssh_tag: "{{ keystone_tag }}"
keystone_ssh_image_full: "{{ keystone_ssh_image }}:{{ keystone_ssh_tag }}"
keystone_dimensions: "{{ default_container_dimensions }}"
keystone_httpd_dimensions: "{{ default_container_dimensions }}"
keystone_fernet_dimensions: "{{ default_container_dimensions }}"
keystone_ssh_dimensions: "{{ default_container_dimensions }}"
@ -130,18 +143,18 @@ keystone_healthcheck:
test: "{% if keystone_enable_healthchecks | bool %}{{ keystone_healthcheck_test }}{% else %}NONE{% endif %}"
timeout: "{{ keystone_healthcheck_timeout }}"
keystone_ssh_enable_healthchecks: "{{ enable_container_healthchecks }}"
keystone_ssh_healthcheck_interval: "{{ default_container_healthcheck_interval }}"
keystone_ssh_healthcheck_retries: "{{ default_container_healthcheck_retries }}"
keystone_ssh_healthcheck_start_period: "{{ default_container_healthcheck_start_period }}"
keystone_ssh_healthcheck_test: ["CMD-SHELL", "healthcheck_listen sshd {{ keystone_ssh_port }}"]
keystone_ssh_healthcheck_timeout: "{{ default_container_healthcheck_timeout }}"
keystone_ssh_healthcheck:
interval: "{{ keystone_ssh_healthcheck_interval }}"
retries: "{{ keystone_ssh_healthcheck_retries }}"
start_period: "{{ keystone_ssh_healthcheck_start_period }}"
test: "{% if keystone_ssh_enable_healthchecks | bool %}{{ keystone_ssh_healthcheck_test }}{% else %}NONE{% endif %}"
timeout: "{{ keystone_ssh_healthcheck_timeout }}"
keystone_httpd_enable_healthchecks: "{{ enable_container_healthchecks }}"
keystone_httpd_healthcheck_interval: "{{ default_container_healthcheck_interval }}"
keystone_httpd_healthcheck_retries: "{{ default_container_healthcheck_retries }}"
keystone_httpd_healthcheck_start_period: "{{ default_container_healthcheck_start_period }}"
keystone_httpd_healthcheck_test: ["CMD-SHELL", "healthcheck_curl {{ 'https' if keystone_enable_tls_backend | bool else 'http' }}://{{ api_interface_address | put_address_in_context('url') }}:{{ keystone_public_listen_port }}"]
keystone_httpd_healthcheck_timeout: "{{ default_container_healthcheck_timeout }}"
keystone_httpd_healthcheck:
interval: "{{ keystone_httpd_healthcheck_interval }}"
retries: "{{ keystone_httpd_healthcheck_retries }}"
start_period: "{{ keystone_httpd_healthcheck_start_period }}"
test: "{% if keystone_httpd_enable_healthchecks | bool %}{{ keystone_httpd_healthcheck_test }}{% else %}NONE{% endif %}"
timeout: "{{ keystone_httpd_healthcheck_timeout }}"
keystone_fernet_enable_healthchecks: "{{ enable_container_healthchecks }}"
keystone_fernet_healthcheck_interval: "{{ default_container_healthcheck_interval }}"
@ -156,6 +169,19 @@ keystone_fernet_healthcheck:
test: "{% if keystone_fernet_enable_healthchecks | bool %}{{ keystone_fernet_healthcheck_test }}{% else %}NONE{% endif %}"
timeout: "{{ keystone_fernet_healthcheck_timeout }}"
keystone_ssh_enable_healthchecks: "{{ enable_container_healthchecks }}"
keystone_ssh_healthcheck_interval: "{{ default_container_healthcheck_interval }}"
keystone_ssh_healthcheck_retries: "{{ default_container_healthcheck_retries }}"
keystone_ssh_healthcheck_start_period: "{{ default_container_healthcheck_start_period }}"
keystone_ssh_healthcheck_test: ["CMD-SHELL", "healthcheck_listen sshd {{ keystone_ssh_port }}"]
keystone_ssh_healthcheck_timeout: "{{ default_container_healthcheck_timeout }}"
keystone_ssh_healthcheck:
interval: "{{ keystone_ssh_healthcheck_interval }}"
retries: "{{ keystone_ssh_healthcheck_retries }}"
start_period: "{{ keystone_ssh_healthcheck_start_period }}"
test: "{% if keystone_ssh_enable_healthchecks | bool %}{{ keystone_ssh_healthcheck_test }}{% else %}NONE{% endif %}"
timeout: "{{ keystone_ssh_healthcheck_timeout }}"
keystone_default_volumes:
- "{{ node_config_directory }}/keystone/:{{ container_config_directory }}/:ro"
- "/etc/localtime:/etc/localtime:ro"
@ -165,7 +191,14 @@ keystone_default_volumes:
- "{{ '/dev/shm:/dev/shm' }}"
- "keystone_fernet_tokens:/etc/keystone/fernet-keys"
keystone_httpd_default_volumes:
- "{{ node_config_directory }}/keystone-httpd/:{{ container_config_directory }}/:ro"
- "/etc/localtime:/etc/localtime:ro"
- "{{ '/etc/timezone:/etc/timezone:ro' if ansible_facts.os_family == 'Debian' else '' }}"
- "kolla_logs:/var/log/kolla/"
keystone_extra_volumes: "{{ default_extra_volumes }}"
keystone_httpd_extra_volumes: "{{ keystone_extra_volumes }}"
####################
# OpenStack
@ -266,3 +299,4 @@ keystone_copy_certs: "{{ kolla_copy_ca_into_containers | bool or keystone_enable
# WSGI
############
keystone_wsgi_provider: "uwsgi"
keystone_wsgi_socket_port: "5001"

View file

@ -68,6 +68,20 @@
dimensions: "{{ service.dimensions }}"
healthcheck: "{{ service.healthcheck | default(omit) }}"
- name: Restart keystone-httpd container
vars:
service_name: "keystone-httpd"
service: "{{ keystone_services[service_name] }}"
become: true
kolla_container:
action: "recreate_or_restart_container"
common_options: "{{ docker_common_options }}"
name: "{{ service.container_name }}"
image: "{{ service.image }}"
volumes: "{{ service.volumes | reject('equalto', '') | list }}"
dimensions: "{{ service.dimensions }}"
healthcheck: "{{ service.healthcheck | default(omit) }}"
- name: Finish keystone database upgrade
vars:
service_name: "keystone"

View file

@ -147,9 +147,14 @@
project_services: "{{ keystone_services }}"
service: "{{ keystone_services['keystone'] }}"
service_name: "keystone"
service_uwsgi_config_host: >-
{{ '127.0.0.1' if enable_keystone_federation | bool
else api_interface_address | put_address_in_context('url') }}
service_uwsgi_config_http_port: "{{ keystone_listen_port }}"
service_uwsgi_config_module: "{{ service.wsgi }}"
service_uwsgi_config_tls_backend: "{{ keystone_enable_tls_backend | bool }}"
service_uwsgi_config_socket_port: "{{ keystone_wsgi_socket_port if enable_keystone_federation | bool else '' }}"
service_uwsgi_config_tls_backend: >-
{{ keystone_enable_tls_backend | bool and (not enable_keystone_federation | bool) }}
service_uwsgi_config_tls_cert: "/etc/keystone/certs/keystone-cert.pem"
service_uwsgi_config_tls_key: "/etc/keystone/certs/keystone-key.pem"
service_uwsgi_config_uid: "keystone"
@ -157,6 +162,22 @@
- service | service_enabled_and_mapped_to_host
- keystone_wsgi_provider == "uwsgi"
- name: Copying over httpd-keystone.conf
vars:
service: "{{ keystone_services['keystone-httpd'] }}"
template:
src: "{{ item }}"
dest: "{{ node_config_directory }}/keystone-httpd/httpd-keystone.conf"
mode: "0660"
become: true
when:
- service | service_enabled_and_mapped_to_host
- keystone_wsgi_provider == "uwsgi"
with_first_found:
- "{{ node_custom_config }}/keystone/{{ inventory_hostname }}/httpd-keystone.conf"
- "{{ node_custom_config }}/keystone/httpd-keystone.conf"
- "httpd-keystone.conf.j2"
- name: Checking whether keystone-paste.ini file exists
vars:
service: "{{ keystone_services['keystone'] }}"

View file

@ -0,0 +1,113 @@
{% set keystone_log_dir = '/var/log/kolla/keystone' %}
{% set binary_path = '/var/lib/kolla/venv/bin' %}
{% if keystone_enable_tls_backend | bool %}
{% if kolla_base_distro in ['centos', 'rocky'] %}
LoadModule ssl_module /usr/lib64/httpd/modules/mod_ssl.so
{% else %}
LoadModule ssl_module /usr/lib/apache2/modules/mod_ssl.so
{% endif %}
{% endif %}
{% if kolla_base_distro in ['centos', 'rocky'] %}
LoadModule proxy_module /usr/lib64/httpd/modules/mod_proxy.so
LoadModule proxy_uwsgi_module /usr/lib64/httpd/modules/mod_proxy_uwsgi.so
{% else %}
LoadModule proxy_module /usr/lib/apache2/modules/mod_proxy.so
LoadModule proxy_uwsgi_module /usr/lib/apache2/modules/mod_proxy_uwsgi.so
{% endif %}
Listen {{ api_interface_address | put_address_in_context('url') }}:{{ keystone_public_listen_port }}
ServerSignature Off
ServerTokens Prod
TraceEnable off
TimeOut {{ kolla_httpd_timeout }}
KeepAliveTimeout {{ kolla_httpd_keep_alive }}
ErrorLog "{{ keystone_log_dir }}/apache-error.log"
<IfModule log_config_module>
CustomLog "{{ keystone_log_dir }}/apache-access.log" common
</IfModule>
{% if keystone_logging_debug | bool %}
LogLevel info
{% endif %}
<VirtualHost *:{{ keystone_public_listen_port }}>
{# NOTE(darmach): with external tls enabled OIDC redirection fails, as TLS terminated on haproxy keystone is not aware that redirection should use https. -#}
{# With missing ServerName Keystone Apache uses fqdn, with http. Adding ServerName pointing to keystone_public_url corrects this. -#}
{% if kolla_enable_tls_external | bool %}
ServerName {{ keystone_public_url }}
{% endif %}
ErrorLogFormat "%{cu}t %M"
ErrorLog "{{ keystone_log_dir }}/keystone-apache-public-error.log"
LogFormat "%{X-Forwarded-For}i %l %u %t \"%r\" %>s %b %D \"%{Referer}i\" \"%{User-Agent}i\"" logformat
CustomLog "{{ keystone_log_dir }}/keystone-apache-public-access.log" logformat
ProxyPass / "uwsgi://localhost:{{ keystone_wsgi_socket_port }}/"
{% if keystone_enable_tls_backend | bool %}
SSLEngine on
SSLCertificateFile /etc/keystone/certs/keystone-cert.pem
SSLCertificateKeyFile /etc/keystone/certs/keystone-key.pem
{% endif -%}
{% if keystone_enable_federation_openid | bool %}
{% if keystone_federation_oidc_forwarded_headers | length > 0 %}
OIDCXForwardedHeaders "{{ keystone_federation_oidc_forwarded_headers }}"
{% endif %}
OIDCClaimPrefix "OIDC-"
OIDCClaimDelimiter "{{ keystone_federation_oidc_claim_delimiter }}"
OIDCResponseType "{{ keystone_federation_oidc_response_type }}"
OIDCScope "{{ keystone_federation_oidc_scopes }}"
OIDCMetadataDir {{ keystone_container_federation_oidc_metadata_folder }}
{% if keystone_federation_oidc_jwks_uri | length > 0 %}
OIDCOAuthVerifyJwksUri {{ keystone_federation_oidc_jwks_uri }}
{% endif %}
{% if keystone_federation_openid_certificate_key_ids | length > 0 %}
OIDCOAuthVerifyCertFiles {{ keystone_federation_openid_certificate_key_ids | join(" ") }}
{% endif %}
OIDCCryptoPassphrase {{ keystone_federation_openid_crypto_password }}
OIDCRedirectURI {{ keystone_public_url }}/redirect_uri
{% if enable_memcached | bool and keystone_oidc_enable_memcached | bool %}
OIDCCacheType memcache
OIDCMemCacheServers "{% for host in groups['memcached'] %}{{ 'api' | kolla_address(host) | put_address_in_context('memcache') }}:{{ memcached_port }}{% if not loop.last %} {% endif %}{% endfor %}"
{% endif %}
{% for key, value in keystone_federation_oidc_additional_options.items() %}
{{ key }} {{ value }}
{% endfor %}
<Location ~ "/redirect_uri">
Require valid-user
AuthType openid-connect
</Location>
{# WebSSO authentication endpoint -#}
<Location /v3/auth/OS-FEDERATION/websso/openid>
Require valid-user
AuthType openid-connect
</Location>
{% for idp in keystone_identity_providers %}
{% if idp.protocol == 'openid' %}
<LocationMatch /v3/auth/OS-FEDERATION/identity_providers/{{ idp.name }}/protocols/{{ idp.protocol }}/websso>
OIDCDiscoverURL {{ keystone_public_url }}/redirect_uri?iss={{ idp.identifier | urlencode }}
Require valid-user
AuthType openid-connect
</LocationMatch>
{% endif %}
{% endfor %}
{# CLI / API authentication endpoint -#}
{% for idp in keystone_identity_providers %}
{% if idp.protocol == 'openid' -%}
<LocationMatch /v3/OS-FEDERATION/identity_providers/{{ idp.name }}/protocols/{{ idp.protocol }}/auth>
Require valid-user
{# Note(jasonanderson): `auth-openidc` is a special auth type that can -#}
{# additionally handle verifying bearer tokens -#}
AuthType auth-openidc
</LocationMatch>
{% endif %}
{% endfor %}
{% endif %}
</VirtualHost>

View file

@ -0,0 +1,63 @@
{% set apache_cmd = '/usr/sbin/apache2' if kolla_base_distro in ['ubuntu', 'debian'] else '/usr/sbin/httpd' %}
{% set apache_dir = 'apache2/conf-enabled' if kolla_base_distro in ['ubuntu', 'debian'] else 'httpd/conf.d' %}
{% set apache_user = 'www-data' if kolla_base_distro in ['ubuntu', 'debian'] else 'apache' %}
{
"command": "{{ apache_cmd }} -DFOREGROUND",
"config_files": [
{
"source": "{{ container_config_directory }}/httpd-keystone.conf",
"dest": "/etc/{{ apache_dir }}/httpd-keystone.conf",
"owner": "root",
"perm": "0600"
}{% if keystone_enable_tls_backend | bool %},
{
"source": "{{ container_config_directory }}/keystone-cert.pem",
"dest": "/etc/keystone/certs/keystone-cert.pem",
"owner": "keystone",
"perm": "0600"
},
{
"source": "{{ container_config_directory }}/keystone-key.pem",
"dest": "/etc/keystone/certs/keystone-key.pem",
"owner": "keystone",
"perm": "0600"
}{% endif %}{% if keystone_enable_federation_openid | bool %},
{
"source": "{{ container_config_directory }}/federation/oidc/metadata",
"dest": "{{ keystone_container_federation_oidc_metadata_folder }}",
"owner": "{{ apache_user }}:{{ apache_user }}",
"perm": "0600",
"merge": true
},
{
"source": "{{ container_config_directory }}/federation/oidc/cert",
"dest": "{{ keystone_container_federation_oidc_idp_certificate_folder }}",
"owner": "{{ apache_user }}:{{ apache_user }}",
"perm": "0600",
"merge": true
}{% endif %}{% if kolla_copy_ca_into_containers | bool %},
{
"source": "{{ container_config_directory }}/ca-certificates",
"dest": "/var/lib/kolla/share/ca-certificates",
"owner": "root",
"perm": "0600"
}{% endif %}
],
"permissions": [
{
"path": "/var/log/kolla/keystone",
"owner": "keystone:kolla"
}{% if keystone_enable_federation_openid | bool %},
{
"path": "{{ keystone_container_federation_oidc_metadata_folder }}",
"owner": "{{ apache_user }}:{{ apache_user }}",
"perm": "0700"
},
{
"path": "{{ keystone_container_federation_oidc_idp_certificate_folder }}",
"owner": "{{ apache_user }}:{{ apache_user }}",
"perm": "0700"
}{% endif %}
]
}

View file

@ -3,6 +3,7 @@ service_uwsgi_config_host: "{{ api_interface_address | put_address_in_context('u
service_uwsgi_config_file: "{{ node_config_directory }}/{{ service_name }}/{{ service_name }}-uwsgi.ini"
service_uwsgi_config_log_dir: "{{ ansible_parent_role_names | first }}"
service_uwsgi_config_log_file: "{{ service_name }}-uwsgi.log"
service_uwsgi_config_socket_port: ""
service_uwsgi_config_tls_backend: false
service_uwsgi_config_worker_timeout: 80
service_uwsgi_config_workers: "{{ openstack_service_workers }}"

View file

@ -30,6 +30,9 @@ wsgi-file = {{ service_uwsgi_config_wsgi_file }}
plugins-dir = {{ '/usr/lib/uwsgi/plugins' if kolla_base_distro in ['ubuntu', 'debian'] else '/usr/lib64/uwsgi' }}
plugins = python3
processes = {{ service_uwsgi_config_workers }}
{% if service_uwsgi_config_socket_port | length > 0 %}
socket = {{ service_uwsgi_config_host }}:{{ service_uwsgi_config_socket_port }}
{% endif %}
socket-timeout = 30
thunder-lock = true
{% if service_uwsgi_config_uid is defined %}

View file

@ -298,5 +298,9 @@ enable_gnocchi: "yes"
enable_valkey: "yes"
{% endif %}
{% if scenario == "federation" %}
enable_keystone_federation: true
{% endif %}
mariadb_monitor_read_only_interval: "30000"
mariadb_monitor_galera_healthcheck_timeout: "30000"

View file

@ -11,6 +11,7 @@
# NOTE(mnasiadka): Failing since
# https://review.opendev.org/c/openstack/kolla-ansible/+/864780
# - kolla-ansible-scenario-container-engine-migration
- kolla-ansible-scenario-federation
- kolla-ansible-scenario-haproxy-fqdn
- kolla-ansible-scenario-kayobe
- kolla-ansible-scenario-openbao

View file

@ -0,0 +1,37 @@
---
- job:
name: kolla-ansible-federation-base
parent: kolla-ansible-base
voting: false
files: !inherit
- ^ansible/group_vars/all/keystone.yml
- ^ansible/roles/keystone/
vars:
scenario: federation
scenario_images_extra:
- ^httpd
- job:
name: kolla-ansible-debian-bookworm-federation
parent: kolla-ansible-federation-base
nodeset: kolla-ansible-debian-bookworm-multi-8GB
- job:
name: kolla-ansible-rocky-10-federation
parent: kolla-ansible-federation-base
nodeset: kolla-ansible-rocky-10-multi-8GB
- job:
name: kolla-ansible-ubuntu-noble-federation
parent: kolla-ansible-federation-base
nodeset: kolla-ansible-ubuntu-noble-multi-8GB
- project-template:
name: kolla-ansible-scenario-federation
description: |
Runs Kolla-Ansible Keystone federation scenario jobs.
check:
jobs:
- kolla-ansible-debian-bookworm-federation
- kolla-ansible-rocky-10-federation
- kolla-ansible-ubuntu-noble-federation