Skip to content

Commit

Permalink
Keystone SSL cert/key distribution and configuration
Browse files Browse the repository at this point in the history
This patch adds the option to provide an SSL certificate for the
Keystone service (either self-signed or user provided) and to
configure the endpoints and Keystone service appropriately.

* A new boolean variable called 'keystone_ssl' enables/disables
  the configuration of SSL for the Keystone service.

* The server key/certificate (and optionally a CA cert) are
  distributed to all keystone containers and used for the setup
  of SSL endpoints if the appropriate protocol is set.

* The internal/public and the admin endpoints can be set to be
  served via http or https seperately via the
  'keystone_service_*_proto' variables.

* The logic to determine the appropriate load balancing
  configuration based on the Keystone endpoint protocol has
  been implemented in the haproxy vars.

* Two new variables have been implemented for a user-provided
  server key and certificate:
  - keystone_user_ssl_cert: <path to cert on deployment host>
  - keystone_user_ssl_key: <path to cert on deployment host>
  If either of these is not defined, but a Keystone endpoint
  has been configured for SSL, then the missing cert/key
  will be self generated on the first Keystone container and
  distributed to the other containers.

* A new variable has been implemented for a user-provided CA
  certificate:
  - keystone_user_ssl_ca_cert: <path to cert on deployment host>

* A new variable called 'keystone_ssl_self_signed_subject' has
  been implemented to allow the user to override the certificate
  properties, such as the CN and subjectAltName.

Upgrade notes:

* The SSL-based client authentication configuration in Apache
  has been removed as it appears to be unused.

* The minimum Ansible version for the os_keystone and
  haproxy_server roles have been increased to v1.9.0 as it's
  the minimum version that supports ternary filters.

* The boolean 'keystone_ssl_enabled' has been renamed to
  'keystone_ssl'. This maintains a pattern set in the haproxy
  role for enablement of ssl offloading in the load balancer.

* The Apache configuration appropriately implements the
  'SSLCACertificateFile' instead of the 'SSLCACertificatePath'
  directive in order to ensure that the appropriate signing
  certificate is provided to the browser.

* The 'keystone_self_signed_regen' variable has been renamed
  to 'keystone_ssl_self_signed_regen'.

* The default names for the deployed keys/certificates have been
  changed:
  - /etc/ssl/certs/apache.cert  > /etc/ssl/certs/keystone.pem
  - /etc/ssl/private/apache.key > /etc/ssl/private/keystone.key

DocImpact
Partial-Bug: #1466827
Implements: blueprint keystone-federation
Change-Id: I4c5ea7b6bfc3d7d7230a7440fa501241826c9dee
Co-Authored-By: Miguel Grinberg <miguelgrinberg50@gmail.com>
(cherry picked from commit 4b35b3e)
  • Loading branch information
Jesse Pretorius committed Aug 20, 2015
1 parent 33a4f2c commit caa9733
Show file tree
Hide file tree
Showing 14 changed files with 247 additions and 34 deletions.
10 changes: 5 additions & 5 deletions playbooks/haproxy-install.yml
Expand Up @@ -31,6 +31,8 @@
- name: Add keystone internal endpoint config
include: roles/haproxy_server/tasks/haproxy_service_config.yml
when: internal_lb_vip_address != external_lb_vip_address
vars_files:
- vars/configs/haproxy_config.yml
vars:
haproxy_service_configs:
- service:
Expand All @@ -39,11 +41,9 @@
haproxy_bind: "{{ internal_lb_vip_address }}"
haproxy_port: 5000
haproxy_ssl: "{% if haproxy_ssl | bool and keystone_service_internaluri_proto == 'https' %}true{% else %}false{% endif %}"
haproxy_balance_type: http
haproxy_backend_options:
- "forwardfor"
- "httpchk"
- "httplog"
haproxy_balance_type: "{{ (keystone_ssl_internal | bool) | ternary('tcp','http') }}"
haproxy_balance_alg: "{{ (keystone_ssl_internal | bool) | ternary('source', 'leastconn') }}"
haproxy_backend_options: "{{ (keystone_ssl_internal | bool) | ternary(haproxy_backend_options_https, haproxy_backend_options_http) }}"
tags:
- haproxy-service-config
roles:
Expand Down
4 changes: 2 additions & 2 deletions playbooks/roles/haproxy_server/meta/main.yml
Expand Up @@ -15,10 +15,10 @@

