From 5d86053abc278fb5448b508cee92bcd1beb3e3c8 Mon Sep 17 00:00:00 2001 From: Aurélien Bompard Date: Nov 23 2020 08:24:18 +0000 Subject: In the new AAA system, the SSH key will be base64-encoded Signed-off-by: Aurélien Bompard --- diff --git a/pagure/ui/oidc_login.py b/pagure/ui/oidc_login.py index eba73e8..39153d7 100644 --- a/pagure/ui/oidc_login.py +++ b/pagure/ui/oidc_login.py @@ -11,6 +11,7 @@ from __future__ import unicode_literals, absolute_import import logging +from base64 import b64decode import flask from flask import Markup @@ -51,11 +52,19 @@ def fas_user_from_oidc(): username = info[email_key].split("@")[0] elif fb == "sub": username = flask.g.oidc_id_token["sub"] + # The SSH key may be returned base64-encoded + ssh_key = info.get(ssh_key) + if ssh_key is not None: + try: + ssh_key = b64decode(ssh_key).decode("ascii") + except (TypeError, ValueError): + pass + # Create the user object flask.g.fas_user = munch.Munch( username=username, fullname=info.get(fulln_key, ""), email=info[email_key], - ssh_key=info.get(ssh_key), + ssh_key=ssh_key, groups=info.get(groups_key, []), login_time=flask.session["oidc_logintime"], ) diff --git a/tests/test_pagure_flask_ui_oidc_login.py b/tests/test_pagure_flask_ui_oidc_login.py new file mode 100644 index 0000000..f9cf133 --- /dev/null +++ b/tests/test_pagure_flask_ui_oidc_login.py @@ -0,0 +1,132 @@ +# -*- coding: utf-8 -*- + +""" + (c) 2020 - Copyright Red Hat Inc + + Authors: + Aurelien Bompard + +""" + +from __future__ import unicode_literals + +__requires__ = ["SQLAlchemy >= 0.8"] +import pkg_resources + +import unittest +import json +import sys +import os + +import flask +from mock import patch, Mock + +sys.path.insert( + 0, os.path.join(os.path.dirname(os.path.abspath(__file__)), "..") +) + +import pagure.lib +import tests + +from pagure.ui.oidc_login import fas_user_from_oidc, oidc + + +CLIENT_SECRETS = { + "web": { + "client_id": "dummy", + "client_secret": "dummy", + "auth_uri": "dummy-uri://", + "token_uri": "dummy-uri://", + "userinfo_uri": "dummy-uri://", + "redirect_uris": ["http://localhost:5000/oidc"], + } +} + + +class PagureFlaskOIDCLogintests(tests.SimplePagureTest): + """ Tests for OIDC login in the flask app controller of pagure """ + + populate_db = False + + def setUp(self): + """ Create the application with PAGURE_AUTH being local. """ + super(PagureFlaskOIDCLogintests, self).setUp() + + self.app = pagure.flask_app.create_app( + {"DB_URL": self.dbpath, "PAGURE_AUTH": "local"} + ) + # Remove the log handlers for the tests + self.app.logger.handlers = [] + + secrets_path = os.path.join(self.path, "client_secrets.json") + self.config_patcher = patch.dict( + "pagure.config.config", + { + "OIDC_PAGURE_EMAIL": "email", + "OIDC_PAGURE_FULLNAME": "name", + "OIDC_PAGURE_USERNAME": "preferred_username", + "OIDC_PAGURE_SSH_KEY": "ssh_key", + "OIDC_PAGURE_GROUPS": "groups", + "OIDC_CLIENT_SECRETS": secrets_path, + }, + ) + self.config_patcher.start() + + with open(secrets_path, "w") as secrets: + secrets.write(json.dumps(CLIENT_SECRETS)) + + oidc.init_app(self.app) + + self.request_context = self.app.test_request_context("/") + self.request_context.push() + flask.session["oidc_logintime"] = "dummy-logintime" + flask.g.session = Mock() # the DB session should be here + flask.g.oidc_id_token = {"sub": "dummy"} + self.user_info = { + "email": "dummy@example.com", + "name": "Dummy User", + "preferred_username": "dummy", + } + + def tearDown(self): + self.request_context.pop() + self.config_patcher.stop() + + def test_fas_user_from_oidc(self): + """ Test the user creation function. """ + user_info = self.user_info.copy() + flask.g._oidc_userinfo = user_info + fas_user_from_oidc() + self.assertIsNotNone(getattr(flask.g, "fas_user", None)) + self.assertEqual(flask.g.fas_user.username, "dummy") + self.assertEqual(flask.g.fas_user.fullname, "Dummy User") + self.assertIsNone(flask.g.fas_user.ssh_key) + self.assertEqual(flask.g.fas_user.groups, []) + + def test_fas_user_from_oidc_groups(self): + """ Test the user creation function. """ + user_info = self.user_info.copy() + user_info["groups"] = ["group1", "group2"] + flask.g._oidc_userinfo = user_info + fas_user_from_oidc() + self.assertEqual(flask.g.fas_user.groups, ["group1", "group2"]) + + def test_fas_user_from_oidc_ssh(self): + """ Test the user creation function. """ + user_info = self.user_info.copy() + user_info["ssh_key"] = "dummy ssh key" + flask.g._oidc_userinfo = user_info + fas_user_from_oidc() + self.assertEqual(flask.g.fas_user.ssh_key, "dummy ssh key") + + def test_fas_user_from_oidc_ssh_b64(self): + """The SSH key may be base64-encoded""" + user_info = self.user_info.copy() + user_info["ssh_key"] = "ZHVtbXkgc3NoIGtleQ==" + flask.g._oidc_userinfo = user_info + fas_user_from_oidc() + self.assertEqual(flask.g.fas_user.ssh_key, "dummy ssh key") + + +if __name__ == "__main__": + unittest.main(verbosity=2)