From 1506845ce67e05eb167dc9d99e938aab24f43e1e Mon Sep 17 00:00:00 2001 From: kaiyou <pierre@jaury.eu> Date: Fri, 20 Mar 2020 16:06:03 +0100 Subject: [PATCH] Application templates for Nextcloud, Grafana and Synapse --- hiboo/application/__init__.py | 2 +- hiboo/application/infrastructure.py | 65 +++++++++++++++++++ hiboo/application/social.py | 32 ++++++++- hiboo/application/storage.py | 21 +++--- .../templates/application_grafana.html | 30 +++++++++ .../templates/application_nextcloud.html | 29 +++++++++ .../templates/application_synapse.html | 15 +++++ 7 files changed, 179 insertions(+), 15 deletions(-) create mode 100644 hiboo/application/infrastructure.py create mode 100644 hiboo/application/templates/application_grafana.html create mode 100644 hiboo/application/templates/application_nextcloud.html create mode 100644 hiboo/application/templates/application_synapse.html diff --git a/hiboo/application/__init__.py b/hiboo/application/__init__.py index 8343071..c6916eb 100644 --- a/hiboo/application/__init__.py +++ b/hiboo/application/__init__.py @@ -9,4 +9,4 @@ from hiboo.application import base register = base.BaseApplication.register registry = base.BaseApplication.registry -from hiboo.application import sso, social, storage \ No newline at end of file +from hiboo.application import sso, infrastructure, social, storage \ No newline at end of file diff --git a/hiboo/application/infrastructure.py b/hiboo/application/infrastructure.py new file mode 100644 index 0000000..4d138e6 --- /dev/null +++ b/hiboo/application/infrastructure.py @@ -0,0 +1,65 @@ +from hiboo.application import register, base +from wtforms import validators, fields +from flask_babel import lazy_gettext as _ + + +@register("gitlab") +class GitlabApplication(base.OIDCApplication): + """ Gitlab is a source code and project management plaform, largely based on Git + """ + + name = _("Gitlab") + + class Form(base.BaseForm): + application_uri = fields.StringField(_("Gitlab URL"), [validators.URL(require_tld=False)]) + submit = fields.SubmitField(_('Submit')) + + def populate_service(self, form, service): + service.profile_regex = "[a-z0-9_.\-]*" + callback_uri = form.application_uri.data + "/users/auth/openid_connect/callback" + service.config.update({ + "application_uri": form.application_uri.data, + "token_endpoint_auth_method": "client_secret_post", + "redirect_uris": [callback_uri], + "grant_types": ["authorization_code"], + "response_types": ["code"], + "special_mappings": ["mask_sub_uuid"] + }) + self.fill_service(service) + + def populate_form(self, service, form): + form.process( + obj=service, + application_uri=service.config.get("application_uri") + ) + + +@register("grafana") +class GrafanaApplication(base.OIDCApplication): + """ Grafana is an infrastructure dashboard application + """ + + name = _("Grafana") + + class Form(base.BaseForm): + application_uri = fields.StringField(_("Grafana URL"), [validators.URL(require_tld=False)]) + submit = fields.SubmitField(_('Submit')) + + def populate_service(self, form, service): + service.profile_regex = "[a-z0-9_.\-]*" + callback_uri = form.application_uri.data + "/login/generic_oauth" + service.config.update({ + "application_uri": form.application_uri.data, + "token_endpoint_auth_method": "client_secret_post", + "redirect_uris": [callback_uri], + "grant_types": ["authorization_code"], + "response_types": ["code"], + "special_mappings": [] + }) + self.fill_service(service) + + def populate_form(self, service, form): + form.process( + obj=service, + application_uri=service.config.get("application_uri") + ) diff --git a/hiboo/application/social.py b/hiboo/application/social.py index c023e43..e99ad0e 100644 --- a/hiboo/application/social.py +++ b/hiboo/application/social.py @@ -5,10 +5,10 @@ from flask_babel import lazy_gettext as _ @register("mastodon") class MastodonApplication(base.SAMLApplication): - """ Mastodon social network is an ActivityPub micro-blogging platform + """ Mastodon social network is a popular micro-blogging platform compliant with ActivityPub """ - name = _("Mastodon social network") + name = _("Mastodon") class Form(base.BaseForm): application_uri = fields.StringField(_("Mastodon URL"), [validators.URL(require_tld=False)]) @@ -30,3 +30,31 @@ class MastodonApplication(base.SAMLApplication): obj=service, application_uri=service.config.get("application_uri") ) + + +@register("synapse") +class SynapseApplication(base.SAMLApplication): + """ Synapse is the flagship implmentation of Matrix, a federated, end-to-end-encrypted messaging protocol + """ + + name = _("Synapse") + + class Form(base.BaseForm): + application_uri = fields.StringField(_("Synapse homeserver URL"), [validators.URL(require_tld=False)]) + submit = fields.SubmitField(_('Submit')) + + def populate_service(self, form, service): + service.profile_regex = "[a-zA-Z0-9_\-./=]+" + service.config.update({ + "application_uri": form.application_uri.data, + "acs": form.application_uri.data + "/saml2/authn_response", + "entityid": form.application_uri.data + "/saml2/metadata.xml", + "sign_mode": "response" + }) + self.fill_service(service) + + def populate_form(self, service, form): + form.process( + obj=service, + application_uri=service.config.get("application_uri") + ) diff --git a/hiboo/application/storage.py b/hiboo/application/storage.py index 12e025f..ae85e5a 100644 --- a/hiboo/application/storage.py +++ b/hiboo/application/storage.py @@ -3,27 +3,24 @@ from wtforms import validators, fields from flask_babel import lazy_gettext as _ -@register("gitlab") -class GitlabApplication(base.OIDCApplication): - """ Gitlab is a source code and project management plaform, largely based on Git +@register("nextcloud") +class SeafileApplication(base.SAMLApplication): + """ NextCloud is a free alternative to many cloud vendors (storage, contacts, meetings, etc.) """ - name = _("Gitlab repository manager") + name = _("NextCloud") class Form(base.BaseForm): - application_uri = fields.StringField(_("Gitlab URL"), [validators.URL(require_tld=False)]) + application_uri = fields.StringField(_("NextCloud URL"), [validators.URL(require_tld=False)]) submit = fields.SubmitField(_('Submit')) def populate_service(self, form, service): service.profile_regex = "[a-z0-9_.\-]*" - callback_uri = form.application_uri.data + "/users/auth/openid_connect/callback" service.config.update({ "application_uri": form.application_uri.data, - "token_endpoint_auth_method": "client_secret_post", - "redirect_uris": [callback_uri], - "grant_types": ["authorization_code"], - "response_types": ["code"], - "special_mappings": ["mask_sub_uuid"] + "acs": form.application_uri.data + "/apps/user_saml/saml/acs", + "entityid": form.application_uri.data + "/apps/user_saml/saml/metadata", + "sign_mode": "response" }) self.fill_service(service) @@ -36,7 +33,7 @@ class GitlabApplication(base.OIDCApplication): @register("seafile") class SeafileApplication(base.OIDCApplication): - """ Seafile is a file sharing and synchronization application with a Web viewer + """ Seafile is a file sharing and synchronization application with an embedded Web viewer """ name = _("Seafile") diff --git a/hiboo/application/templates/application_grafana.html b/hiboo/application/templates/application_grafana.html new file mode 100644 index 0000000..b15396f --- /dev/null +++ b/hiboo/application/templates/application_grafana.html @@ -0,0 +1,30 @@ +<h3>Setting up Grafana</h3> +<p>Grafna supports Oauth2 authentication through Omniauth, which is compatible with OIDC.</p> +<p>If you are running Grafana directly, you may add the following lines to your configuration.</p> +<pre> +[server] +root_url = {{ service.config["application_uri"] }} + +[auth.generic_oauth] +enabled = true +allow_sign_up = true +client_id = {{ service.config["client_id"] }} +client_secret = {{ service.config["client_secret"] }} +scopes = openid profile email +auth_url = {{ url_for("sso.oidc_authorize", service_uuid=service.uuid, _external=True) }} +token_url = {{ url_for("sso.oidc_token", service_uuid=service.uuid, _external=True) }} +</pre> + +<p>If you are running the Grafana Docker image, please set the following environment variables.</p> +<pre> +GF_SERVER_ROOT_URL={{ service.config["application_uri"] }} +GF_AUTH_GENERIC_OAUTH_ENABLED=True +GF_AUTH_GENERIC_OAUTH_ALLOW_SIGN_UP=True +GF_AUTH_GENERIC_OAUTH_CLIENT_ID={{ service.config["client_id"] }} +GF_AUTH_GENERIC_OAUTH_CLIENT_SECRET={{ service.config["client_secret"] }} +GF_AUTH_GENERIC_OAUTH_SCOPES=openid profile email +GF_AUTH_GENERIC_OAUTH_AUTH_URL={{ url_for("sso.oidc_authorize", service_uuid=service.uuid, _external=True) }} +GF_AUTH_GENERIC_OAUTH_TOKEN_URL={{ url_for("sso.oidc_token", service_uuid=service.uuid, _external=True) }} +</pre> + +{% include "application_oidc.html" %} \ No newline at end of file diff --git a/hiboo/application/templates/application_nextcloud.html b/hiboo/application/templates/application_nextcloud.html new file mode 100644 index 0000000..7373daf --- /dev/null +++ b/hiboo/application/templates/application_nextcloud.html @@ -0,0 +1,29 @@ +<h3>Setting up NextCloud</h3> +<p>NextCloud uses the <a href="https://apps.nextcloud.com/apps/user_saml">user_saml</a> extension in order to handle SAML2 authentication.</p> +<p>You must first install this extension on your instance, then go to your <i>Settings</i> menu and fill in the following parameters.</p> + +<dt>Attribute to map the uid to</dt> +<dd><pre>urn:oid:0.9.2342.19200300.100.1.1</pre></dd> + +<dt>Name id format</dt> +<dd><pre>Persistent</pre></dd> + +<dt>X.509 certificat of the Service Provider</dt> +<dd><pre>{{ "".join(service.config["sp_cert"].strip().split("\n")[1:-1]) }}</pre></dd> + +<dt>Private Key of the Service Provider</dt> +<dd><pre>{{ "".join(service.config["sp_key"].strip().split("\n")[1:-1]) }}</pre></dd> + +<dt>Identifier of the IDP entity</dt> +<dd><pre>{{ url_for("sso.saml_metadata", service_uuid=service.uuid, _external=True) }}</pre></dd> + +<dt>URL target of the IDP where the SP will send the Authentication Request Message</dt> +<dd><pre>{{ url_for("sso.saml_redirect", service_uuid=service.uuid, _external=True) }}</pre></dd> + +<dt>URL location of the IDP where the SP will send the SLO request</dt> +<dd><pre>{{ service.config["application_uri"] }}</pre></dd> + +<dt>Public X.509 certificat of the IDP</dt> +<dd><pre>{{ "".join(service.config["idp_cert"].strip().split("\n")[1:-1]) }}</pre></dd> + +{% include "application_saml.html" %} \ No newline at end of file diff --git a/hiboo/application/templates/application_synapse.html b/hiboo/application/templates/application_synapse.html new file mode 100644 index 0000000..03344f4 --- /dev/null +++ b/hiboo/application/templates/application_synapse.html @@ -0,0 +1,15 @@ +<h3>Setting up Synapse</h3> +<p>Synapse relies on the pysaml2 SAML implementation for SAML2 authentication.</p> +<p>In order to configure SAML for Synapse, you may copy then paste the following lines directly into your homeserver configuration file.</p> +<pre> +saml2_config: + enabled: true + sp_config: + metadata: + remote: + - url: {{ url_for("sso.saml_metadata", service_uuid=service.uuid, _external=True) }} +</pre> + +<p>You should also disable password authentication if you wish to avoid desynchronization and username conflicts.</p> + +{% include "application_saml.html" %} \ No newline at end of file -- GitLab