galaxy_info:
author: rcbops
description: Installation and setup of HAPtoxy
description: Installation and setup of HAProxy
company: Rackspace
license: Apache2
min_ansible_version: 1.6.6
min_ansible_version: 1.9.0
platforms:
- name: Ubuntu
versions:
Expand Down
19 changes: 14 additions & 5 deletions playbooks/roles/os_keystone/defaults/main.yml
Expand Up @@ -129,14 +129,23 @@ keystone_apache_serversignature: "Off"
keystone_wsgi_threads: "{{ ansible_processor_vcpus | default(2) // 2 }}"
keystone_wsgi_processes: "{{ ansible_processor_vcpus | default(1) }}"

keystone_ssl_enabled: false
keystone_ssl_cert_path: /etc/ssl/certs
keystone_ssl_cert: "{{ keystone_ssl_cert_path }}/apache.cert"
keystone_ssl_key_path: /etc/ssl/private
keystone_ssl_key: "{{ keystone_ssl_key_path }}/apache.key"
# set keystone_ssl to true to enable SSL configuration on the keystone containers
keystone_ssl: false
keystone_ssl_cert: /etc/ssl/certs/keystone.pem
keystone_ssl_key: /etc/ssl/private/keystone.key
keystone_ssl_ca_cert: /etc/ssl/certs/keystone-ca.pem
keystone_ssl_protocol: "{{ ssl_protocol }}"
keystone_ssl_cipher_suite: "{{ ssl_cipher_suite }}"

# if using a self-signed certificate, set this to true to regenerate it
keystone_ssl_self_signed_regen: false
keystone_ssl_self_signed_subject: "/C=US/ST=Texas/L=San Antonio/O=IT/CN={{ internal_lb_vip_address }}/subjectAltName=IP.1={{ external_lb_vip_address }}"

# Set these in user_variables to deploy custom certificates
#keystone_user_ssl_cert: <path to cert on ansible deployment host>
#keystone_user_ssl_key: <path to cert on ansible deployment host>
#keystone_user_ssl_ca_cert: <path to cert on ansible deployment host>

## Caching
# If set this will enable dog pile cache for keystone.
# keystone_cache_backend_argument: url:127.0.0.1:11211
Expand Down
3 changes: 2 additions & 1 deletion playbooks/roles/os_keystone/tasks/keystone_apache.yml
Expand Up @@ -80,11 +80,12 @@
- name: Enable/disable mod_ssl for apache2
apache2_module:
name: ssl
state: "{{ (keystone_ssl_enabled | bool) | ternary('present', 'absent') }}"
state: "{{ (keystone_ssl | bool) | ternary('present', 'absent') }}"
notify:
- Restart Apache
tags:
- keystone-httpd
- keystone-ssl

- name: Enable/disable mod_shib2 for apache2
apache2_module:
Expand Down
25 changes: 25 additions & 0 deletions playbooks/roles/os_keystone/tasks/keystone_ssl.yml
@@ -0,0 +1,25 @@
---
# Copyright 2015, Rackspace US, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

- include: keystone_ssl_self_signed.yml
when: >
keystone_ssl | bool and
(keystone_user_ssl_cert is not defined or keystone_user_ssl_key is not defined)
tags:
- keystone-ssl

- include: keystone_ssl_user_provided.yml
tags:
- keystone-ssl
36 changes: 36 additions & 0 deletions playbooks/roles/os_keystone/tasks/keystone_ssl_key_create.yml
@@ -0,0 +1,36 @@
---
# Copyright 2015, Rackspace US, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

- name: Remove self signed cert for regen
file:
dest: "{{ keystone_ssl_cert }}"
state: "absent"
when: keystone_ssl_self_signed_regen | bool
tags:
- keystone-ssl

- name: Create self-signed Apache ssl cert
command: >
openssl req -new -nodes -sha256 -x509 -subj
"{{ keystone_ssl_self_signed_subject }}"
-days 3650
-keyout {{ keystone_ssl_key }}
-out {{ keystone_ssl_cert }}
-extensions v3_ca
creates={{ keystone_ssl_cert }}
notify: Restart Apache
tags:
- keystone-configs
- keystone-ssl
35 changes: 35 additions & 0 deletions playbooks/roles/os_keystone/tasks/keystone_ssl_key_distribute.yml
@@ -0,0 +1,35 @@
---
# Copyright 2014, Rackspace US, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

