From 0f3dcf6e0ee7a3ab2d8e2eb6e57d027fa4cb8b74 Mon Sep 17 00:00:00 2001 From: Miguel Grinberg Date: Thu, 18 Jun 2015 18:34:36 -0700 Subject: [PATCH] Keystone Federation Identity Provider Configuration This change adds the bits necessary to configure Keystone as an identity provider (IdP) for an external service provider (SP). * New variables to configure Keystone as an identity provider are now supported under a root `keystone_idp` variable. Example configurations can be seen in Keystone's defaults file. This configuration includes the location of the signing certificate, authentication endpoints and list of allowed service providers. * xmlsec1 is installed in the Keystone containers when IdP configuration is enabled. * The IdP metadata and signing certiciate are generated and installed. Implements: blueprint keystone-federation Change-Id: I81455e593e3059633a55f7e341511d5ad9eba76f --- defaults/main.yml | 37 +++++++++++++- tasks/keystone_idp_metadata.yml | 25 ++++++++++ tasks/keystone_idp_self_signed_create.yml | 48 +++++++++++++++++++ tasks/keystone_idp_self_signed_distribute.yml | 44 +++++++++++++++++ tasks/keystone_idp_self_signed_store.yml | 31 ++++++++++++ tasks/keystone_idp_setup.yml | 30 ++++++++++++ tasks/keystone_idp_sp_setup.yml | 30 ++++++++++++ tasks/keystone_install.yml | 13 +++++ tasks/keystone_post_install.yml | 1 - tasks/keystone_pre_install.yml | 10 ++++ tasks/main.yml | 4 ++ templates/keystone.conf.j2 | 36 ++++++++++++++ 12 files changed, 306 insertions(+), 3 deletions(-) create mode 100644 tasks/keystone_idp_metadata.yml create mode 100644 tasks/keystone_idp_self_signed_create.yml create mode 100644 tasks/keystone_idp_self_signed_distribute.yml create mode 100644 tasks/keystone_idp_self_signed_store.yml create mode 100644 tasks/keystone_idp_setup.yml create mode 100644 tasks/keystone_idp_sp_setup.yml diff --git a/defaults/main.yml b/defaults/main.yml index 07b0a937..3cfdc5dd 100644 --- a/defaults/main.yml +++ b/defaults/main.yml @@ -24,6 +24,8 @@ keystone_fatal_deprecations: False ## System info keystone_system_user_name: keystone keystone_system_group_name: keystone +keystone_system_additional_groups: + - ssl_cert keystone_system_service_name: apache2 keystone_system_shell: /bin/bash keystone_system_comment: keystone system user @@ -124,9 +126,10 @@ keystone_service_adminurl: "{{ keystone_service_adminurl_v3 }}" keystone_apache_log_level: info keystone_ssl_enabled: false -keystone_ssl_cert: /etc/ssl/certs/apache.cert -keystone_ssl_key: /etc/ssl/private/apache.key 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" keystone_ssl_protocol: "{{ ssl_protocol }}" keystone_ssl_cipher_suite: "{{ ssl_cipher_suite }}" @@ -161,6 +164,32 @@ keystone_recreate_keys: False # identity:create_region: "rule:admin_required" # identity:update_region: "rule:admin_required" +## Federation + +# Enable the following section on the Keystone IdP +#keystone_idp: +# certfile: "/etc/keystone/ssl/idp_signing_cert.pem" +# keyfile: "/etc/keystone/ssl/idp_signing_key.pem" +# self_signed_cert_subject: "/C=US/ST=Texas/L=San Antonio/O=IT/CN={{ external_lb_vip_address }}" +# regen_cert: false +# idp_entity_id: "{{ keystone_service_publicurl_v3 }}/OS-FEDERATION/saml2/idp" +# idp_sso_endpoint: "{{ keystone_service_publicurl_v3 }}/OS-FEDERATION/saml2/sso" +# idp_metadata_path: /etc/keystone/saml2_idp_metadata.xml +# service_providers: +# - id: "sp_1" +# auth_url: https://example.com:5000/v3/OS-FEDERATION/identity_providers/idp/protocols/saml2/auth +# sp_url: https://example.com:5000/Shibboleth.sso/SAML2/ECP +# # the following settings are optional +# organization_name: example_company +# organization_display_name: Example Corp. +# organization_url: example.com +# contact_company: example_company +# contact_name: John +# contact_surname: Smith +# contact_email: jsmith@example.com +# contact_telephone: 555-55-5555 +# contact_type: technical + # Common apt packages keystone_apt_packages: - apache2 @@ -177,6 +206,10 @@ keystone_apt_packages: - libxslt1.1 - rsync +keystone_idp_apt_packages: + - ssl-cert + - xmlsec1 + # Common pip packages keystone_pip_packages: - keystone diff --git a/tasks/keystone_idp_metadata.yml b/tasks/keystone_idp_metadata.yml new file mode 100644 index 00000000..489428cf --- /dev/null +++ b/tasks/keystone_idp_metadata.yml @@ -0,0 +1,25 @@ +--- +# 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: Generate IdP metadata + shell: "keystone-manage saml_idp_metadata > {{ keystone_idp.idp_metadata_path }}" + sudo: yes + sudo_user: "{{ keystone_system_user_name }}" + when: keystone_idp is defined + notify: + - Restart Apache + tags: + - keystone-config + - keystone-idp diff --git a/tasks/keystone_idp_self_signed_create.yml b/tasks/keystone_idp_self_signed_create.yml new file mode 100644 index 00000000..2ae0094c --- /dev/null +++ b/tasks/keystone_idp_self_signed_create.yml @@ -0,0 +1,48 @@ +--- +# 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: Remove IdP self-signed certificate for regen + file: + dest: "{{ keystone_idp.cerfile }}" + state: "absent" + when: > + keystone_idp.regen_cert == true or + keystone_idp.regen_cert == "True" + +- name: Create IdP self-signed ssl cert + command: > + openssl req -new -nodes -sha256 -x509 -subj + "{{ keystone_idp.self_signed_cert_subject }}" + -days 3650 + -keyout {{ keystone_idp.keyfile }} + -out {{ keystone_idp.certfile }} + -extensions v3_ca + creates={{ keystone_idp.certfile }} + when: > + inventory_hostname == groups['keystone_all'][0] + notify: Restart Apache + tags: + - keystone-config + - keystone-idp + +- name: Set appropriate file ownership on the IdP self-signed cert + file: + path: "{{ item }}" + owner: "{{ keystone_system_user_name }}" + group: "{{ keystone_system_group_name }}" + mode: "0640" + with_items: + - "{{ keystone_idp.keyfile }}" + - "{{ keystone_idp.certfile }}" diff --git a/tasks/keystone_idp_self_signed_distribute.yml b/tasks/keystone_idp_self_signed_distribute.yml new file mode 100644 index 00000000..089a26bd --- /dev/null +++ b/tasks/keystone_idp_self_signed_distribute.yml @@ -0,0 +1,44 @@ +--- +# 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 IdP self-signed certificate + 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_idp.certfile }}", name: "keystone_idp_cert", file_mode: "0640", dir_mode: "0750" } + - { src: "{{ keystone_idp.keyfile }}", name: "keystone_idp_key", file_mode: "0640", dir_mode: "0750" } + register: memcache_keys + until: memcache_keys|success + retries: 5 + delay: 2 + notify: Restart Apache + tags: + - keystone-idp + +- name: Set appropriate file ownership on the IdP self-signed cert + file: + path: "{{ item }}" + owner: "{{ keystone_system_user_name }}" + group: "{{ keystone_system_group_name }}" + mode: "0640" + with_items: + - "{{ keystone_idp.keyfile }}" + - "{{ keystone_idp.certfile }}" diff --git a/tasks/keystone_idp_self_signed_store.yml b/tasks/keystone_idp_self_signed_store.yml new file mode 100644 index 00000000..2d39af0c --- /dev/null +++ b/tasks/keystone_idp_self_signed_store.yml @@ -0,0 +1,31 @@ +--- +# 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: Store IdP self-signed certificate + memcached: + name: "{{ item.name }}" + file_path: "{{ item.src }}" + state: "present" + server: "{{ memcached_servers }}" + encrypt_string: "{{ memcached_encryption_key }}" + with_items: + - { src: "{{ keystone_idp.certfile }}", name: "keystone_idp_cert" } + - { src: "{{ keystone_idp.keyfile }}", name: "keystone_idp_key" } + register: memcache_keys + until: memcache_keys|success + retries: 5 + delay: 2 + tags: + - keystone-idp diff --git a/tasks/keystone_idp_setup.yml b/tasks/keystone_idp_setup.yml new file mode 100644 index 00000000..4400ad7a --- /dev/null +++ b/tasks/keystone_idp_setup.yml @@ -0,0 +1,30 @@ +--- +# 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. + +- include: keystone_idp_self_signed_create.yml + when: > + inventory_hostname == groups['keystone_all'][0] + +- include: keystone_idp_self_signed_store.yml + when: > + inventory_hostname == groups['keystone_all'][0] + +- include: keystone_idp_self_signed_distribute.yml + when: > + inventory_hostname != groups['keystone_all'][0] + +- include: keystone_idp_metadata.yml + +- include: keystone_idp_sp_setup.yml diff --git a/tasks/keystone_idp_sp_setup.yml b/tasks/keystone_idp_sp_setup.yml new file mode 100644 index 00000000..bf5ebce0 --- /dev/null +++ b/tasks/keystone_idp_sp_setup.yml @@ -0,0 +1,30 @@ +--- +# 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: Register service providers + keystone: + command: "ensure_service_provider" + token: "{{ keystone_auth_admin_token }}" + endpoint: "{{ keystone_service_adminurl }}" + sp_name: "{{ item.id }}" + sp_url: "{{ item.sp_url }}" + sp_auth_url: "{{ item.auth_url }}" + with_items: keystone_idp.service_providers + register: add_service_providers + until: add_service_providers|success + retries: 5 + delay: 10 + tags: + - keystone-idp diff --git a/tasks/keystone_install.yml b/tasks/keystone_install.yml index 8fd64146..216f6cea 100644 --- a/tasks/keystone_install.yml +++ b/tasks/keystone_install.yml @@ -36,6 +36,19 @@ tags: - keystone-apt-packages +- name: Install IdP apt packages + apt: + pkg: "{{ item }}" + state: latest + register: install_packages + until: install_packages|success + retries: 5 + delay: 2 + with_items: keystone_idp_apt_packages + when: keystone_idp is defined + tags: + - keystone-apt-packages + - name: Install pip packages pip: name: "{{ item }}" diff --git a/tasks/keystone_post_install.yml b/tasks/keystone_post_install.yml index 09d07fa7..29119547 100644 --- a/tasks/keystone_post_install.yml +++ b/tasks/keystone_post_install.yml @@ -57,4 +57,3 @@ - Restart Apache tags: - keystone-config - diff --git a/tasks/keystone_pre_install.yml b/tasks/keystone_pre_install.yml index 39fbdbf6..1816ebf9 100644 --- a/tasks/keystone_pre_install.yml +++ b/tasks/keystone_pre_install.yml @@ -21,6 +21,15 @@ tags: - keystone-group +- name: create additional groups + group: + name: "{{ item }}" + state: "present" + system: "yes" + with_items: keystone_system_additional_groups + tags: + - keystone-group + - name: Remove old key file(s) if found file: path: "{{ item }}" @@ -38,6 +47,7 @@ user: name: "{{ keystone_system_user_name }}" group: "{{ keystone_system_group_name }}" + groups: "{{ keystone_system_additional_groups | join(',') }}" comment: "{{ keystone_system_comment }}" shell: "{{ keystone_system_shell }}" system: "yes" diff --git a/tasks/main.yml b/tasks/main.yml index 20f2c2bd..fc8c8346 100644 --- a/tasks/main.yml +++ b/tasks/main.yml @@ -42,3 +42,7 @@ - name: Flush handlers meta: flush_handlers + +- include: keystone_idp_setup.yml + when: > + keystone_idp is defined diff --git a/templates/keystone.conf.j2 b/templates/keystone.conf.j2 index 08d0d7fa..b2c61a4a 100644 --- a/templates/keystone.conf.j2 +++ b/templates/keystone.conf.j2 @@ -87,6 +87,42 @@ provider = {{ keystone_token_provider }} driver = {{ keystone_token_driver }} {% endif %} +{% if keystone_idp is defined %} +[saml] +certfile = "{{ keystone_idp.certfile }}" +keyfile = "{{ keystone_idp.keyfile }}" +idp_entity_id = "{{ keystone_idp.idp_entity_id }}" +idp_sso_endpoint = "{{ keystone_idp.idp_sso_endpoint }}" +idp_metadata_path = "{{ keystone_idp.idp_metadata_path }}" +{% if keystone_idp.organization_name is defined %} +idp_organization_name = {{ keystone_idp.organization_name }} +{% endif %} +{% if keystone_idp.organization_display_name is defined %} +idp_organization_display_name = {{ keystone_idp.organization_display_name }} +{% endif %} +{% if keystone_idp.organization_url is defined %} +idp_organization_url = {{ keystone_idp.organization_url }} +{% endif %} +{% if keystone_idp.contact_company is defined %} +idp_contact_company = {{ keystone_idp.contact_company }} +{% endif %} +{% if keystone_idp.contact_name is defined %} +idp_contact_name = {{ keystone_idp.contact_name }} +{% endif %} +{% if keystone_idp.contact_surname is defined %} +idp_contact_surname = {{ keystone_idp.contact_surname }} +{% endif %} +{% if keystone_idp.contact_email is defined %} +idp_contact_email = {{ keystone_idp.contact_email }} +{% endif %} +{% if keystone_idp.contact_telephone is defined %} +idp_contact_telephone = {{ keystone_idp.contact_telephone }} +{% endif %} +{% if keystone_idp.contact_type is defined %} +idp_contact_type = {{ keystone_idp.contact_type }} +{% endif %} +{% endif %} + [eventlet_server] admin_bind_host = {{ keystone_bind_address }} admin_port = {{ keystone_admin_port }}