diff --git a/config.yaml b/config.yaml index a0c4a8c49f97d21a8f4e5fe75535e2917b000681..57f8e2ce848ea8baa921ce7e2ea477ba25a8761f 100644 --- a/config.yaml +++ b/config.yaml @@ -318,6 +318,12 @@ options: type: string default: description: ID of the federation identity provider (e.g., idem-fed) + shibsp-idp-entity-id: + type: string + default: + description: | + String used for keystone registration in SAML federation, defaults + to <keystone_publicname_url>/shibboleth shibsp-idp-remote-ids: type: string default: diff --git a/hooks/keystone_context.py b/hooks/keystone_context.py index c194a2b753c222d639a1597e0be99dd344a411d4..698c73b70fcb0f59a59ac4ba2cbeb1f2c0377651 100644 --- a/hooks/keystone_context.py +++ b/hooks/keystone_context.py @@ -418,15 +418,13 @@ class TokenFlushContext(context.OSContextGenerator): class IdpFetchContext(context.OSContextGenerator): def __call__(self): - from keystone_utils import ( - REMOTE_IDS_FETCH_SCRIPT, get_api_suffix, + from keystone_utils import (get_api_suffix, api_port, endpoint_url, resolve_address, ADMIN, ) ctxt = { 'enable_saml2': config('enable-saml2'), 'remote_ids_fetch': is_elected_leader(DC_RESOURCE_NAME) and config('shibsp-idp-remote-ids-fetch'), - 'fetch_script': REMOTE_IDS_FETCH_SCRIPT, 'identity_provider': config('shibsp-identity-provider'), 'keystone_endpoint': endpoint_url(resolve_address(ADMIN), api_port('keystone-admin'), diff --git a/hooks/keystone_hooks.py b/hooks/keystone_hooks.py index e24aec2d3913c75d65fa0c2df9431f4c0c287a7d..3e531eee171522d0ebc7665a43d3e222f7216f8e 100755 --- a/hooks/keystone_hooks.py +++ b/hooks/keystone_hooks.py @@ -101,8 +101,6 @@ from keystone_utils import ( SHIBSP_FILES, OIDC_MAPPING_FILE, SAML2_MAPPING_FILE, - REMOTE_IDS_FETCH_CRON_FILE, - REMOTE_IDS_FETCH_SCRIPT, install_apache_error_handler, restart_pid_check, get_api_version, @@ -490,8 +488,6 @@ def leader_elected(): # When the local unit has been elected the leader, update the cron jobs # to ensure that the cron jobs are active on this unit. CONFIGS.write(TOKEN_FLUSH_CRON_FILE) - if config('enable-saml2'): - CONFIGS.write(REMOTE_IDS_FETCH_CRON_FILE) update_all_identity_relation_units() @@ -503,8 +499,6 @@ def leader_settings_changed(): # leader-settings-changed hook, rewrite the token flush cron job to make # sure only the leader is running the cron job. CONFIGS.write(TOKEN_FLUSH_CRON_FILE) - if config('enable-saml2'): - CONFIGS.write(REMOTE_IDS_FETCH_CRON_FILE) update_all_identity_relation_units() @@ -804,8 +798,6 @@ def configure_saml2(): SAML2_MAPPING_FILE, config('saml2-mapping'), 'saml2') - ensure_permissions(REMOTE_IDS_FETCH_SCRIPT, - user='keystone', group='keystone', perms=0o744) samlContext = SamlContext() samlContext.configure() diff --git a/hooks/keystone_utils.py b/hooks/keystone_utils.py index b40b050f328fea9f395cd462346f6d187ea71a75..f248ab406ea5da33a663e776605efaf6c34aaf47 100644 --- a/hooks/keystone_utils.py +++ b/hooks/keystone_utils.py @@ -205,8 +205,6 @@ OIDC_MAPPING_FILE = '/etc/keystone/oidc_mapping.json' SAML2_MAPPING_FILE = '/etc/keystone/saml2_mapping.json' APACHE_ERROR_FILES = ['/etc/apache2/conf-enabled/401.conf', '/var/www/html/401.html'] -REMOTE_IDS_FETCH_CRON_FILE = '/etc/cron.daily/remote-ids-fetch' -REMOTE_IDS_FETCH_SCRIPT = '/etc/keystone/remote-ids-fetch.py' SSH_USER = 'juju_keystone' KEYSTONE_USER = 'keystone' SSL_CA_NAME = 'Ubuntu Cloud' @@ -527,15 +525,6 @@ def resource_map(): 'services': [] # shibd should be restarted, but since # it is slow, we do it in config_changed_postupgrade(). } - resource_map[REMOTE_IDS_FETCH_CRON_FILE] = { - 'contexts': [keystone_context.IdpFetchContext(), - context.SyslogContext()], - 'services': [], - } - resource_map[REMOTE_IDS_FETCH_SCRIPT] = { - 'contexts': [keystone_context.IdpFetchContext()], - 'services': [], - } if config('enable-oidc'): log("Add OIDC file mapping to resource_map", level=INFO) diff --git a/templates/mitaka/shibboleth2.xml b/templates/mitaka/shibboleth2.xml index e5ab15cbbd435b2abae4d561ae92231fe93ffb81..39793a8c9be13cdc698f4d86b72afdf7d65a1332 100644 --- a/templates/mitaka/shibboleth2.xml +++ b/templates/mitaka/shibboleth2.xml @@ -87,7 +87,9 @@ uri="{{ saml2_metadata_url }}" backingFilePath="{{ saml2_metadata_bck_file }}" reloadInterval="7200"> + <!-- <MetadataFilter type="Signature" certificate="metadata/{{ saml2_metadata_signer_bck_file }}"/> + --> <MetadataFilter type="EntityRoleWhiteList"> <RetainedRole>md:IDPSSODescriptor</RetainedRole> <RetainedRole>md:AttributeAuthorityDescriptor</RetainedRole> diff --git a/templates/ocata/policy.json b/templates/ocata/policy.json index 95e898327209f7758caa86d87b7a89dd1a41273a..a0236b747f160367ce2366baad11fdd6edfa69ba 100644 --- a/templates/ocata/policy.json +++ b/templates/ocata/policy.json @@ -2,8 +2,10 @@ { "admin_required": "role:{{ admin_role }}", "cloud_admin": "rule:admin_required and (is_admin_project:True or domain_id:{{ admin_domain_id }} or project_id:{{ service_tenant_id }})", -#GARR - "admin_or_cloud_admin": "rule:admin_required or rule:cloud_admin", +#GARR Roles + "reg_admin_required": "role:Region_admin", + "dom_admin_required": "role:Domain_admin", + "prj_admin_required": "role:Project_admin", #### "service_role": "role:service", "service_or_admin": "rule:admin_required or rule:service_role", @@ -13,7 +15,6 @@ "service_admin_or_owner": "rule:service_or_admin or rule:owner", "default": "rule:admin_required", - "identity:get_region": "", "identity:list_regions": "", "identity:create_region": "rule:cloud_admin", @@ -33,6 +34,7 @@ "identity:delete_endpoint": "rule:cloud_admin", "identity:get_domain": "rule:cloud_admin or rule:admin_and_matching_domain_id or token.project.domain.id:%(target.domain.id)s", + "identity:get_domain": "", "identity:list_domains": "rule:cloud_admin", "identity:create_domain": "rule:cloud_admin", "identity:update_domain": "rule:cloud_admin", @@ -40,26 +42,22 @@ "admin_and_matching_target_project_domain_id": "rule:admin_required and domain_id:%(target.project.domain_id)s", "admin_and_matching_project_domain_id": "rule:admin_required and domain_id:%(project.domain_id)s", -#GARR # "identity:get_project": "rule:cloud_admin or rule:admin_and_matching_target_project_domain_id or project_id:%(target.project.id)s", - "identity:get_project": "rule:admin_or_cloud_admin or rule:admin_and_matching_target_project_domain_id or project_id:%(target.project.id)s", + "identity:get_project": "rule:cloud_admin or rule:admin_and_matching_target_project_domain_id or rule:admin_required or project_id:%(target.project.id)s", # "identity:list_projects": "rule:cloud_admin or rule:admin_and_matching_domain_id", - "identity:list_projects": "rule:admin_or_cloud_admin or rule:admin_and_matching_domain_id", -# "identity:create_project": "rule:cloud_admin or rule:admin_and_matching_project_domain_id", + "identity:list_projects": "rule:admin_required or rule:cloud_admin or rule:admin_and_matching_domain_id", + "identity:list_user_projects": "rule:cloud_admin or rule:owner or rule:admin_and_matching_domain_id", + "identity:create_project": "rule:admin_required or rule:cloud_admin or rule:admin_and_matching_project_domain_id", # "identity:update_project": "rule:cloud_admin or rule:admin_and_matching_target_project_domain_id", + "identity:update_project": "rule:admin_required or rule:cloud_admin or rule:admin_and_matching_target_project_domain_id", # "identity:delete_project": "rule:cloud_admin or rule:admin_and_matching_target_project_domain_id", - "identity:create_project": "rule:cloud_admin", - "identity:delete_project": "rule:cloud_admin, -#### - "identity:update_project": "rule:cloud_admin or rule:admin_and_matching_target_project_domain_id", - "identity:list_user_projects": "rule:owner or rule:admin_and_matching_domain_id", + "identity:delete_project": "rule:cloud_admin or rule:admin_and_matching_target_project_domain_id or rule:admin_required and project_id:%(project_id)s", + "admin_and_matching_target_user_domain_id": "rule:admin_required and domain_id:%(target.user.domain_id)s", "admin_and_matching_user_domain_id": "rule:admin_required and domain_id:%(user.domain_id)s", "identity:get_user": "rule:cloud_admin or rule:admin_and_matching_target_user_domain_id or rule:owner", -#GARR # "identity:list_users": "rule:cloud_admin or rule:admin_and_matching_domain_id", - "identity:list_users": "rule:admin_or_cloud_admin or rule:admin_and_matching_domain_id", -#### + "identity:list_users": "rule:admin_required or rule:cloud_admin or rule:admin_and_matching_domain_id", "identity:create_user": "rule:cloud_admin or rule:admin_and_matching_user_domain_id", "identity:update_user": "rule:cloud_admin or rule:admin_and_matching_target_user_domain_id", "identity:delete_user": "rule:cloud_admin or rule:admin_and_matching_target_user_domain_id", @@ -67,9 +65,8 @@ "admin_and_matching_target_group_domain_id": "rule:admin_required and domain_id:%(target.group.domain_id)s", "admin_and_matching_group_domain_id": "rule:admin_required and domain_id:%(group.domain_id)s", "identity:get_group": "rule:cloud_admin or rule:admin_and_matching_target_group_domain_id", -#GARR # "identity:list_groups": "rule:cloud_admin or rule:admin_and_matching_domain_id", - "identity:list_groups": "rule:admin_or_cloud_admin or rule:admin_and_matching_domain_id", + "identity:list_groups": "rule:admin_required or rule:cloud_admin or rule:admin_and_matching_domain_id", "identity:list_groups_for_user": "rule:owner or rule:admin_and_matching_target_user_domain_id", "identity:create_group": "rule:cloud_admin or rule:admin_and_matching_group_domain_id", "identity:update_group": "rule:cloud_admin or rule:admin_and_matching_target_group_domain_id", @@ -120,26 +117,31 @@ "identity:check_grant": "rule:cloud_admin or rule:domain_admin_for_grants or rule:project_admin_for_grants", "identity:list_grants": "rule:cloud_admin or rule:domain_admin_for_list_grants or rule:project_admin_for_list_grants", - "identity:create_grant": "rule:cloud_admin or rule:domain_admin_for_grants or rule:project_admin_for_grants", +# "identity:create_grant": "rule:cloud_admin or rule:domain_admin_for_grants or rule:project_admin_for_grants", + "identity:create_grant": "rule:cloud_admin_grant_reg_adm or rule:reg_admin_grant_dom_adm or rule:dom_admin_grant_prj_adm or rule:admin_grant_member", "identity:revoke_grant": "rule:cloud_admin or rule:domain_admin_for_grants or rule:project_admin_for_grants", "domain_admin_for_grants": "rule:domain_admin_for_global_role_grants or rule:domain_admin_for_domain_role_grants", "domain_admin_for_global_role_grants": "rule:admin_required and None:%(target.role.domain_id)s and rule:domain_admin_grant_match", "domain_admin_for_domain_role_grants": "rule:admin_required and domain_id:%(target.role.domain_id)s and rule:domain_admin_grant_match", "domain_admin_grant_match": "domain_id:%(domain_id)s or domain_id:%(target.project.domain_id)s", "project_admin_for_grants": "rule:project_admin_for_global_role_grants or rule:project_admin_for_domain_role_grants", - "project_admin_for_global_role_grants": "rule:admin_required and None:%(target.role.domain_id)s and project_id:%(project_id)s", + "project_admin_for_global_role_grants": "rule:admin_required and None:%(target.role.domain_id)s and project_id:%(target.project.id)s", "project_admin_for_domain_role_grants": "rule:admin_required and project_domain_id:%(target.role.domain_id)s and project_id:%(project_id)s", "domain_admin_for_list_grants": "rule:admin_required and rule:domain_admin_grant_match", "project_admin_for_list_grants": "rule:admin_required and project_id:%(project_id)s", + "cloud_admin_grant_reg_adm": "rule:cloud_admin", + "reg_admin_grant_dom_adm": "role:Region_admin and rule:dom_prj_mem", + "dom_admin_grant_prj_adm": "role:admin and rule:prj_mem", + "admin_grant_member": "role:admin and 'Member':%(target.role.name)s", + "dom_prj_mem":"'Member':%(target.role.name)s or 'Project_admin':%(target.role.name)s or 'Domain_admin':%(target.role.name)s", + "prj_mem":"'Member':%(target.role.name)s or 'Project_admin':%(target.role.name)s", "admin_on_domain_filter" : "rule:admin_required and domain_id:%(scope.domain.id)s", "admin_on_project_filter" : "rule:admin_required and project_id:%(scope.project.id)s", "admin_on_domain_of_project_filter" : "rule:admin_required and domain_id:%(target.project.domain_id)s", "identity:list_role_assignments": "rule:cloud_admin or rule:admin_on_domain_filter or rule:admin_on_project_filter", -#GARR # "identity:list_role_assignments_for_tree": "rule:cloud_admin or rule:admin_on_domain_of_project_filter", - "identity:list_role_assignments_for_tree": "rule:admin_or_cloud_admin or rule:admin_on_domain_of_project_filter", -#### + "identity:list_role_assignments_for_tree": "rule:cloud_admin or rule:admin_required", "identity:get_policy": "rule:cloud_admin", "identity:list_policies": "rule:cloud_admin", "identity:create_policy": "rule:cloud_admin", diff --git a/templates/remote-ids-fetch b/templates/remote-ids-fetch deleted file mode 100644 index 949277e47b0ca7cb0a35a9c28b0ab0df6cc6f047..0000000000000000000000000000000000000000 --- a/templates/remote-ids-fetch +++ /dev/null @@ -1,10 +0,0 @@ -# Retrieve daily the list of remote ids of the federation identity provider. -{% if remote_ids_fetch -%} -{% if use_syslog -%} -55 8 * * * keystone {{ fetch_script }} 2>&1 | logger -t remote-ids-fetch -{% else -%} -55 8 * * * keystone {{ fetch_script }} >> /var/log/keystone/remote-ids-fetch.log 2>&1 -{% endif -%} -{% else -%} -# Current unit is not the leader unit. IdP list fetch will be managed by the leader unit. -{% endif -%} diff --git a/templates/remote-ids-fetch.py b/templates/remote-ids-fetch.py deleted file mode 100644 index 7f2f8157922b4a629fbad5ddc60f0baf8252fa98..0000000000000000000000000000000000000000 --- a/templates/remote-ids-fetch.py +++ /dev/null @@ -1,85 +0,0 @@ -#! /usr/bin/env python -""" -Collect the list of remote ids for an IdP and add/update the IdP to the keystone identity providers. -""" - -from __future__ import print_function - -import requests -import sys -# See: https://docs.openstack.org/keystoneauth/latest/api/keystoneauth1.identity.v3.html#module-keystoneauth1.identity.v3.federation -# keystoneclient deprecated for keystoneauth1 -# Does not work with admin token: -# from keystoneauth1.v3.federation import identity_providers -# from keystoneauth1.identity import v3 -# from keystoneauth1.session import Session -# from keystoneclient.v3.client import Client - -keystone_uri = '{{ keystone_endpoint }}' - -def get_admin_token(): - """Temporary utility to grab the admin token as configured in - keystone.conf - """ - KEYSTONE_CONF = "/etc/keystone/keystone.conf" - with open(KEYSTONE_CONF, 'r') as f: - for l in f.readlines(): - if l.split(' ')[0] == 'admin_token': - try: - return l.split('=')[1].strip() - except: - print('Could not parse admin_token line from %s' % - KEYSTONE_CONF) - print('Could not find admin_token line in %s' % KEYSTONE_CONF) - -# We could get the token from the context, but it is preferable not to store it into other files. -# token = '{{ token }}' -token = get_admin_token() - -# Does not work with admin token: -# auth = v3.Token(keystone_uri, token) -# session = Session(auth=auth) -# ks = Client(session=session) -# idp_manager = identity_providers.IdentityProviderManager(ks) - -remote_ids_fetch = '{{ remote_ids_fetch }}' -idp = '{{ identity_provider }}' - -data = { - "identity_provider": { - "remote_ids": [], - "enabled": True - } -} - -r = requests.get(remote_ids_fetch, verify=False) -if r.ok: - remote_ids = list({e['entityID'] for e in r.json()}) -else: - print("ERROR failed to connect to " + remote_ids_fetch) - sys.exit(1) - -# patch for HTTP error 413, Request Entity Too Large, when payload exceeds 120000 bytes. -remote_ids = remote_ids[:2550] - -# Does not work with admin token: -# idp_manager.delete(idp) -# idp_manager.create(idp, remote_ids=remote_ids, enabled=True) - -idp_uri = keystone_uri + '/OS-FEDERATION/identity_providers/' + idp -headers = {"X-Auth-Token": token} -data["identity_provider"]["remote_ids"] = remote_ids -# check whether present: -r = requests.get(idp_uri, headers=headers) -if r.ok: - # PATCH /OS-FEDERATION/identity_providers/$identity_provider - r = requests.patch(idp_uri, json=data, headers=headers) -else: - # PUT /OS-FEDERATION/identity_providers/$identity_provider - r = requests.put(idp_uri, json=data, headers=headers) - -# goes into /var/log/keystone/remote-ids-fetch.log -if r.ok: - print("INFO updated IdP %s: %s" % (idp, r.text)) -else: - print("ERROR updating IdP %s: %s" % (idp, r.text))