- name: Distribute self signed cert and key
memcached:
name: "{{ item.name }}"
file_path: "{{ item.src }}"
state: "retrieve"
file_mode: "{{ item.file_mode }}"
dir_mode: "{{ item.dir_mode }}"
server: "{{ memcached_servers }}"
encrypt_string: "{{ memcached_encryption_key }}"
with_items:
- { src: "{{ keystone_ssl_cert }}", name: "keystone_ssl_cert", file_mode: "0644", dir_mode: "0755" }
- { src: "{{ keystone_ssl_key }}", name: "keystone_ssl_key", file_mode: "0640", dir_mode: "0750" }
register: memcache_keys
until: memcache_keys|success
retries: 5
delay: 2
notify: Restart Apache
tags:
- keystone-config
- keystone-ssl
31 changes: 31 additions & 0 deletions playbooks/roles/os_keystone/tasks/keystone_ssl_key_store.yml
@@ -0,0 +1,31 @@
---
# Copyright 2015, Rackspace US, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

- name: Store self signed cert and key
memcached:
name: "{{ item.name }}"
file_path: "{{ item.src }}"
state: "present"
server: "{{ memcached_servers }}"
encrypt_string: "{{ memcached_encryption_key }}"
with_items:
- { src: "{{ keystone_ssl_cert }}", name: "keystone_ssl_cert" }
- { src: "{{ keystone_ssl_key }}", name: "keystone_ssl_key" }
register: memcache_keys
until: memcache_keys|success
retries: 5
delay: 2
tags:
- keystone-ssl
26 changes: 26 additions & 0 deletions playbooks/roles/os_keystone/tasks/keystone_ssl_self_signed.yml
@@ -0,0 +1,26 @@
---
# Copyright 2015, Rackspace US, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

- include: keystone_ssl_key_create.yml
when: >
inventory_hostname == groups['keystone_all'][0]
- include: keystone_ssl_key_store.yml
when: >
inventory_hostname == groups['keystone_all'][0]
- include: keystone_ssl_key_distribute.yml
when: >
inventory_hostname != groups['keystone_all'][0]
43 changes: 43 additions & 0 deletions playbooks/roles/os_keystone/tasks/keystone_ssl_user_provided.yml
@@ -0,0 +1,43 @@
---
# Copyright 2015, Rackspace US, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

- name: Drop user provided ssl cert and key
copy:
src: "{{ item.src }}"
dest: "{{ item.dest }}"
owner: "root"
group: "root"
mode: "{{ item.mode }}"
with_items:
- { src: "{{ keystone_user_ssl_cert }}", dest: "{{ keystone_ssl_cert }}", mode: "0644" }
- { src: "{{ keystone_user_ssl_key }}", dest: "{{ keystone_ssl_key }}", mode: "0640" }
when: keystone_user_ssl_cert is defined and keystone_user_ssl_key is defined
notify: Restart Apache
tags:
- keystone-configs
- keystone-ssl

- name: Drop user provided ssl CA cert
copy:
src: "{{ keystone_user_ssl_ca_cert }}"
dest: "{{ keystone_ssl_ca_cert }}"
owner: "root"
group: "root"
mode: "0644"
when: keystone_user_ssl_ca_cert is defined
notify: Restart Apache
tags:
- keystone-configs
- keystone-ssl
1 change: 1 addition & 0 deletions playbooks/roles/os_keystone/tasks/main.yml
Expand Up @@ -37,6 +37,7 @@
when: >
inventory_hostname == groups['keystone_all'][0]
- include: keystone_ssl.yml
- include: keystone_apache.yml
- include: keystone_token_cleanup.yml

Expand Down
18 changes: 8 additions & 10 deletions playbooks/roles/os_keystone/templates/keystone-httpd.conf.j2
Expand Up @@ -16,14 +16,13 @@
CustomLog /var/log/keystone/ssl_access.log combined
Options +FollowSymLinks

{% if keystone_ssl_enabled == true -%}
{% if keystone_ssl | bool and keystone_service_internaluri_proto == "https" -%}
SSLEngine on
SSLCertificateFile {{ keystone_ssl_cert }}
SSLCertificateKeyFile {{ keystone_ssl_key }}
SSLCACertificatePath {{ keystone_ssl_cert_path }}
SSLCARevocationPath {{ keystone_ssl_cert_path }}
SSLVerifyClient optional
SSLVerifyDepth 10
{% if keystone_user_ssl_ca_cert is defined -%}
SSLCACertificateFile {{ keystone_ssl_ca_cert }}
{% endif -%}
SSLCompression Off
SSLProtocol {{ keystone_ssl_protocol }}
SSLHonorCipherOrder On
Expand Down Expand Up @@ -74,14 +73,13 @@
CustomLog /var/log/keystone/ssl_access.log combined
Options +FollowSymLinks

