Merge ~pjdc/charm-k8s-mattermost/+git/charm-k8s-mattermost:sso into charm-k8s-mattermost:master

Proposed by Paul Collins
Status: Merged
Merged at revision: 2744bd069128499f583edfa457dce656f435d8d8
Proposed branch: ~pjdc/charm-k8s-mattermost/+git/charm-k8s-mattermost:sso
Merge into: charm-k8s-mattermost:master
Prerequisite: ~pjdc/charm-k8s-mattermost/+git/charm-k8s-mattermost:readiness-probe
Diff against target: 156 lines (+68/-1)
4 files modified
README.md (+21/-0)
config.yaml (+7/-0)
src/charm.py (+35/-1)
tests/unit/test_charm.py (+5/-0)
Reviewer Review Type Date Requested Status
Paul Collins self Approve
Canonical IS Reviewers Pending
Review via email: mp+385164@code.launchpad.net

Commit message

add sso setting

To post a comment you must log in.
Revision history for this message
Paul Collins (pjdc) wrote :

Note pre-req.

Revision history for this message
🤖 Canonical IS Merge Bot (canonical-is-mergebot) wrote :

This merge proposal is being monitored by mergebot. Change the status to Approved to merge.

Revision history for this message
Tom Haddon (mthaddon) wrote :

Two small comments inline

Revision history for this message
🤖 Canonical IS Merge Bot (canonical-is-mergebot) wrote :

Change cannot be self approved, setting status to needs review.

Revision history for this message
Paul Collins (pjdc) :
review: Approve (self)
Revision history for this message
🤖 Canonical IS Merge Bot (canonical-is-mergebot) wrote :

