Use OIDC to auth the users, replace submit-build.sh by submit-build.py which does hackish way of OIDC just to test things.

This commit is contained in:
Jan Kaluza
2016-12-02 14:39:14 +01:00
parent d453352f84
commit 8cb4e0de5d
8 changed files with 172 additions and 46 deletions

View File

@@ -26,40 +26,73 @@
from werkzeug.serving import WSGIRequestHandler
from module_build_service.errors import Unauthorized
from module_build_service import app, log
import fedora.client
import httplib2
import json
from six.moves.urllib.parse import urlencode
def _json_loads(content):
if not isinstance(content, str):
content = content.decode('utf-8')
return json.loads(content)
class ClientCertRequestHandler(WSGIRequestHandler):
client_secrets = None
def _load_secrets():
global client_secrets
if client_secrets:
return
if not "OIDC_CLIENT_SECRETS" in app.config:
log.warn("To support authorization, OIDC_CLIENT_SECRETS has to be set.")
return
secrets = _json_loads(open(app.config['OIDC_CLIENT_SECRETS'],
'r').read())
client_secrets = list(secrets.values())[0]
def get_token_info(token):
"""
WSGIRequestHandler subclass adding SSL_CLIENT_CERT_* variables
to `request.environ` dict when the client certificate is set and
is signed by CA configured in `conf.ssl_ca_certificate_file`.
Asks the token_introspection_uri for the validity of a token.
"""
if not client_secrets:
return None
request = {'token': token,
'token_type_hint': 'Bearer',
'client_id': client_secrets['client_id'],
'client_secret': client_secrets['client_secret']}
headers = {'Content-type': 'application/x-www-form-urlencoded'}
resp, content = httplib2.Http().request(
client_secrets['token_introspection_uri'], 'POST',
urlencode(request), headers=headers)
return _json_loads(content)
def get_username(request):
"""
Returns the client's username based on the OIDC token provided.
"""
def make_environ(self):
environ = WSGIRequestHandler.make_environ(self)
_load_secrets()
try:
cert = self.request.getpeercert(False)
except AttributeError:
cert = None
if not "oidc_token" in request.cookies:
raise Unauthorized("Cannot verify OIDC token.")
if cert and "subject" in cert:
for keyval in cert["subject"]:
key, val = keyval[0]
environ["SSL_CLIENT_CERT_" + key] = val
return environ
token = request.cookies["oidc_token"]
data = get_token_info(token)
if not data:
raise Unauthorized("Cannot verify OIDC token.")
if not "active" in data or not data["active"]:
raise Unauthorized("OIDC token invalid or expired.")
def get_username(environ):
""" Extract the user's username from the WSGI environment. """
if not "SSL_CLIENT_CERT_commonName" in environ:
raise Unauthorized("No SSL client cert CN could be found to work with")
return environ["SSL_CLIENT_CERT_commonName"]
#TODO: Once we will get our own scope registered in Fedora infra,
# we can start checking it here.
return data["username"]
def assert_is_packager(username, fas_kwargs):
""" Assert that a user is a packager by consulting FAS.

View File

@@ -62,7 +62,6 @@ api_v1 = {
},
}
class ModuleBuildAPI(MethodView):
def get(self, id):
@@ -93,7 +92,7 @@ class ModuleBuildAPI(MethodView):
raise NotFound('No such module found.')
def post(self):
username = module_build_service.auth.get_username(request.environ)
username = module_build_service.auth.get_username(request)
if conf.require_packager:
module_build_service.auth.assert_is_packager(username, fas_kwargs=dict(
@@ -127,7 +126,7 @@ class ModuleBuildAPI(MethodView):
return jsonify(module.json()), 201
def patch(self, id):
username = module_build_service.auth.get_username(request.environ)
username = module_build_service.auth.get_username(request)
if conf.require_packager:
module_build_service.auth.assert_is_packager(