Add support for encrypting Ironic API

This patch introduces an optional backend encryption for the Ironic API
service. When used in conjunction with enabling TLS for service API
endpoints, network communcation will be encrypted end to end, from
client through HAProxy to the Ironic service.

Change-Id: I9edf7545c174ca8839ceaef877bb09f49ef2b451
Partially-Implements: blueprint add-ssl-internal-network
This commit is contained in:
James Kirsch 2020-09-11 14:12:44 -07:00
parent 3d30624cc1
commit 7c2df87ded
9 changed files with 109 additions and 11 deletions

View File

@ -16,12 +16,14 @@ ironic_services:
external: false
port: "{{ ironic_api_port }}"
listen_port: "{{ ironic_api_listen_port }}"
tls_backend: "{{ ironic_enable_tls_backend }}"
ironic_api_external:
enabled: "{{ enable_ironic }}"
mode: "http"
external: true
port: "{{ ironic_api_port }}"
listen_port: "{{ ironic_api_listen_port }}"
tls_backend: "{{ ironic_enable_tls_backend }}"
ironic-conductor:
container_name: ironic_conductor
group: ironic-conductor
@ -253,3 +255,8 @@ ironic_ks_users:
user: "{{ ironic_inspector_keystone_user }}"
password: "{{ ironic_inspector_keystone_password }}"
role: "admin"
####################
# TLS
####################
ironic_enable_tls_backend: "{{ kolla_enable_tls_backend }}"

View File

@ -40,6 +40,7 @@
module_name: uri
module_args:
url: "{{ ironic_internal_endpoint }}"
validate_certs: false
register: result
until: result is success
retries: 12

View File

@ -33,7 +33,7 @@
- include_tasks: copy-certs.yml
when:
- kolla_copy_ca_into_containers | bool
- kolla_copy_ca_into_containers | bool or ironic_enable_tls_backend | bool
- name: Copying over config.json files for services
template:
@ -244,5 +244,17 @@
notify:
- "Restart {{ item.key }} container"
- name: Copying over ironic-api-wsgi.conf
template:
src: "ironic-api-wsgi.conf.j2"
dest: "{{ node_config_directory }}/ironic-api/ironic-api-wsgi.conf"
mode: "0660"
become: true
when:
- inventory_hostname in groups["ironic-api"]
- ironic_services["ironic-api"].enabled | bool
notify:
- "Restart ironic-api container"
- import_tasks: check-containers.yml
when: kolla_action != "config"

View File

@ -0,0 +1,50 @@
{% set ironic_log_dir = '/var/log/kolla/ironic' %}
{% set wsgi_directory = '/usr/bin' if ironic_install_type == 'binary' else '/var/lib/kolla/venv/bin' %}
{% if ironic_enable_tls_backend | bool %}
{% if kolla_base_distro in ['centos'] %}
LoadModule ssl_module /usr/lib64/httpd/modules/mod_ssl.so
{% else %}
LoadModule ssl_module /usr/lib/apache2/modules/mod_ssl.so
{% endif %}
{% endif %}
Listen {{ api_interface_address | put_address_in_context('url') }}:{{ ironic_api_listen_port }}
ServerSignature Off
ServerTokens Prod
TraceEnable off
KeepAliveTimeout {{ kolla_httpd_keep_alive }}
<Directory "{{ wsgi_directory }}">
<FilesMatch "^ironic-api-wsgi$">
Options None
Require all granted
</FilesMatch>
</Directory>
ErrorLog "{{ ironic_log_dir }}/apache-error.log"
<IfModule log_config_module>
CustomLog "{{ ironic_log_dir }}/apache-access.log" common
</IfModule>
{% if ironic_logging_debug | bool %}
LogLevel info
{% endif %}
<VirtualHost *:{{ ironic_api_listen_port }}>
WSGIDaemonProcess ironic-api processes={{ openstack_service_workers }} threads=1 user=ironic group=ironic display-name=%{GROUP}
WSGIProcessGroup ironic-api
WSGIScriptAlias / {{ wsgi_directory }}/ironic-api-wsgi
WSGIApplicationGroup %{GLOBAL}
WSGIPassAuthorization On
<IfVersion >= 2.4>
ErrorLogFormat "%{cu}t %M"
</IfVersion>
ErrorLog "{{ ironic_log_dir }}/ironic-api-error.log"
LogFormat "%{X-Forwarded-For}i %l %u %t \"%r\" %>s %b %D \"%{Referer}i\" \"%{User-Agent}i\"" logformat
CustomLog "{{ ironic_log_dir }}/ironic-api-access.log" logformat
{% if ironic_enable_tls_backend | bool %}
SSLEngine on
SSLCertificateFile /etc/ironic/certs/ironic-cert.pem
SSLCertificateKeyFile /etc/ironic/certs/ironic-key.pem
{% endif %}
</VirtualHost>