Change cannot be self approved, setting status to needs review.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
diff --git a/README.md b/README.md
index 7394b0f..8f5220c 100644
--- a/README.md
+++ b/README.md
@@ -67,3 +67,24 @@ know what the source addresses or address range is for the next step.
6767
68(In the case of postgresql, `--via` is needed so that the charm can68(In the case of postgresql, `--via` is needed so that the charm can
69configure `pga_hba.conf` to let the k8s pods connect to the database.)69configure `pga_hba.conf` to let the k8s pods connect to the database.)
70
71## Authentication
72
73This charm supports configuring [Ubuntu SSO](https://login.ubuntu.com)
74as the authentication method. This requires the following:
75
76 * a Mattermost Enterprise Edition licence to be obtained and activated
77 * a SAML config for the Mattermost installation to be added to `login.ubuntu.com`
78 * the SAML config will need to have a new certificate generated (refer to "Canonical RT#107985" when requesting this)
79 * this is because the default certificate available via the [SAML metadata URL](https://login.ubuntu.com/+saml/metadata) has expired
80 * the new certificate to be installed in the Mattermost database (see below)
81
82### Installing the SAML Identity Provider Certificate
83
84Invoke `psql` against the mattermost database on the current primary
85and use the following query to install the certificate:
86
87 INSERT INTO configurationfiles (name, createat, updateat, data)
88 VALUES ('saml-idp.crt', (extract(epoch from now()) * 1000)::bigint ,(extract(epoch from now()) * 1000)::bigint, $$-----BEGIN CERTIFICATE-----
89 [...]
90 -----END CERTIFICATE-----$$);
diff --git a/config.yaml b/config.yaml
index e15f8cd..ae1fbef 100644
--- a/config.yaml
+++ b/config.yaml
@@ -126,3 +126,10 @@ options:
126126
127 This requires configuration on the S3 side, as well as a suitable Mattermost licence.127 This requires configuration on the S3 side, as well as a suitable Mattermost licence.
128 default: false128 default: false
129 sso:
130 type: boolean
131 description: |
132 Whether to use Ubuntu SSO to log in.
133
134 This will not work unless the administrators of login.ubuntu.com have created a suitable SAML config first.
135 default: false
diff --git a/src/charm.py b/src/charm.py
index 9b0474d..2831af0 100755
--- a/src/charm.py
+++ b/src/charm.py
@@ -43,6 +43,8 @@ DATABASE_NAME = 'mattermost'
43LICENCE_SECRET_KEY_NAME = 'licence'43LICENCE_SECRET_KEY_NAME = 'licence'
44REQUIRED_S3_SETTINGS = ['s3_bucket', 's3_region', 's3_access_key_id', 's3_secret_access_key']44REQUIRED_S3_SETTINGS = ['s3_bucket', 's3_region', 's3_access_key_id', 's3_secret_access_key']
45REQUIRED_SETTINGS = ['mattermost_image_path']45REQUIRED_SETTINGS = ['mattermost_image_path']
46REQUIRED_SSO_SETTINGS = ['licence', 'site_url']
47SAML_IDP_CRT = 'saml-idp.crt'
4648
4749
48class MattermostDBMasterAvailableEvent(EventBase):50class MattermostDBMasterAvailableEvent(EventBase):
@@ -214,7 +216,10 @@ class MattermostK8sCharm(CharmBase):
214 if config['s3_enabled']:216 if config['s3_enabled']:
215 missing.extend([setting for setting in REQUIRED_S3_SETTINGS if not config[setting]])217 missing.extend([setting for setting in REQUIRED_S3_SETTINGS if not config[setting]])
216218
217 return missing219 if config['sso']:
220 missing.extend([setting for setting in REQUIRED_SSO_SETTINGS if not config[setting]])
221
222 return sorted(list(set(missing)))
218223
219 def _make_s3_pod_config(self):224 def _make_s3_pod_config(self):
220 config = self.model.config225 config = self.model.config
@@ -358,6 +363,34 @@ class MattermostK8sCharm(CharmBase):
358363
359 return pod_spec364 return pod_spec
360365
366 def _update_pod_spec_for_sso(self, pod_spec):
367 config = self.model.config
368 if not config['sso'] or [setting for setting in REQUIRED_SSO_SETTINGS if not config[setting]]:
369 return pod_spec
370 pod_spec = copy.deepcopy(pod_spec)
371 site_hostname = urlparse(config['site_url']).hostname
372
373 pod_spec['containers'][0]['envConfig'].update({
374 'MM_SAMLSETTINGS_ENABLE': 'true',
375 'MM_SAMLSETTINGS_IDPURL': 'https://login.ubuntu.com/saml/',
376 'MM_SAMLSETTINGS_VERIFY': 'true',
377 'MM_SAMLSETTINGS_ENCRYPT': 'false', # per POC
378 'MM_SAMLSETTINGS_IDPDESCRIPTORURL': 'https://login.ubuntu.com',
379 'MM_SAMLSETTINGS_IDPMETADATAURL': 'https://login.ubuntu.com/+saml/metadata',
380 'MM_SAMLSETTINGS_ASSERTIONCONSUMERSERVICEURL': 'https://{}/login/sso/saml'.format(site_hostname),
381 'MM_SAMLSETTINGS_LOGINBUTTONTEXT': 'Ubuntu SSO',
382 'MM_SAMLSETTINGS_EMAILATTRIBUTE': 'email',
383 'MM_SAMLSETTINGS_USERNAMEATTRIBUTE': 'username',
384 'MM_SAMLSETTINGS_IDATTRIBUTE': 'openid',
385 'MM_SAMLSETTINGS_FIRSTNAMEATTRIBUTE': 'fullname',
386 'MM_SAMLSETTINGS_LASTNAMEATTRIBUTE': '',
387 'MM_SAMLSETTINGS_IDPCERTIFICATEFILE': SAML_IDP_CRT,
388 # Otherwise we have to install xmlsec1 and Mattermost forks on every login(!).
389 'MM_EXPERIMENTALSETTINGS_USENEWSAMLLIBRARY': 'true',
390 })
391
392 return pod_spec
393
361 def configure_pod(self, event):394 def configure_pod(self, event):
362 if not state_get('db_uri'):395 if not state_get('db_uri'):
363 self.unit.status = WaitingStatus('Waiting for database relation')396 self.unit.status = WaitingStatus('Waiting for database relation')
@@ -378,6 +411,7 @@ class MattermostK8sCharm(CharmBase):
378 pod_spec = self._update_pod_spec_for_k8s_ingress(pod_spec)411 pod_spec = self._update_pod_spec_for_k8s_ingress(pod_spec)
379 pod_spec = self._update_pod_spec_for_licence(pod_spec)412 pod_spec = self._update_pod_spec_for_licence(pod_spec)
380 pod_spec = self._update_pod_spec_for_clustering(pod_spec)413 pod_spec = self._update_pod_spec_for_clustering(pod_spec)
414 pod_spec = self._update_pod_spec_for_sso(pod_spec)
381415
382 self.unit.status = MaintenanceStatus('Setting pod spec')416 self.unit.status = MaintenanceStatus('Setting pod spec')
383 self.model.pod.set_spec(pod_spec)417 self.model.pod.set_spec(pod_spec)
diff --git a/tests/unit/test_charm.py b/tests/unit/test_charm.py
index 8a970b6..7e8c809 100644
--- a/tests/unit/test_charm.py
+++ b/tests/unit/test_charm.py
@@ -20,6 +20,7 @@ CONFIG_IMAGE_NO_CREDS = {
20 'mattermost_image_username': '',20 'mattermost_image_username': '',
21 'mattermost_image_password': '',21 'mattermost_image_password': '',
22 's3_enabled': False,22 's3_enabled': False,
23 'sso': False,
23}24}
2425
25CONFIG_IMAGE_NO_IMAGE = {26CONFIG_IMAGE_NO_IMAGE = {
@@ -28,6 +29,7 @@ CONFIG_IMAGE_NO_IMAGE = {
28 'mattermost_image_username': '',29 'mattermost_image_username': '',
29 'mattermost_image_password': '',30 'mattermost_image_password': '',
30 's3_enabled': False,31 's3_enabled': False,
32 'sso': False,
31}33}
3234
33CONFIG_IMAGE_NO_PASSWORD = {35CONFIG_IMAGE_NO_PASSWORD = {
@@ -36,6 +38,7 @@ CONFIG_IMAGE_NO_PASSWORD = {
36 'mattermost_image_username': 'production',38 'mattermost_image_username': 'production',
37 'mattermost_image_password': '',39 'mattermost_image_password': '',
38 's3_enabled': False,40 's3_enabled': False,
41 'sso': False,
39}42}
4043
41CONFIG_NO_S3_SETTINGS_S3_ENABLED = {44CONFIG_NO_S3_SETTINGS_S3_ENABLED = {
@@ -49,6 +52,7 @@ CONFIG_NO_S3_SETTINGS_S3_ENABLED = {
49 's3_region': '',52 's3_region': '',
50 's3_access_key_id': '',53 's3_access_key_id': '',
51 's3_secret_access_key': '',54 's3_secret_access_key': '',
55 'sso': False,
52}56}
5357
54CONFIG_NO_S3_SETTINGS_S3_DISABLED_NO_DEFAULTS = {58CONFIG_NO_S3_SETTINGS_S3_DISABLED_NO_DEFAULTS = {
@@ -57,6 +61,7 @@ CONFIG_NO_S3_SETTINGS_S3_DISABLED_NO_DEFAULTS = {
57 'mattermost_image_username': '',61 'mattermost_image_username': '',
58 'mattermost_image_password': '',62 'mattermost_image_password': '',
59 's3_enabled': False,63 's3_enabled': False,
64 'sso': False,
60}65}
6166
62RANGE_BAD = '10.242.0.0/8,91.189.92.242/25'67RANGE_BAD = '10.242.0.0/8,91.189.92.242/25'

Subscribers

People subscribed via source and target branches