Keystone Federation Service Provider Configuration
This patch adds the ability to configure Keystone as a Service Provider (SP) for a Federated Identity Provider (IdP). * New variables to configure Keystone as a service provider are now supported under a root `keystone_sp` variable. Example configurations can be seen in Keystone's defaults file. This configuration includes the list of identity providers and trusted dashboards. (At this time only one identity provider is supported). * Identity provider configuration includes the remote-to-local user mapping and the list of remote attributes the SP can obtain from the IdP. * Shibboleth is installed and configured in the Keystone containers when SP configuration is present. * Horizon is configured for SSO login DocImpact UpgradeImpact Implements: blueprint keystone-federation Change-Id: I78b3d740434ea4b3ca0bd9f144e4a07026be23c6 Co-Authored-By: Jesse Pretorius <jesse.pretorius@rackspace.co.uk>
This commit is contained in:
parent
d82bbb4336
commit
23da164fe4
@ -195,7 +195,8 @@ options:
|
|||||||
'ensure_user', 'ensure_user_role', 'ensure_tenant',
|
'ensure_user', 'ensure_user_role', 'ensure_tenant',
|
||||||
'ensure_project', 'ensure_service_provider',
|
'ensure_project', 'ensure_service_provider',
|
||||||
'ensure_group', 'ensure_identity_provider',
|
'ensure_group', 'ensure_identity_provider',
|
||||||
'ensure_protocol', ensure_mapping']
|
'ensure_protocol', ensure_mapping',
|
||||||
|
'ensure_group_role']
|
||||||
required: true
|
required: true
|
||||||
insecure:
|
insecure:
|
||||||
description:
|
description:
|
||||||
@ -251,6 +252,13 @@ EXAMPLES = """
|
|||||||
project_name: "service"
|
project_name: "service"
|
||||||
role_name: "admin"
|
role_name: "admin"
|
||||||
|
|
||||||
|
# Add a project role to a group
|
||||||
|
- keystone:
|
||||||
|
command: "ensure_group_role"
|
||||||
|
group_name: "fedgroup"
|
||||||
|
project_name: "fedproject"
|
||||||
|
role_name: "_member_"
|
||||||
|
|
||||||
# Create a service
|
# Create a service
|
||||||
- keystone:
|
- keystone:
|
||||||
command: "ensure_service"
|
command: "ensure_service"
|
||||||
@ -353,6 +361,13 @@ COMMAND_MAP = {
|
|||||||
'role_name'
|
'role_name'
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
'ensure_group_role': {
|
||||||
|
'variables': [
|
||||||
|
'group_name',
|
||||||
|
'project_name',
|
||||||
|
'role_name'
|
||||||
|
]
|
||||||
|
},
|
||||||
'ensure_project': {
|
'ensure_project': {
|
||||||
'variables': [
|
'variables': [
|
||||||
'project_name',
|
'project_name',
|
||||||
@ -716,7 +731,7 @@ class ManageKeystone(object):
|
|||||||
return self._facts(facts={'id': user.id})
|
return self._facts(facts={'id': user.id})
|
||||||
|
|
||||||
def _get_role(self, name):
|
def _get_role(self, name):
|
||||||
"""Return a tenant by name.
|
"""Return a role by name.
|
||||||
|
|
||||||
This will return `None` if the ``name`` is not found.
|
This will return `None` if the ``name`` is not found.
|
||||||
|
|
||||||
@ -728,8 +743,25 @@ class ManageKeystone(object):
|
|||||||
else:
|
else:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
def _get_group(self, name, domain=None):
|
||||||
|
"""Return a group by name.
|
||||||
|
|
||||||
|
This will return `None` if the ``name`` is not found.
|
||||||
|
|
||||||
|
:param name: ``str`` Name of the role.
|
||||||
|
"""
|
||||||
|
for entry in self.keystone.groups.list():
|
||||||
|
if domain is None:
|
||||||
|
if entry.name == name:
|
||||||
|
return entry
|
||||||
|
else:
|
||||||
|
if entry.name == name and entry.domain_id == domain.id:
|
||||||
|
return entry
|
||||||
|
else:
|
||||||
|
return None
|
||||||
|
|
||||||
def get_role(self, variables):
|
def get_role(self, variables):
|
||||||
"""Return a tenant by name.
|
"""Return a role by name.
|
||||||
|
|
||||||
This will return `None` if the ``name`` is not found.
|
This will return `None` if the ``name`` is not found.
|
||||||
|
|
||||||
@ -749,7 +781,8 @@ class ManageKeystone(object):
|
|||||||
|
|
||||||
return self._facts(facts={'id': role_data.id})
|
return self._facts(facts={'id': role_data.id})
|
||||||
|
|
||||||
def _get_role_data(self, user_name, project_name, role_name):
|
def _get_role_data(self, user_name, project_name, role_name, group_name):
|
||||||
|
if user_name is not None:
|
||||||
user = self._get_user(name=user_name)
|
user = self._get_user(name=user_name)
|
||||||
if user is None:
|
if user is None:
|
||||||
self.failure(
|
self.failure(
|
||||||
@ -757,6 +790,8 @@ class ManageKeystone(object):
|
|||||||
rc=2,
|
rc=2,
|
||||||
msg='User was not found, does it exist?'
|
msg='User was not found, does it exist?'
|
||||||
)
|
)
|
||||||
|
else:
|
||||||
|
user = None
|
||||||
|
|
||||||
project = self._get_project(name=project_name)
|
project = self._get_project(name=project_name)
|
||||||
if project is None:
|
if project is None:
|
||||||
@ -774,7 +809,18 @@ class ManageKeystone(object):
|
|||||||
msg='role was not found, does it exist?'
|
msg='role was not found, does it exist?'
|
||||||
)
|
)
|
||||||
|
|
||||||
return user, project, role
|
if group_name is not None:
|
||||||
|
group = self._get_group(name=group_name)
|
||||||
|
if group is None:
|
||||||
|
self.failure(
|
||||||
|
error='group [ %s ] was not found.' % group_name,
|
||||||
|
rc=2,
|
||||||
|
msg='group was not found, does it exist?'
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
group = None
|
||||||
|
|
||||||
|
return user, project, role, group
|
||||||
|
|
||||||
def ensure_role(self, variables):
|
def ensure_role(self, variables):
|
||||||
"""Create a new role within Keystone if it does not exist.
|
"""Create a new role within Keystone if it does not exist.
|
||||||
@ -802,6 +848,13 @@ class ManageKeystone(object):
|
|||||||
else:
|
else:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
def _get_group_roles(self, name, group, project):
|
||||||
|
for entry in self.keystone.roles.list(group=group, project=project):
|
||||||
|
if entry.name == name:
|
||||||
|
return entry
|
||||||
|
else:
|
||||||
|
return None
|
||||||
|
|
||||||
def ensure_user_role(self, variables):
|
def ensure_user_role(self, variables):
|
||||||
self._authenticate()
|
self._authenticate()
|
||||||
required_vars = ['user_name', 'role_name']
|
required_vars = ['user_name', 'role_name']
|
||||||
@ -814,8 +867,9 @@ class ManageKeystone(object):
|
|||||||
or variables_dict.pop('tenant_name'))
|
or variables_dict.pop('tenant_name'))
|
||||||
role_name = variables_dict.pop('role_name')
|
role_name = variables_dict.pop('role_name')
|
||||||
|
|
||||||
user, project, role = self._get_role_data(
|
user, project, role, group = self._get_role_data(
|
||||||
user_name=user_name, project_name=project_name, role_name=role_name
|
user_name=user_name, project_name=project_name,
|
||||||
|
role_name=role_name, group_name=None
|
||||||
)
|
)
|
||||||
|
|
||||||
user_role = self._get_user_roles(
|
user_role = self._get_user_roles(
|
||||||
@ -832,6 +886,64 @@ class ManageKeystone(object):
|
|||||||
|
|
||||||
return self._facts(facts={'id': user_role.id})
|
return self._facts(facts={'id': user_role.id})
|
||||||
|
|
||||||
|
def ensure_group_role(self, variables):
|
||||||
|
self._authenticate()
|
||||||
|
required_vars = ['group_name', 'project_name', 'role_name']
|
||||||
|
variables_dict = self._get_vars(variables, required=required_vars)
|
||||||
|
group_name = variables_dict.pop('group_name')
|
||||||
|
project_name = variables_dict.pop('project_name')
|
||||||
|
role_name = variables_dict.pop('role_name')
|
||||||
|
|
||||||
|
user, project, role, group = self._get_role_data(
|
||||||
|
group_name=group_name, project_name=project_name,
|
||||||
|
role_name=role_name, user_name=None
|
||||||
|
)
|
||||||
|
|
||||||
|
group_role = self._get_group_roles(
|
||||||
|
name=role_name, group=group, project=project
|
||||||
|
)
|
||||||
|
|
||||||
|
if group_role is None:
|
||||||
|
self.keystone.roles.grant(
|
||||||
|
group=group, role=role, project=project
|
||||||
|
)
|
||||||
|
group_role = self._get_group_roles(
|
||||||
|
name=role_name, group=group, project=project
|
||||||
|
)
|
||||||
|
|
||||||
|
return self._facts(facts={'id': group_role.id})
|
||||||
|
|
||||||
|
def ensure_group(self, variables):
|
||||||
|
"""Create a new group within Keystone if it does not exist.
|
||||||
|
|
||||||
|
Returns the group ID on a successful run.
|
||||||
|
|
||||||
|
:param variables: ``list`` List of all variables that are available to
|
||||||
|
use within the Keystone Command.
|
||||||
|
"""
|
||||||
|
|
||||||
|
self._authenticate()
|
||||||
|
required_vars = ['group_name', 'domain_name']
|
||||||
|
variables_dict = self._get_vars(variables, required=required_vars)
|
||||||
|
group_name = variables_dict.pop('group_name')
|
||||||
|
domain_name = variables_dict.pop('domain_name')
|
||||||
|
|
||||||
|
domain = self._get_domain(
|
||||||
|
name=domain_name
|
||||||
|
)
|
||||||
|
|
||||||
|
group = self._get_group(
|
||||||
|
name=group_name, domain=domain
|
||||||
|
)
|
||||||
|
|
||||||
|
if group is None:
|
||||||
|
self.state_change = True
|
||||||
|
group = self.keystone.groups.create(
|
||||||
|
name=group_name, domain=domain
|
||||||
|
)
|
||||||
|
|
||||||
|
return self._facts(facts={'id': group.id})
|
||||||
|
|
||||||
def _get_service(self, name, srv_type=None):
|
def _get_service(self, name, srv_type=None):
|
||||||
for entry in self.keystone.services.list():
|
for entry in self.keystone.services.list():
|
||||||
if srv_type is not None:
|
if srv_type is not None:
|
||||||
@ -975,23 +1087,6 @@ class ManageKeystone(object):
|
|||||||
# return no facts in this case.
|
# return no facts in this case.
|
||||||
return self._facts(facts={})
|
return self._facts(facts={})
|
||||||
|
|
||||||
def ensure_group(self, variables):
|
|
||||||
"""Create a new group within Keystone if it does not exist.
|
|
||||||
|
|
||||||
Returns the group ID on a successful run.
|
|
||||||
|
|
||||||
:param variables: ``list`` List of all variables that are available to
|
|
||||||
use within the Keystone Command.
|
|
||||||
"""
|
|
||||||
|
|
||||||
self._authenticate()
|
|
||||||
return self._ensure_generic(
|
|
||||||
manager=self.keystone.groups,
|
|
||||||
required_vars={'group_name': 'name',
|
|
||||||
'domain_name': 'domain'},
|
|
||||||
variables=variables
|
|
||||||
)
|
|
||||||
|
|
||||||
def ensure_identity_provider(self, variables):
|
def ensure_identity_provider(self, variables):
|
||||||
self._authenticate()
|
self._authenticate()
|
||||||
return self._ensure_generic(
|
return self._ensure_generic(
|
||||||
|
@ -170,21 +170,27 @@ OPENSTACK_KEYSTONE_URL = "{{ horizon_keystone_endpoint }}"
|
|||||||
|
|
||||||
OPENSTACK_KEYSTONE_DEFAULT_ROLE = "_member_"
|
OPENSTACK_KEYSTONE_DEFAULT_ROLE = "_member_"
|
||||||
|
|
||||||
# Enables keystone web single-sign-on if set to True.
|
{% if keystone_sp is defined %}
|
||||||
#WEBSSO_ENABLED = False
|
# Enables keystone web single-sign-on
|
||||||
|
WEBSSO_ENABLED = True
|
||||||
|
|
||||||
# Determines which authentication choice to show as default.
|
# Determines which authentication choice to show as default.
|
||||||
#WEBSSO_INITIAL_CHOICE = "credentials"
|
WEBSSO_INITIAL_CHOICE = "credentials"
|
||||||
|
|
||||||
# The list of authentication mechanisms
|
# The list of authentication mechanisms
|
||||||
# which include keystone federation protocols.
|
# which include keystone federation protocols.
|
||||||
# Current supported protocol IDs are 'saml2' and 'oidc'
|
# Current supported protocol IDs are 'saml2' and 'oidc'
|
||||||
# which represent SAML 2.0, OpenID Connect respectively.
|
# which represent SAML 2.0, OpenID Connect respectively.
|
||||||
# Do not remove the mandatory credentials mechanism.
|
# Do not remove the mandatory credentials mechanism.
|
||||||
#WEBSSO_CHOICES = (
|
WEBSSO_CHOICES = (
|
||||||
# ("credentials", _("Keystone Credentials")),
|
("credentials", _("Keystone Credentials")),
|
||||||
# ("oidc", _("OpenID Connect")),
|
{% for idp in keystone_sp.trusted_idp_list %}
|
||||||
# ("saml2", _("Security Assertion Markup Language")))
|
{% for protocol in idp.protocols %}
|
||||||
|
("{{ protocol.name }}", _("{{ idp.name }}")){% if not loop.last %},{% endif %}
|
||||||
|
{% endfor %}
|
||||||
|
{% endfor %}
|
||||||
|
)
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
# Disable SSL certificate checks (useful for self-signed certificates):
|
# Disable SSL certificate checks (useful for self-signed certificates):
|
||||||
OPENSTACK_SSL_NO_VERIFY = {{ horizon_ssl_no_verify | bool }}
|
OPENSTACK_SSL_NO_VERIFY = {{ horizon_ssl_no_verify | bool }}
|
||||||
|
@ -120,7 +120,7 @@ keystone_service_internalurl: "{{ keystone_service_internalurl_v3 }}"
|
|||||||
keystone_service_adminurl: "{{ keystone_service_adminurl_v3 }}"
|
keystone_service_adminurl: "{{ keystone_service_adminurl_v3 }}"
|
||||||
|
|
||||||
## Set this value to override the "public_endpoint" keystone.conf variable
|
## Set this value to override the "public_endpoint" keystone.conf variable
|
||||||
#keystone_public_endpoint:
|
#keystone_public_endpoint: "{{ keystone_service_publicuri }}"
|
||||||
|
|
||||||
## Apache setup
|
## Apache setup
|
||||||
keystone_apache_log_level: info
|
keystone_apache_log_level: info
|
||||||
@ -190,6 +190,82 @@ keystone_recreate_keys: False
|
|||||||
# contact_telephone: 555-55-5555
|
# contact_telephone: 555-55-5555
|
||||||
# contact_type: technical
|
# contact_type: technical
|
||||||
|
|
||||||
|
# Enable the following section in order to install and configure
|
||||||
|
# Keystone as a Resource Service Provider (SP) and to configure
|
||||||
|
# trusts with specific Identity Providers (IdP).
|
||||||
|
#keystone_sp:
|
||||||
|
# cert_duration_years: 5
|
||||||
|
# trusted_dashboard_list:
|
||||||
|
# - "https://{{ external_lb_vip_address }}/auth/websso/"
|
||||||
|
# trusted_idp_list:
|
||||||
|
# note that only one of these is supported at any one time for now
|
||||||
|
# - name: "keystone-idp"
|
||||||
|
# entity_ids:
|
||||||
|
# - 'https://keystone-idp:5000/v3/OS-FEDERATION/saml2/idp'
|
||||||
|
# metadata_uri: 'https://keystone-idp:5000/v3/OS-FEDERATION/saml2/metadata'
|
||||||
|
# metadata_file: 'metadata-keystone-idp.xml'
|
||||||
|
# metadata_reload: 1800
|
||||||
|
# federated_identities:
|
||||||
|
# - domain: Default
|
||||||
|
# project: fedproject
|
||||||
|
# group: fedgroup
|
||||||
|
# role: _member_
|
||||||
|
# protocols:
|
||||||
|
# - name: saml2
|
||||||
|
# mapping:
|
||||||
|
# name: keystone-idp-mapping
|
||||||
|
# rules:
|
||||||
|
# - remote:
|
||||||
|
# - type: openstack_user
|
||||||
|
# local:
|
||||||
|
# - group:
|
||||||
|
# name: fedgroup
|
||||||
|
# domain:
|
||||||
|
# name: Default
|
||||||
|
# user:
|
||||||
|
# name: '{0}'
|
||||||
|
# attributes:
|
||||||
|
# - name: openstack_user
|
||||||
|
# id: openstack_user
|
||||||
|
# - name: openstack_roles
|
||||||
|
# id: openstack_roles
|
||||||
|
# - name: openstack_project
|
||||||
|
# id: openstack_project
|
||||||
|
# - name: openstack_user_domain
|
||||||
|
# id: openstack_user_domain
|
||||||
|
# - name: openstack_project_domain
|
||||||
|
# id: openstack_project_domain
|
||||||
|
#
|
||||||
|
# - name: 'testshib-idp'
|
||||||
|
# entity_ids:
|
||||||
|
# - 'https://idp.testshib.org/idp/shibboleth'
|
||||||
|
# metadata_uri: 'http://www.testshib.org/metadata/testshib-providers.xml'
|
||||||
|
# metadata_file: 'metadata-testshib-idp.xml'
|
||||||
|
# metadata_reload: 1800
|
||||||
|
# federated_identities:
|
||||||
|
# - domain: Default
|
||||||
|
# project: fedproject
|
||||||
|
# group: fedgroup
|
||||||
|
# role: _member_
|
||||||
|
# protocols:
|
||||||
|
# - name: saml2
|
||||||
|
# mapping:
|
||||||
|
# name: testshib-idp-mapping
|
||||||
|
# rules:
|
||||||
|
# - remote:
|
||||||
|
# - type: eppn
|
||||||
|
# local:
|
||||||
|
# - group:
|
||||||
|
# name: fedgroup
|
||||||
|
# domain:
|
||||||
|
# name: Default
|
||||||
|
# - user:
|
||||||
|
# name: '{0}'
|
||||||
|
|
||||||
|
# Keystone Federation SP Packages
|
||||||
|
keystone_sp_apt_packages:
|
||||||
|
- libapache2-mod-shib2
|
||||||
|
|
||||||
# Common apt packages
|
# Common apt packages
|
||||||
keystone_apt_packages:
|
keystone_apt_packages:
|
||||||
- apache2
|
- apache2
|
||||||
|
22
playbooks/roles/os_keystone/files/sso_callback_template.html
Normal file
22
playbooks/roles/os_keystone/files/sso_callback_template.html
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||||
|
<head>
|
||||||
|
<title>Keystone WebSSO redirect</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<form id="sso" name="sso" action="$host" method="post">
|
||||||
|
Please wait...
|
||||||
|
<br/>
|
||||||
|
<input type="hidden" name="token" id="token" value="$token"/>
|
||||||
|
<noscript>
|
||||||
|
<input type="submit" name="submit_no_javascript" id="submit_no_javascript"
|
||||||
|
value="If your JavaScript is disabled, please click to continue"/>
|
||||||
|
</noscript>
|
||||||
|
</form>
|
||||||
|
<script type="text/javascript">
|
||||||
|
window.onload = function() {
|
||||||
|
document.forms['sso'].submit();
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
@ -22,3 +22,13 @@
|
|||||||
until: apache_restart|success
|
until: apache_restart|success
|
||||||
retries: 5
|
retries: 5
|
||||||
delay: 2
|
delay: 2
|
||||||
|
|
||||||
|
- name: Restart Shibd
|
||||||
|
service:
|
||||||
|
name: "shibd"
|
||||||
|
state: "restarted"
|
||||||
|
pattern: "shibd"
|
||||||
|
register: shibd_restart
|
||||||
|
until: shibd_restart|success
|
||||||
|
retries: 5
|
||||||
|
delay: 2
|
||||||
|
117
playbooks/roles/os_keystone/library/keystone_sp
Normal file
117
playbooks/roles/os_keystone/library/keystone_sp
Normal file
@ -0,0 +1,117 @@
|
|||||||
|
#!/usr/bin/python
|
||||||
|
# (c) 2015, Kevin Carter <kevin.carter@rackspace.com>
|
||||||
|
#
|
||||||
|
# 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.
|
||||||
|
|
||||||
|
DOCUMENTATION = """
|
||||||
|
---
|
||||||
|
module: keystone_sp
|
||||||
|
version_added: "1.9.2"
|
||||||
|
short_description:
|
||||||
|
- Creates a fact for keystone_federated_identities and keystone_protocols
|
||||||
|
description:
|
||||||
|
- Sets facts called `keystone_federated_identities` and
|
||||||
|
`keystone_federated_protocols`, which are lists of hashes built from
|
||||||
|
keystone_sp using the information in the `federated_identities` and
|
||||||
|
`protocols` keys.
|
||||||
|
options:
|
||||||
|
sp_data:
|
||||||
|
description:
|
||||||
|
- Hash to build the service provider lists from
|
||||||
|
required: true
|
||||||
|
author: Kevin Carter
|
||||||
|
"""
|
||||||
|
|
||||||
|
EXAMPLES = """
|
||||||
|
# Set the keystone_federated_identities and keystone_federated_protocols facts
|
||||||
|
- keystone_sp:
|
||||||
|
sp_data: "{{ keystone_sp }}"
|
||||||
|
when: keystone_sp is defined
|
||||||
|
"""
|
||||||
|
|
||||||
|
# Keystone service provider data structure example.
|
||||||
|
"""
|
||||||
|
keystone_sp:
|
||||||
|
trusted_idp_list:
|
||||||
|
- name: "keystone-idp"
|
||||||
|
federated_identities:
|
||||||
|
- domain: Default
|
||||||
|
project: fedproject
|
||||||
|
group: fedgroup
|
||||||
|
role: _member_
|
||||||
|
protocols:
|
||||||
|
- name: saml2
|
||||||
|
mapping:
|
||||||
|
...
|
||||||
|
- name: 'testshib-idp'
|
||||||
|
federated_identities:
|
||||||
|
- domain: Default
|
||||||
|
project: fedproject2
|
||||||
|
group: fedgroup2
|
||||||
|
role: _member_
|
||||||
|
protocols:
|
||||||
|
- name: saml2
|
||||||
|
mapping:
|
||||||
|
...
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
class KeystoneSp(object):
|
||||||
|
def __init__(self, module):
|
||||||
|
"""Generate an integer from a name."""
|
||||||
|
self.module = module
|
||||||
|
self.identities_return_list = list()
|
||||||
|
self.protocols_return_list = list()
|
||||||
|
self.sp_data = self.module.params['sp_data']
|
||||||
|
|
||||||
|
def populate_sp_data(self):
|
||||||
|
trusted_idp_list = self.sp_data['trusted_idp_list']
|
||||||
|
for trusted_idp in trusted_idp_list:
|
||||||
|
federated_identities = trusted_idp.get('federated_identities')
|
||||||
|
if federated_identities:
|
||||||
|
self.identities_return_list.extend(federated_identities)
|
||||||
|
protocols = trusted_idp.get('protocols')
|
||||||
|
if protocols:
|
||||||
|
for protocol in protocols:
|
||||||
|
self.protocols_return_list.append(
|
||||||
|
{'idp': trusted_idp, 'protocol': protocol})
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
module = AnsibleModule(
|
||||||
|
argument_spec=dict(
|
||||||
|
sp_data=dict(
|
||||||
|
required=True
|
||||||
|
)
|
||||||
|
),
|
||||||
|
supports_check_mode=False
|
||||||
|
)
|
||||||
|
try:
|
||||||
|
ksp = KeystoneSp(module=module)
|
||||||
|
ksp.populate_sp_data()
|
||||||
|
module.exit_json(
|
||||||
|
changed=True,
|
||||||
|
ansible_facts={
|
||||||
|
'keystone_federated_identities': ksp.identities_return_list,
|
||||||
|
'keystone_federated_protocols': ksp.protocols_return_list}
|
||||||
|
)
|
||||||
|
except Exception as exp:
|
||||||
|
resp = {'stderr': exp}
|
||||||
|
module.fail_json(msg='Failed Process', **resp)
|
||||||
|
|
||||||
|
# import module snippets
|
||||||
|
from ansible.module_utils.basic import *
|
||||||
|
if __name__ == '__main__':
|
||||||
|
main()
|
@ -61,5 +61,17 @@
|
|||||||
apache2_module:
|
apache2_module:
|
||||||
name: ssl
|
name: ssl
|
||||||
state: "{{ (keystone_ssl_enabled | bool) | ternary('present', 'absent') }}"
|
state: "{{ (keystone_ssl_enabled | bool) | ternary('present', 'absent') }}"
|
||||||
|
notify:
|
||||||
|
- Restart Apache
|
||||||
|
tags:
|
||||||
|
- keystone-httpd
|
||||||
|
|
||||||
|
- name: Enable/disable mod_shib2 for apache2
|
||||||
|
apache2_module:
|
||||||
|
name: shib2
|
||||||
|
state: "{{ ( keystone_sp is defined ) | ternary('present', 'absent') }}"
|
||||||
|
ignore_errors: yes
|
||||||
|
notify:
|
||||||
|
- Restart Apache
|
||||||
tags:
|
tags:
|
||||||
- keystone-httpd
|
- keystone-httpd
|
||||||
|
@ -0,0 +1,152 @@
|
|||||||
|
---
|
||||||
|
# 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.
|
||||||
|
|
||||||
|
# note that these tasks will run when the id/name parameter is present.
|
||||||
|
# Providing the id/name without the other required params is a user error.
|
||||||
|
|
||||||
|
# TODO: Revisit this method when Ansible 2 releases
|
||||||
|
# User with_subelements instead, but in v1.x it's broken
|
||||||
|
- name: Set keystone_federated_identities fact
|
||||||
|
keystone_sp:
|
||||||
|
sp_data: "{{ keystone_sp }}"
|
||||||
|
tags:
|
||||||
|
- keystone-federation-sp
|
||||||
|
|
||||||
|
- name: Ensure domain which remote IDP users are mapped onto exists
|
||||||
|
keystone:
|
||||||
|
command: ensure_domain
|
||||||
|
domain_name: "{{ item.domain }}"
|
||||||
|
token: "{{ keystone_auth_admin_token }}"
|
||||||
|
endpoint: "{{ keystone_service_adminurl }}"
|
||||||
|
insecure: "{{ keystone_service_adminuri_insecure }}"
|
||||||
|
when: item.domain is defined
|
||||||
|
with_items: keystone_federated_identities
|
||||||
|
tags:
|
||||||
|
- keystone-federation-sp
|
||||||
|
|
||||||
|
- name: Ensure project which remote IDP users are mapped onto exists
|
||||||
|
keystone:
|
||||||
|
command: ensure_project
|
||||||
|
project_name: "{{ item.project }}"
|
||||||
|
domain_name: "{{ item.domain | default('Default') }}"
|
||||||
|
token: "{{ keystone_auth_admin_token }}"
|
||||||
|
endpoint: "{{ keystone_service_adminurl }}"
|
||||||
|
insecure: "{{ keystone_service_adminuri_insecure }}"
|
||||||
|
when: item.project is defined
|
||||||
|
with_items: keystone_federated_identities
|
||||||
|
tags:
|
||||||
|
- keystone-federation-sp
|
||||||
|
|
||||||
|
- name: Ensure user which remote IDP users are mapped onto exists
|
||||||
|
keystone:
|
||||||
|
command: ensure_user
|
||||||
|
user_name: "{{ item.user }}"
|
||||||
|
password: "{{ item.password }}"
|
||||||
|
project_name: "{{ item.project }}"
|
||||||
|
domain_name: "{{ item.domain | default('Default') }}"
|
||||||
|
token: "{{ keystone_auth_admin_token }}"
|
||||||
|
endpoint: "{{ keystone_service_adminurl }}"
|
||||||
|
insecure: "{{ keystone_service_adminuri_insecure }}"
|
||||||
|
when: >
|
||||||
|
item.user is defined and
|
||||||
|
item.password is defined and
|
||||||
|
item.project is defined
|
||||||
|
with_items: keystone_federated_identities
|
||||||
|
tags:
|
||||||
|
- keystone-federation-sp
|
||||||
|
|
||||||
|
- name: Ensure Group for external IDP users exists
|
||||||
|
keystone:
|
||||||
|
command: ensure_group
|
||||||
|
group_name: "{{ item.group }}"
|
||||||
|
domain_name: "{{ item.domain | default('Default') }}"
|
||||||
|
token: "{{ keystone_auth_admin_token }}"
|
||||||
|
endpoint: "{{ keystone_service_adminurl }}"
|
||||||
|
insecure: "{{ keystone_service_adminuri_insecure }}"
|
||||||
|
when: item.group is defined
|
||||||
|
with_items: keystone_federated_identities
|
||||||
|
tags:
|
||||||
|
- keystone-federation-sp
|
||||||
|
|
||||||
|
- name: Ensure Role for external IDP users exists
|
||||||
|
keystone:
|
||||||
|
command: "ensure_role"
|
||||||
|
role_name: "{{ item.role | default('_member_') }}"
|
||||||
|
token: "{{ keystone_auth_admin_token }}"
|
||||||
|
endpoint: "{{ keystone_service_adminurl }}"
|
||||||
|
insecure: "{{ keystone_service_adminuri_insecure }}"
|
||||||
|
when: >
|
||||||
|
item.group is defined and
|
||||||
|
item.project is defined
|
||||||
|
with_items: keystone_federated_identities
|
||||||
|
tags:
|
||||||
|
- keystone-federation-sp
|
||||||
|
|
||||||
|
- name: Ensure Group/Project/Role mapping exists
|
||||||
|
keystone:
|
||||||
|
command: ensure_group_role
|
||||||
|
group_name: "{{ item.group }}"
|
||||||
|
project_name: "{{ item.project }}"
|
||||||
|
role_name: "{{ item.role | default('_member_') }}"
|
||||||
|
token: "{{ keystone_auth_admin_token }}"
|
||||||
|
endpoint: "{{ keystone_service_adminurl }}"
|
||||||
|
insecure: "{{ keystone_service_adminuri_insecure }}"
|
||||||
|
when: >
|
||||||
|
item.group is defined and
|
||||||
|
item.project is defined
|
||||||
|
with_items: keystone_federated_identities
|
||||||
|
tags:
|
||||||
|
- keystone-federation-sp
|
||||||
|
|
||||||
|
- name: Ensure mapping for external IDP attributes exists
|
||||||
|
keystone:
|
||||||
|
command: ensure_mapping
|
||||||
|
mapping_name: "{{ item.protocol.mapping.name }}"
|
||||||
|
mapping_rules: "{{ item.protocol.mapping.rules }}"
|
||||||
|
token: "{{ keystone_auth_admin_token }}"
|
||||||
|
endpoint: "{{ keystone_service_adminurl }}"
|
||||||
|
insecure: "{{ keystone_service_adminuri_insecure }}"
|
||||||
|
when: item.protocol.mapping.name is defined
|
||||||
|
with_items: keystone_federated_protocols
|
||||||
|
tags:
|
||||||
|
- keystone-federation-sp
|
||||||
|
|
||||||
|
- name: Ensure external IDP
|
||||||
|
keystone:
|
||||||
|
command: ensure_identity_provider
|
||||||
|
idp_name: "{{ item.name }}"
|
||||||
|
idp_remote_ids: "{{ item.entity_ids }}"
|
||||||
|
idp_enabled: true
|
||||||
|
token: "{{ keystone_auth_admin_token }}"
|
||||||
|
endpoint: "{{ keystone_service_adminurl }}"
|
||||||
|
insecure: "{{ keystone_service_adminuri_insecure }}"
|
||||||
|
when: item.name is defined
|
||||||
|
with_items: keystone_sp.trusted_idp_list
|
||||||
|
tags:
|
||||||
|
- keystone-federation-sp
|
||||||
|
|
||||||
|
- name: Ensure federation protocol exists
|
||||||
|
keystone:
|
||||||
|
command: ensure_protocol
|
||||||
|
protocol_name: "{{ item.protocol.name }}"
|
||||||
|
idp_name: "{{ item.idp.name }}"
|
||||||
|
mapping_name: "{{ item.protocol.mapping.name }}"
|
||||||
|
token: "{{ keystone_auth_admin_token }}"
|
||||||
|
endpoint: "{{ keystone_service_adminurl }}"
|
||||||
|
insecure: "{{ keystone_service_adminuri_insecure }}"
|
||||||
|
when: item.protocol.name is defined
|
||||||
|
with_items: keystone_federated_protocols
|
||||||
|
tags:
|
||||||
|
- keystone-federation-sp
|
@ -0,0 +1,101 @@
|
|||||||
|
---
|
||||||
|
# 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 Shibboleth Config
|
||||||
|
template:
|
||||||
|
src: "{{ item.src }}"
|
||||||
|
dest: "{{ item.dest }}"
|
||||||
|
owner: "{{ keystone_system_user_name }}"
|
||||||
|
group: "{{ keystone_system_group_name }}"
|
||||||
|
mode: "{{ item.mode|default('0644') }}"
|
||||||
|
with_items:
|
||||||
|
- { src: "shibboleth-attribute-map.xml.j2", dest: "/etc/shibboleth/attribute-map.xml" }
|
||||||
|
- { src: "shibboleth2.xml.j2", dest: "/etc/shibboleth/shibboleth2.xml" }
|
||||||
|
notify:
|
||||||
|
- Restart Shibd
|
||||||
|
tags:
|
||||||
|
- keystone-config
|
||||||
|
- keystone-federation-sp
|
||||||
|
|
||||||
|
- name: Generate the Shibboleth SP key-pair
|
||||||
|
shell: "shib-keygen -h {{ external_lb_vip_address }} -y {{ keystone_sp.cert_duration_years }}"
|
||||||
|
args:
|
||||||
|
creates: "/etc/shibboleth/sp-cert.pem"
|
||||||
|
when: inventory_hostname == groups['keystone_all'][0]
|
||||||
|
notify:
|
||||||
|
- Restart Apache
|
||||||
|
- Restart Shibd
|
||||||
|
tags:
|
||||||
|
- keystone-config
|
||||||
|
- keystone-federation-sp
|
||||||
|
|
||||||
|
- name: Store Shibboleth SP key-pair
|
||||||
|
memcached:
|
||||||
|
name: "{{ item.name }}"
|
||||||
|
file_path: "{{ item.src }}"
|
||||||
|
state: "present"
|
||||||
|
server: "{{ memcached_servers }}"
|
||||||
|
encrypt_string: "{{ memcached_encryption_key }}"
|
||||||
|
with_items:
|
||||||
|
- { src: "/etc/shibboleth/sp-cert.pem", name: "keystone_sp_cert" }
|
||||||
|
- { src: "/etc/shibboleth/sp-key.pem", name: "keystone_sp_key" }
|
||||||
|
register: memcache_keys
|
||||||
|
until: memcache_keys|success
|
||||||
|
retries: 5
|
||||||
|
delay: 2
|
||||||
|
when: inventory_hostname == groups['keystone_all'][0]
|
||||||
|
tags:
|
||||||
|
- keystone-config
|
||||||
|
- keystone-federation-sp
|
||||||
|
|
||||||
|
- name: Distribute the Shibboleth SP key-pair
|
||||||
|
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: "/etc/shibboleth/sp-cert.pem", name: "keystone_sp_cert", file_mode: "0640", dir_mode: "0750" }
|
||||||
|
- { src: "/etc/shibboleth/sp-key.pem", name: "keystone_sp_key", file_mode: "0600", dir_mode: "0750" }
|
||||||
|
register: memcache_keys
|
||||||
|
until: memcache_keys|success
|
||||||
|
retries: 5
|
||||||
|
delay: 2
|
||||||
|
when: inventory_hostname != groups['keystone_all'][0]
|
||||||
|
notify:
|
||||||
|
- Restart Apache
|
||||||
|
- Restart Shibd
|
||||||
|
tags:
|
||||||
|
- keystone-config
|
||||||
|
- keystone-federation-sp
|
||||||
|
|
||||||
|
- name: Set appropriate file ownership on the Shibboleth SP key-pair
|
||||||
|
file:
|
||||||
|
path: "{{ item }}"
|
||||||
|
owner: "_shibd"
|
||||||
|
group: "_shibd"
|
||||||
|
with_items:
|
||||||
|
- "/etc/shibboleth/sp-cert.pem"
|
||||||
|
- "/etc/shibboleth/sp-key.pem"
|
||||||
|
when: inventory_hostname != groups['keystone_all'][0]
|
||||||
|
notify:
|
||||||
|
- Restart Apache
|
||||||
|
- Restart Shibd
|
||||||
|
tags:
|
||||||
|
- keystone-config
|
||||||
|
- keystone-federation-sp
|
@ -49,6 +49,19 @@
|
|||||||
tags:
|
tags:
|
||||||
- keystone-apt-packages
|
- keystone-apt-packages
|
||||||
|
|
||||||
|
- name: Install SP apt packages
|
||||||
|
apt:
|
||||||
|
pkg: "{{ item }}"
|
||||||
|
state: latest
|
||||||
|
register: install_packages
|
||||||
|
until: install_packages|success
|
||||||
|
retries: 5
|
||||||
|
delay: 2
|
||||||
|
with_items: keystone_sp_apt_packages
|
||||||
|
when: keystone_sp is defined
|
||||||
|
tags:
|
||||||
|
- keystone-apt-packages
|
||||||
|
|
||||||
- name: Install pip packages
|
- name: Install pip packages
|
||||||
pip:
|
pip:
|
||||||
name: "{{ item }}"
|
name: "{{ item }}"
|
||||||
|
@ -36,6 +36,7 @@
|
|||||||
mode: "{{ item.mode|default('0644') }}"
|
mode: "{{ item.mode|default('0644') }}"
|
||||||
with_items:
|
with_items:
|
||||||
- { src: "keystone-paste.ini", dest: "/etc/keystone/keystone-paste.ini" }
|
- { src: "keystone-paste.ini", dest: "/etc/keystone/keystone-paste.ini" }
|
||||||
|
- { src: "sso_callback_template.html", dest: "/etc/keystone/sso_callback_template.html" }
|
||||||
- { src: "keystone-wsgi.py", dest: "/var/www/cgi-bin/keystone/admin", mode: "0755" }
|
- { src: "keystone-wsgi.py", dest: "/var/www/cgi-bin/keystone/admin", mode: "0755" }
|
||||||
- { src: "keystone-wsgi.py", dest: "/var/www/cgi-bin/keystone/main", mode: "0755" }
|
- { src: "keystone-wsgi.py", dest: "/var/www/cgi-bin/keystone/main", mode: "0755" }
|
||||||
notify:
|
notify:
|
||||||
|
@ -29,6 +29,10 @@
|
|||||||
|
|
||||||
- include: keystone_post_install.yml
|
- include: keystone_post_install.yml
|
||||||
|
|
||||||
|
- include: keystone_federation_sp_setup.yml
|
||||||
|
when: >
|
||||||
|
keystone_sp is defined
|
||||||
|
|
||||||
- include: keystone_db_setup.yml
|
- include: keystone_db_setup.yml
|
||||||
when: >
|
when: >
|
||||||
inventory_hostname == groups['keystone_all'][0]
|
inventory_hostname == groups['keystone_all'][0]
|
||||||
@ -40,6 +44,11 @@
|
|||||||
when: >
|
when: >
|
||||||
inventory_hostname == groups['keystone_all'][0]
|
inventory_hostname == groups['keystone_all'][0]
|
||||||
|
|
||||||
|
- include: keystone_federation_sp_idp_setup.yml
|
||||||
|
when: >
|
||||||
|
keystone_sp is defined and
|
||||||
|
inventory_hostname == groups['keystone_all'][0]
|
||||||
|
|
||||||
- name: Flush handlers
|
- name: Flush handlers
|
||||||
meta: flush_handlers
|
meta: flush_handlers
|
||||||
|
|
||||||
|
@ -25,6 +25,32 @@ WSGIDaemonProcess keystone user={{ keystone_system_user_name }} group=nogroup pr
|
|||||||
SSLOptions +StdEnvVars +ExportCertData
|
SSLOptions +StdEnvVars +ExportCertData
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
|
{% if keystone_sp is defined -%}
|
||||||
|
ShibURLScheme {{ keystone_service_publicuri_proto }}
|
||||||
|
|
||||||
|
<Location /Shibboleth.sso>
|
||||||
|
SetHandler shib
|
||||||
|
</Location>
|
||||||
|
|
||||||
|
<Location /v3/auth/OS-FEDERATION/websso/saml2>
|
||||||
|
AuthType shibboleth
|
||||||
|
ShibRequestSetting requireSession 1
|
||||||
|
ShibRequestSetting exportAssertion 1
|
||||||
|
ShibRequireSession On
|
||||||
|
ShibExportAssertion On
|
||||||
|
Require valid-user
|
||||||
|
</Location>
|
||||||
|
|
||||||
|
<LocationMatch /v3/OS-FEDERATION/identity_providers/.*?/protocols/saml2/auth>
|
||||||
|
ShibRequestSetting requireSession 1
|
||||||
|
AuthType shibboleth
|
||||||
|
ShibExportAssertion Off
|
||||||
|
Require valid-user
|
||||||
|
</LocationMatch>
|
||||||
|
|
||||||
|
WSGIScriptAliasMatch ^(/v3/OS-FEDERATION/identity_providers/.*?/protocols/.*?/auth)$ /var/www/cgi-bin/keystone/main/$1
|
||||||
|
{%- endif %}
|
||||||
|
|
||||||
WSGIScriptAlias / /var/www/cgi-bin/keystone/main
|
WSGIScriptAlias / /var/www/cgi-bin/keystone/main
|
||||||
WSGIProcessGroup keystone
|
WSGIProcessGroup keystone
|
||||||
</VirtualHost>
|
</VirtualHost>
|
||||||
|
@ -43,8 +43,12 @@ cache_time = {{ keystone_revocation_cache_time }}
|
|||||||
|
|
||||||
|
|
||||||
[auth]
|
[auth]
|
||||||
|
{% if keystone_sp is defined %}
|
||||||
|
methods = {{ keystone_auth_methods }},saml2
|
||||||
|
saml2 = keystone.auth.plugins.mapped.Mapped
|
||||||
|
{% else %}
|
||||||
methods = {{ keystone_auth_methods }}
|
methods = {{ keystone_auth_methods }}
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
[database]
|
[database]
|
||||||
connection = mysql://{{ keystone_galera_user }}:{{ keystone_container_mysql_password }}@{{ keystone_galera_address }}/{{ keystone_galera_database }}?charset=utf8
|
connection = mysql://{{ keystone_galera_user }}:{{ keystone_container_mysql_password }}@{{ keystone_galera_address }}/{{ keystone_galera_database }}?charset=utf8
|
||||||
@ -132,3 +136,13 @@ public_port = {{ keystone_service_port }}
|
|||||||
rabbit_hosts = {{ rabbitmq_servers }}
|
rabbit_hosts = {{ rabbitmq_servers }}
|
||||||
rabbit_userid = {{ rabbitmq_userid }}
|
rabbit_userid = {{ rabbitmq_userid }}
|
||||||
rabbit_password = {{ rabbitmq_password }}
|
rabbit_password = {{ rabbitmq_password }}
|
||||||
|
|
||||||
|
{% if keystone_sp is defined %}
|
||||||
|
[federation]
|
||||||
|
remote_id_attribute = Shib-Identity-Provider
|
||||||
|
{% if keystone_sp.trusted_dashboard_list is defined %}
|
||||||
|
{% for item in keystone_sp.trusted_dashboard_list %}
|
||||||
|
trusted_dashboard = {{ item }}
|
||||||
|
{% endfor %}
|
||||||
|
{% endif %}
|
||||||
|
{% endif %}
|
||||||
|
@ -0,0 +1,63 @@
|
|||||||
|
<Attributes xmlns="urn:mace:shibboleth:2.0:attribute-map"
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
||||||
|
|
||||||
|
<!--
|
||||||
|
The below default attributes are standard for a Shibboleth
|
||||||
|
Identity Provider and will likely work with many other
|
||||||
|
standard SAML2 Identity Providers.
|
||||||
|
-->
|
||||||
|
|
||||||
|
<Attribute name="urn:mace:dir:attribute-def:eduPersonPrincipalName" id="eppn">
|
||||||
|
<AttributeDecoder xsi:type="ScopedAttributeDecoder"/>
|
||||||
|
</Attribute>
|
||||||
|
<Attribute name="urn:oid:1.3.6.1.4.1.5923.1.1.1.6" id="eppn">
|
||||||
|
<AttributeDecoder xsi:type="ScopedAttributeDecoder"/>
|
||||||
|
</Attribute>
|
||||||
|
|
||||||
|
<Attribute name="urn:mace:dir:attribute-def:eduPersonScopedAffiliation" id="affiliation">
|
||||||
|
<AttributeDecoder xsi:type="ScopedAttributeDecoder" caseSensitive="false"/>
|
||||||
|
</Attribute>
|
||||||
|
<Attribute name="urn:oid:1.3.6.1.4.1.5923.1.1.1.9" id="affiliation">
|
||||||
|
<AttributeDecoder xsi:type="ScopedAttributeDecoder" caseSensitive="false"/>
|
||||||
|
</Attribute>
|
||||||
|
|
||||||
|
<Attribute name="urn:mace:dir:attribute-def:eduPersonAffiliation" id="unscoped-affiliation">
|
||||||
|
<AttributeDecoder xsi:type="StringAttributeDecoder" caseSensitive="false"/>
|
||||||
|
</Attribute>
|
||||||
|
<Attribute name="urn:oid:1.3.6.1.4.1.5923.1.1.1.1" id="unscoped-affiliation">
|
||||||
|
<AttributeDecoder xsi:type="StringAttributeDecoder" caseSensitive="false"/>
|
||||||
|
</Attribute>
|
||||||
|
|
||||||
|
<Attribute name="urn:mace:dir:attribute-def:eduPersonEntitlement" id="entitlement"/>
|
||||||
|
<Attribute name="urn:oid:1.3.6.1.4.1.5923.1.1.1.7" id="entitlement"/>
|
||||||
|
|
||||||
|
<!-- A persistent id attribute that supports personalized anonymous access. -->
|
||||||
|
|
||||||
|
<Attribute name="urn:mace:dir:attribute-def:eduPersonTargetedID" id="targeted-id">
|
||||||
|
<AttributeDecoder xsi:type="ScopedAttributeDecoder"/>
|
||||||
|
</Attribute>
|
||||||
|
|
||||||
|
<Attribute name="urn:oid:1.3.6.1.4.1.5923.1.1.1.10" id="persistent-id">
|
||||||
|
<AttributeDecoder xsi:type="NameIDAttributeDecoder" formatter="$NameQualifier!$SPNameQualifier!$Name" defaultQualifiers="true"/>
|
||||||
|
</Attribute>
|
||||||
|
|
||||||
|
<Attribute name="urn:oasis:names:tc:SAML:2.0:nameid-format:persistent" id="persistent-id">
|
||||||
|
<AttributeDecoder xsi:type="NameIDAttributeDecoder" formatter="$NameQualifier!$SPNameQualifier!$Name" defaultQualifiers="true"/>
|
||||||
|
</Attribute>
|
||||||
|
|
||||||
|
<!--
|
||||||
|
The following attributes have been configured through Ansible.
|
||||||
|
-->
|
||||||
|
{% for idp in keystone_sp.trusted_idp_list %}
|
||||||
|
{% if idp.protocols is defined %}
|
||||||
|
{% for protocol in idp.protocols %}
|
||||||
|
{% if protocol.name == "saml2" and protocol.attributes is defined %}
|
||||||
|
{% for attr in protocol.attributes %}
|
||||||
|
<Attribute{% for k in attr %} {{ k }}="{{ attr[k] }}"{% endfor %}/>
|
||||||
|
{% endfor %}
|
||||||
|
{% endif %}
|
||||||
|
{% endfor %}
|
||||||
|
{% endif %}
|
||||||
|
{% endfor %}
|
||||||
|
|
||||||
|
</Attributes>
|
104
playbooks/roles/os_keystone/templates/shibboleth2.xml.j2
Normal file
104
playbooks/roles/os_keystone/templates/shibboleth2.xml.j2
Normal file
@ -0,0 +1,104 @@
|
|||||||
|
<SPConfig xmlns="urn:mace:shibboleth:2.0:native:sp:config"
|
||||||
|
xmlns:conf="urn:mace:shibboleth:2.0:native:sp:config"
|
||||||
|
xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion"
|
||||||
|
xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol"
|
||||||
|
xmlns:md="urn:oasis:names:tc:SAML:2.0:metadata"
|
||||||
|
clockSkew="180">
|
||||||
|
|
||||||
|
<!-- The entityID is the name by which your IdP will know your SP. -->
|
||||||
|
<ApplicationDefaults entityID="{{ keystone_service_publicuri }}/shibboleth">
|
||||||
|
|
||||||
|
<!-- You should use secure cookies if at all possible. See cookieProps in this Wiki article. -->
|
||||||
|
<!-- https://wiki.shibboleth.net/confluence/display/SHIB2/NativeSPSessions -->
|
||||||
|
<Sessions lifetime="28800"
|
||||||
|
timeout="3600"
|
||||||
|
relayState="ss:mem"
|
||||||
|
checkAddress="false"
|
||||||
|
handlerSSL="{% if keystone_ssl_enabled | bool %}true{% else %}false{% endif %}"
|
||||||
|
{% if keystone_service_publicuri_proto == "https" %}cookieProps="; path=/; secure"{% endif %}>
|
||||||
|
|
||||||
|
<!-- Triggers a login request directly to the IdP. -->
|
||||||
|
<!-- https://wiki.shibboleth.net/confluence/display/SHIB2/NativeSPServiceSSO -->
|
||||||
|
<SSO ECP="true" entityID="{{ keystone_sp.trusted_idp_list.0.entity_ids.0 }}">
|
||||||
|
SAML2 SAML1
|
||||||
|
</SSO>
|
||||||
|
|
||||||
|
<!-- SAML and local-only logout. -->
|
||||||
|
<!-- https://wiki.shibboleth.net/confluence/display/SHIB2/NativeSPServiceLogout -->
|
||||||
|
<Logout>SAML2 Local</Logout>
|
||||||
|
|
||||||
|
<!--
|
||||||
|
Handlers allow you to interact with the SP and gather more information.
|
||||||
|
Attribute values received by the SP through SAML will be visible at:
|
||||||
|
{{ keystone_service_publicuri }}/Shibboleth.sso/Session
|
||||||
|
-->
|
||||||
|
|
||||||
|
<!-- Extension service that generates "approximate" metadata based on SP configuration. -->
|
||||||
|
<Handler type="MetadataGenerator"
|
||||||
|
Location="/Metadata"
|
||||||
|
signing="false"/>
|
||||||
|
|
||||||
|
<!-- Status reporting service. -->
|
||||||
|
<Handler type="Status" Location="/Status" acl="127.0.0.1 ::1"/>
|
||||||
|
|
||||||
|
<!-- Session diagnostic service. -->
|
||||||
|
<Handler type="Session" Location="/Session" showAttributeValues="true"/>
|
||||||
|
|
||||||
|
<!-- JSON feed of discovery information. -->
|
||||||
|
<Handler type="DiscoveryFeed" Location="/DiscoFeed"/>
|
||||||
|
</Sessions>
|
||||||
|
|
||||||
|
<!--
|
||||||
|
Allows overriding of error template information/filenames. You can
|
||||||
|
also add attributes with values that can be plugged into the templates.
|
||||||
|
-->
|
||||||
|
<Errors supportContact="root@localhost"
|
||||||
|
helpLocation="/about.html"
|
||||||
|
styleSheet="/shibboleth-sp/main.css"/>
|
||||||
|
|
||||||
|
<!--
|
||||||
|
Loads and trusts a list of metadata files which describes
|
||||||
|
the trusted IdP's and how to communicate with them.
|
||||||
|
-->
|
||||||
|
{% if keystone_sp.trusted_idp_list is defined -%}
|
||||||
|
{% for item in keystone_sp.trusted_idp_list %}
|
||||||
|
<MetadataProvider type="XML"
|
||||||
|
uri="{{ item.metadata_uri }}"
|
||||||
|
backingFilePath="{{ item.metadata_file }}"
|
||||||
|
reloadInterval="{{ item.metadata_reload }}" />
|
||||||
|
{% endfor %}
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
<!-- Map to extract attributes from SAML assertions. -->
|
||||||
|
<AttributeExtractor type="XML"
|
||||||
|
validate="true"
|
||||||
|
reloadChanges="false"
|
||||||
|
path="attribute-map.xml"/>
|
||||||
|
|
||||||
|
<!-- Use a SAML query if no attributes are supplied during SSO. -->
|
||||||
|
<AttributeResolver type="Query" subjectMatch="true"/>
|
||||||
|
|
||||||
|
<!-- Default filtering policy for recognized attributes, lets other data pass. -->
|
||||||
|
<AttributeFilter type="XML"
|
||||||
|
validate="true"
|
||||||
|
path="attribute-policy.xml"/>
|
||||||
|
|
||||||
|
<!-- Your SP generated these credentials. They're used to talk to IdP's. -->
|
||||||
|
<CredentialResolver type="File"
|
||||||
|
key="sp-key.pem"
|
||||||
|
certificate="sp-cert.pem"/>
|
||||||
|
|
||||||
|
</ApplicationDefaults>
|
||||||
|
|
||||||
|
<!-- Policies that determine how to process and authenticate runtime messages. -->
|
||||||
|
<SecurityPolicyProvider type="XML"
|
||||||
|
validate="true"
|
||||||
|
path="security-policy.xml"/>
|
||||||
|
|
||||||
|
<!-- Low-level configuration about protocols and bindings available for use. -->
|
||||||
|
<ProtocolProvider type="XML"
|
||||||
|
validate="true"
|
||||||
|
reloadChanges="false"
|
||||||
|
path="protocols.xml"/>
|
||||||
|
|
||||||
|
</SPConfig>
|
Loading…
Reference in New Issue
Block a user