{% if keystone_ssl_enabled == true -%}
{% if keystone_ssl | bool and keystone_service_adminuri_proto == "https" -%}
SSLEngine on
SSLCertificateFile {{ keystone_ssl_cert }}
SSLCertificateKeyFile {{ keystone_ssl_key }}
SSLCACertificatePath {{ keystone_ssl_cert_path }}
SSLCARevocationPath {{ keystone_ssl_cert_path }}
SSLVerifyClient optional
SSLVerifyDepth 10
{% if keystone_user_ssl_ca_cert is defined -%}
SSLCACertificateFile {{ keystone_ssl_ca_cert }}
{% endif -%}
SSLCompression Off
SSLProtocol {{ keystone_ssl_protocol }}
SSLHonorCipherOrder On
Expand Down
2 changes: 1 addition & 1 deletion playbooks/roles/os_keystone/templates/keystone.conf.j2
Expand Up @@ -10,7 +10,7 @@ public_endpoint = {{ keystone_public_endpoint }}
admin_endpoint = {{ keystone_service_adminuri }}
fatal_deprecations = {{ keystone_fatal_deprecations }}

{% if keystone_ssl_enabled == true and keystone_secure_proxy_ssl_header is defined %}
{% if keystone_ssl | bool and keystone_secure_proxy_ssl_header is defined %}
secure_proxy_ssl_header = {{ keystone_secure_proxy_ssl_header }}
{% endif %}

Expand Down
28 changes: 18 additions & 10 deletions playbooks/vars/configs/haproxy_config.yml
Expand Up @@ -12,6 +12,18 @@
# See the License for the specific language governing permissions and
# limitations under the License.

haproxy_backend_options_http:
- "forwardfor"
- "httpchk"
- "httplog"

haproxy_backend_options_https:
- "ssl-hello-chk"

keystone_ssl_admin: "{% if keystone_ssl is defined and keystone_ssl | bool and keystone_service_adminuri_proto == 'https' %}true{% else %}false{% endif %}"
keystone_ssl_internal: "{% if keystone_ssl is defined and keystone_ssl | bool and keystone_service_internaluri_proto == 'https' %}true{% else %}false{% endif %}"
keystone_ssl_public: "{% if keystone_ssl is defined and keystone_ssl | bool and keystone_service_publicuri_proto == 'https' %}true{% else %}false{% endif %}"

haproxy_service_configs:
- service:
haproxy_service_name: galera
Expand Down Expand Up @@ -69,22 +81,18 @@ haproxy_service_configs:
haproxy_backend_nodes: "{{ groups['keystone_all'] }}"
haproxy_port: 35357
haproxy_ssl: "{% if haproxy_ssl | bool and keystone_service_adminuri_proto == 'https' %}true{% else %}false{% endif %}"
haproxy_balance_type: http
haproxy_backend_options:
- "forwardfor"
- "httpchk"
- "httplog"
haproxy_balance_type: "{{ (keystone_ssl_admin | bool) | ternary('tcp', 'http') }}"
haproxy_balance_alg: "{{ (keystone_ssl_admin | bool) | ternary('source', 'leastconn') }}"
haproxy_backend_options: "{{ (keystone_ssl_admin | bool) | ternary(haproxy_backend_options_https, haproxy_backend_options_http) }}"
- service:
haproxy_service_name: keystone_service
haproxy_backend_nodes: "{{ groups['keystone_all'] }}"
haproxy_bind: "{% if internal_lb_vip_address == external_lb_vip_address %}*{% else %}{{ external_lb_vip_address }}{% endif %}"
haproxy_port: 5000
haproxy_ssl: "{% if haproxy_ssl | bool and keystone_service_publicuri_proto == 'https' %}true{% else %}false{% endif %}"
haproxy_balance_type: http
haproxy_backend_options:
- "forwardfor"
- "httpchk"
- "httplog"
haproxy_balance_type: "{{ (keystone_ssl_public | bool) | ternary('tcp','http') }}"
haproxy_balance_alg: "{{ (keystone_ssl_public | bool) | ternary('source', 'leastconn') }}"
haproxy_backend_options: "{{ (keystone_ssl_public | bool) | ternary(haproxy_backend_options_https, haproxy_backend_options_http) }}"
- service:
haproxy_service_name: neutron_server
haproxy_backend_nodes: "{{ groups['neutron_server'] }}"
Expand Down

0 comments on commit caa9733

Please sign in to comment.