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
1diff --git a/README.md b/README.md
2index 7394b0f..8f5220c 100644
3--- a/README.md
4+++ b/README.md
5@@ -67,3 +67,24 @@ know what the source addresses or address range is for the next step.
6
7 (In the case of postgresql, `--via` is needed so that the charm can
8 configure `pga_hba.conf` to let the k8s pods connect to the database.)
9+
10+## Authentication
11+
12+This charm supports configuring [Ubuntu SSO](https://login.ubuntu.com)
13+as the authentication method. This requires the following:
14+
15+ * a Mattermost Enterprise Edition licence to be obtained and activated
16+ * a SAML config for the Mattermost installation to be added to `login.ubuntu.com`
17+ * the SAML config will need to have a new certificate generated (refer to "Canonical RT#107985" when requesting this)
18+ * this is because the default certificate available via the [SAML metadata URL](https://login.ubuntu.com/+saml/metadata) has expired
19+ * the new certificate to be installed in the Mattermost database (see below)
20+
21+### Installing the SAML Identity Provider Certificate
22+
23+Invoke `psql` against the mattermost database on the current primary
24+and use the following query to install the certificate:
25+
26+ INSERT INTO configurationfiles (name, createat, updateat, data)
27+ VALUES ('saml-idp.crt', (extract(epoch from now()) * 1000)::bigint ,(extract(epoch from now()) * 1000)::bigint, $$-----BEGIN CERTIFICATE-----
28+ [...]
29+ -----END CERTIFICATE-----$$);
30diff --git a/config.yaml b/config.yaml
31index e15f8cd..ae1fbef 100644
32--- a/config.yaml
33+++ b/config.yaml
34@@ -126,3 +126,10 @@ options:
35
36 This requires configuration on the S3 side, as well as a suitable Mattermost licence.
37 default: false
38+ sso:
39+ type: boolean
40+ description: |
41+ Whether to use Ubuntu SSO to log in.
42+
43+ This will not work unless the administrators of login.ubuntu.com have created a suitable SAML config first.
44+ default: false
45diff --git a/src/charm.py b/src/charm.py
46index 9b0474d..2831af0 100755
47--- a/src/charm.py
48+++ b/src/charm.py
49@@ -43,6 +43,8 @@ DATABASE_NAME = 'mattermost'
50 LICENCE_SECRET_KEY_NAME = 'licence'
51 REQUIRED_S3_SETTINGS = ['s3_bucket', 's3_region', 's3_access_key_id', 's3_secret_access_key']
52 REQUIRED_SETTINGS = ['mattermost_image_path']
53+REQUIRED_SSO_SETTINGS = ['licence', 'site_url']
54+SAML_IDP_CRT = 'saml-idp.crt'
55
56
57 class MattermostDBMasterAvailableEvent(EventBase):
58@@ -214,7 +216,10 @@ class MattermostK8sCharm(CharmBase):
59 if config['s3_enabled']:
60 missing.extend([setting for setting in REQUIRED_S3_SETTINGS if not config[setting]])
61
62- return missing
63+ if config['sso']:
64+ missing.extend([setting for setting in REQUIRED_SSO_SETTINGS if not config[setting]])
65+
66+ return sorted(list(set(missing)))
67
68 def _make_s3_pod_config(self):
69 config = self.model.config
70@@ -358,6 +363,34 @@ class MattermostK8sCharm(CharmBase):
71
72 return pod_spec
73
74+ def _update_pod_spec_for_sso(self, pod_spec):
75+ config = self.model.config
76+ if not config['sso'] or [setting for setting in REQUIRED_SSO_SETTINGS if not config[setting]]:
77+ return pod_spec
78+ pod_spec = copy.deepcopy(pod_spec)
79+ site_hostname = urlparse(config['site_url']).hostname
80+
81+ pod_spec['containers'][0]['envConfig'].update({
82+ 'MM_SAMLSETTINGS_ENABLE': 'true',
83+ 'MM_SAMLSETTINGS_IDPURL': 'https://login.ubuntu.com/saml/',
84+ 'MM_SAMLSETTINGS_VERIFY': 'true',
85+ 'MM_SAMLSETTINGS_ENCRYPT': 'false', # per POC
86+ 'MM_SAMLSETTINGS_IDPDESCRIPTORURL': 'https://login.ubuntu.com',
87+ 'MM_SAMLSETTINGS_IDPMETADATAURL': 'https://login.ubuntu.com/+saml/metadata',
88+ 'MM_SAMLSETTINGS_ASSERTIONCONSUMERSERVICEURL': 'https://{}/login/sso/saml'.format(site_hostname),
89+ 'MM_SAMLSETTINGS_LOGINBUTTONTEXT': 'Ubuntu SSO',
90+ 'MM_SAMLSETTINGS_EMAILATTRIBUTE': 'email',
91+ 'MM_SAMLSETTINGS_USERNAMEATTRIBUTE': 'username',
92+ 'MM_SAMLSETTINGS_IDATTRIBUTE': 'openid',
93+ 'MM_SAMLSETTINGS_FIRSTNAMEATTRIBUTE': 'fullname',
94+ 'MM_SAMLSETTINGS_LASTNAMEATTRIBUTE': '',
95+ 'MM_SAMLSETTINGS_IDPCERTIFICATEFILE': SAML_IDP_CRT,
96+ # Otherwise we have to install xmlsec1 and Mattermost forks on every login(!).
97+ 'MM_EXPERIMENTALSETTINGS_USENEWSAMLLIBRARY': 'true',
98+ })
99+
100+ return pod_spec
101+
102 def configure_pod(self, event):
103 if not state_get('db_uri'):
104 self.unit.status = WaitingStatus('Waiting for database relation')
105@@ -378,6 +411,7 @@ class MattermostK8sCharm(CharmBase):
106 pod_spec = self._update_pod_spec_for_k8s_ingress(pod_spec)
107 pod_spec = self._update_pod_spec_for_licence(pod_spec)
108 pod_spec = self._update_pod_spec_for_clustering(pod_spec)
109+ pod_spec = self._update_pod_spec_for_sso(pod_spec)
110
111 self.unit.status = MaintenanceStatus('Setting pod spec')
112 self.model.pod.set_spec(pod_spec)
113diff --git a/tests/unit/test_charm.py b/tests/unit/test_charm.py
114index 8a970b6..7e8c809 100644
115--- a/tests/unit/test_charm.py
116+++ b/tests/unit/test_charm.py
117@@ -20,6 +20,7 @@ CONFIG_IMAGE_NO_CREDS = {
118 'mattermost_image_username': '',
119 'mattermost_image_password': '',
120 's3_enabled': False,
121+ 'sso': False,
122 }
123
124 CONFIG_IMAGE_NO_IMAGE = {
125@@ -28,6 +29,7 @@ CONFIG_IMAGE_NO_IMAGE = {
126 'mattermost_image_username': '',
127 'mattermost_image_password': '',
128 's3_enabled': False,
129+ 'sso': False,
130 }
131
132 CONFIG_IMAGE_NO_PASSWORD = {
133@@ -36,6 +38,7 @@ CONFIG_IMAGE_NO_PASSWORD = {
134 'mattermost_image_username': 'production',
135 'mattermost_image_password': '',
136 's3_enabled': False,
137+ 'sso': False,
138 }
139
140 CONFIG_NO_S3_SETTINGS_S3_ENABLED = {
141@@ -49,6 +52,7 @@ CONFIG_NO_S3_SETTINGS_S3_ENABLED = {
142 's3_region': '',
143 's3_access_key_id': '',
144 's3_secret_access_key': '',
145+ 'sso': False,
146 }
147
148 CONFIG_NO_S3_SETTINGS_S3_DISABLED_NO_DEFAULTS = {
149@@ -57,6 +61,7 @@ CONFIG_NO_S3_SETTINGS_S3_DISABLED_NO_DEFAULTS = {
150 'mattermost_image_username': '',
151 'mattermost_image_password': '',
152 's3_enabled': False,
153+ 'sso': False,
154 }
155
156 RANGE_BAD = '10.242.0.0/8,91.189.92.242/25'

Subscribers

People subscribed via source and target branches