View File

@ -1,17 +1,37 @@
{% set apache_binary = 'apache2' if kolla_base_distro in ['ubuntu', 'debian'] else 'httpd' %}
{% set apache_conf_dir = 'apache2/conf-enabled' if kolla_base_distro in ['ubuntu', 'debian'] else 'httpd/conf.d' %}
{
"command": "ironic-api",
"command": "/usr/sbin/{{ apache_binary }} -DFOREGROUND",
"config_files": [
{
"source": "{{ container_config_directory }}/ironic.conf",
"dest": "/etc/ironic/ironic.conf",
"owner": "ironic",
"perm": "0600"
},
{
"source": "{{ container_config_directory }}/ironic-api-wsgi.conf",
"dest": "/etc/{{ apache_conf_dir }}/ironic-api-wsgi.conf",
"owner": "ironic",
"perm": "0600"
}{% if ironic_policy_file is defined %},
{
"source": "{{ container_config_directory }}/{{ ironic_policy_file }}",
"dest": "/etc/ironic/{{ ironic_policy_file }}",
"owner": "ironic",
"perm": "0600"
}{% endif %}{% if ironic_enable_tls_backend | bool %},
{
"source": "{{ container_config_directory }}/ironic-cert.pem",
"dest": "/etc/ironic/certs/ironic-cert.pem",
"owner": "ironic",
"perm": "0600"
},
{
"source": "{{ container_config_directory }}/ironic-key.pem",
"dest": "/etc/ironic/certs/ironic-key.pem",
"owner": "ironic",
"perm": "0600"
}{% endif %}
],
"permissions": [

View File

@ -35,13 +35,6 @@ driver = noop
policy_file = {{ ironic_policy_file }}
{% endif %}
{% if service_name == 'ironic-api' %}
[api]
host_ip = {{ api_interface_address }}
port = {{ ironic_api_listen_port }}
api_workers = {{ openstack_service_workers }}
{% endif %}
{% if service_name == 'ironic-conductor' %}
[conductor]
automated_clean=false

View File

@ -0,0 +1,7 @@
---
features:
- |
Adds configuration options to enable backend TLS encryption from HAProxy
to the Nova and Ironic services. When used in conjunction with enabling TLS
for service API endpoints, network communcation will be encrypted end to
end, from client through HAProxy to the backend service.

View File

@ -383,6 +383,8 @@
cmd: test-ironic.sh
executable: /bin/bash
chdir: "{{ kolla_ansible_src_dir }}"
environment:
TLS_ENABLED: "{{ tls_enabled }}"
when: scenario == "ironic"
- name: Run test-masakari.sh script

View File

@ -35,7 +35,13 @@ function wait_for_placement_resources {
for i in $(seq 1 120); do
# Fetch provider UUIDs from Placement
local providers
providers=$(curl -sH "X-Auth-Token: $token" $endpoint/resource_providers \
args=(
-sH "X-Auth-Token: $token"
)
if [[ "$TLS_ENABLED" = "True" ]]; then
args+=(--cacert $OS_CACERT)
fi
providers=$(curl "${args[@]}" $endpoint/resource_providers \
| ./jq -r '.resource_providers[].uuid')
local p
@ -46,7 +52,7 @@ function wait_for_placement_resources {
# A resource class inventory record looks something like
# {"max_unit": 1, "min_unit": 1, "step_size": 1, "reserved": 0, "total": 1, "allocation_ratio": 1}
# Subtract reserved from total (defaulting both to 0)
amount=$(curl -sH "X-Auth-Token: $token" $endpoint/resource_providers/$p/inventories \
amount=$(curl "${args[@]}" $endpoint/resource_providers/$p/inventories \
| ./jq ".inventories.CUSTOM_$resource_class as \$cls
| (\$cls.total // 0) - (\$cls.reserved // 0)")
if [ $amount -gt 0 ]; then