Add support for an external JWT-based authentication system
This authentication system hits two HTTP endpoints to check and verify the existence of users: Existance endpoint: GET http://endpoint/ with Authorization: Basic (username:) => Returns 200 if the username/email exists, 4** otherwise Verification endpoint: GET http://endpoint/ with Authorization: Basic (username:password) => Returns 200 and a signed JWT with the user's username and email address if the username+password validates, 4** otherwise with the body containing an optional error message The JWT produced by the endpoint must be issued with an issuer matching that configured in the config.yaml, and the audience must be "quay.io/jwtauthn". The JWT is signed using a private key and then validated on the Quay.io side with the associated public key, found as "jwt-authn.cert" in the conf/stack directory.
This commit is contained in:
parent
42da017d69
commit
8aac3fd86e
10 changed files with 417 additions and 38 deletions
|
@ -7,7 +7,7 @@ import OpenSSL
|
|||
import logging
|
||||
|
||||
from fnmatch import fnmatch
|
||||
from data.users import LDAPConnection
|
||||
from data.users import LDAPConnection, JWTAuthUsers
|
||||
from flask import Flask
|
||||
from flask.ext.mail import Mail, Message
|
||||
from data.database import validate_database_url, User
|
||||
|
@ -20,6 +20,8 @@ from bitbucket import BitBucket
|
|||
logger = logging.getLogger(__name__)
|
||||
|
||||
SSL_FILENAMES = ['ssl.cert', 'ssl.key']
|
||||
JWT_FILENAMES = ['jwt-authn.cert']
|
||||
CONFIG_FILENAMES = SSL_FILENAMES + JWT_FILENAMES
|
||||
|
||||
def get_storage_provider(config):
|
||||
parameters = config.get('DISTRIBUTED_STORAGE_CONFIG', {}).get('local', ['LocalStorage', {}])
|
||||
|
@ -303,6 +305,36 @@ def _validate_ldap(config):
|
|||
raise Exception(values.get('desc', 'Unknown error'))
|
||||
|
||||
|
||||
def _validate_jwt(config):
|
||||
""" Validates the JWT authentication system. """
|
||||
if config.get('AUTHENTICATION_TYPE', 'Database') != 'JWT':
|
||||
return
|
||||
|
||||
verify_endpoint = config.get('JWT_VERIFY_ENDPOINT')
|
||||
exists_endpoint = config.get('JWT_EXISTS_ENDPOINT')
|
||||
issuer = config.get('JWT_AUTH_ISSUER')
|
||||
|
||||
if not verify_endpoint:
|
||||
raise Exception('Missing JWT Verification endpoint')
|
||||
|
||||
if not exists_endpoint:
|
||||
raise Exception('Missing JWT Exists endpoint')
|
||||
|
||||
if not issuer:
|
||||
raise Exception('Missing JWT Issuer ID')
|
||||
|
||||
# Try to instatiate the JWT authentication mechanism. This will raise an exception if
|
||||
# the key cannot be found.
|
||||
users = JWTAuthUsers(exists_endpoint, verify_endpoint, issuer)
|
||||
|
||||
# Verify that the superuser exists. If not, raise an exception.
|
||||
username = get_authenticated_user().username
|
||||
result = users.user_exists(username)
|
||||
if not result:
|
||||
raise Exception('Verification of superuser %s failed. The user either does not exist ' +
|
||||
'in the remote authentication system OR JWT auth is misconfigured.' % username)
|
||||
|
||||
|
||||
_VALIDATORS = {
|
||||
'database': _validate_database,
|
||||
'redis': _validate_redis,
|
||||
|
@ -315,4 +347,5 @@ _VALIDATORS = {
|
|||
'google-login': _validate_google_login,
|
||||
'ssl': _validate_ssl,
|
||||
'ldap': _validate_ldap,
|
||||
'jwt': _validate_jwt,
|
||||
}
|
Reference in a new issue