From 43a2215d3c1d175eb06dfdb0c2f48326a31a2dec Mon Sep 17 00:00:00 2001 From: Felipe Reyes Date: Wed, 21 Sep 2022 18:48:08 -0300 Subject: [PATCH] Add support for websso-fid-service-provider relation. This change adds support to relate the keystone-openidc charm to openstack-dashboard allowing it expose a OpenID Connect backend for logging into Horizon. The configuration option 'user-facing-name' allows operator to set a user friendly name that gets displayed in the list of choices available for logging in. Change-Id: Ia09cb5b68bc35d25f5b012f0011697966827eb03 --- config.yaml | 6 ++++++ src/charm.py | 32 +++++++++++++++++++++----------- test-requirements.txt | 4 ++-- unit_tests/test_charm.py | 23 +++++++++++++++++++++++ 4 files changed, 52 insertions(+), 13 deletions(-) diff --git a/config.yaml b/config.yaml index 7994768..b1c04f9 100644 --- a/config.yaml +++ b/config.yaml @@ -108,3 +108,9 @@ options: OAuth 2.0 Authorization Server token introspection endpoint. When `enable-oauth` is set to true and this option unset (the default), the introspection endpoint available in the metadata will be used. + user-facing-name: + type: string + default: 'OpenID Connect via mapped' + description: | + A user-facing name to be used for the identity provider and protocol + combination. Used in the OpenStack dashboard. diff --git a/src/charm.py b/src/charm.py index 7f06315..861a35b 100755 --- a/src/charm.py +++ b/src/charm.py @@ -91,12 +91,12 @@ class KeystoneOpenIDCOptions(ConfigurationAdapter): @property def oidc_auth_path(self) -> str: - service_name = self.charm_instance.unit.app.name - return (f'/v3/OS-FEDERATION/identity_providers/{service_name}' + return (f'/v3/OS-FEDERATION/identity_providers/{self.idp_id}' f'/protocols/openid/auth') @property def idp_id(self) -> str: + """Identity provider name to use for URL generation.""" return 'openid' @property @@ -215,10 +215,6 @@ class KeystoneOpenIDCCharm(ops_openstack.core.OSBaseCharm): ) # websso-fid-service-provider - self.framework.observe( - self.on.websso_fid_service_provider_relation_joined, - self._on_websso_fid_service_provider_relation_joined - ) self.framework.observe( self.on.websso_fid_service_provider_relation_changed, self._on_websso_fid_service_provider_relation_changed @@ -269,14 +265,27 @@ class KeystoneOpenIDCCharm(ops_openstack.core.OSBaseCharm): data['remote-id-attribute'] = json.dumps( self.options.remote_id_attribute) - def _on_websso_fid_service_provider_relation_joined(self, event): - pass - def _on_websso_fid_service_provider_relation_changed(self, event): - pass + self._update_websso_data() def _update_websso_data(self): - pass + """Update websso-fid-service-provider relation data. + + When there is a relation established via websso-fid-service-provider + this handler will take care of update the relation data with the + information that openstack-dashboard expects to enable WebSSO + Federation. + """ + relation = self.model.get_relation('websso-fid-service-provider') + if not relation: + logger.debug('There is not relation established via ' + 'websso-fid-service-provider interface') + return + + data = relation.data[self.unit] + data['protocol-name'] = json.dumps(self.options.idp_id) + data['idp-name'] = json.dumps(self.options.protocol_id) + data['user-facing-name'] = json.dumps(self.options.user_facing_name) def _on_config_changed(self, event): if not self.is_data_ready(): @@ -289,6 +298,7 @@ class KeystoneOpenIDCCharm(ops_openstack.core.OSBaseCharm): self._stored.is_started = True self.update_config_if_needed() self.update_principal_data() + self._update_websso_data() def update_config_if_needed(self): with ch_host.restart_on_change( diff --git a/test-requirements.txt b/test-requirements.txt index ea74210..bbff0e9 100644 --- a/test-requirements.txt +++ b/test-requirements.txt @@ -2,5 +2,5 @@ coverage flake8 stestr git+https://github.com/openstack-charmers/zaza.git#egg=zaza -git+https://github.com/freyes/zaza-openstack-tests.git@keystone-openidc#egg=zaza.openstack -requests-mock \ No newline at end of file +git+https://github.com/openstack-charmers/zaza-openstack-tests.git#egg=zaza.openstack +requests-mock diff --git a/unit_tests/test_charm.py b/unit_tests/test_charm.py index b52fc8e..0e4fecd 100644 --- a/unit_tests/test_charm.py +++ b/unit_tests/test_charm.py @@ -1,3 +1,4 @@ +import json import logging import os import shutil @@ -177,3 +178,25 @@ class TestCharm(BaseTestCharm): m.get(WELL_KNOWN_URL, json=well_known_url_content) self.assertRaises(charm.CharmConfigError, self.harness.charm.find_missing_keys) + + def test_update_websso_data(self): + rid = self.harness.add_relation('websso-fid-service-provider', + 'openstack-dashboard') + self.harness.add_relation_unit(rid, 'openstack-dashboard/0') + self.harness.charm._update_websso_data() + data = self.harness.get_relation_data(rid, 'keystone-openidc/0') + options = self.harness.charm.options + expected = {'protocol-name': json.dumps(options.idp_id), + 'idp-name': json.dumps(options.protocol_id), + 'user-facing-name': json.dumps(options.user_facing_name)} + self.assertDictEqual(data, expected) + + # check that on config-changed the data is updated on the relation. + self.harness.update_config(key_values={'user-facing-name': 'My IdP'}) + self.harness.charm.options = charm.KeystoneOpenIDCOptions( + self.harness.charm + ) + self.harness.charm._update_websso_data() + data = self.harness.get_relation_data(rid, 'keystone-openidc/0') + expected['user-facing-name'] = json.dumps('My IdP') + self.assertDictEqual(data, expected)