def wrapper(namespace_name, repo_name, *args, **kwargs): response = f(namespace_name, repo_name, *args, **kwargs) # Setting session namespace and repository session["namespace"] = namespace_name session["repository"] = repo_name # We run our index and registry on the same hosts for now registry_server = urlparse.urlparse(request.url).netloc response.headers["X-Docker-Endpoints"] = registry_server has_token_request = request.headers.get("X-Docker-Token", "") force_grant = add_grant_for_status == response.status_code if has_token_request or force_grant: grants = [] if scope == GrantType.READ_REPOSITORY: if force_grant or ReadRepositoryPermission(namespace_name, repo_name).can(): grants.append(repository_read_grant(namespace_name, repo_name)) elif scope == GrantType.WRITE_REPOSITORY: if force_grant or ModifyRepositoryPermission(namespace_name, repo_name).can(): grants.append(repository_write_grant(namespace_name, repo_name)) # Generate a signed token for the user (if any) and the grants (if any) if grants or get_authenticated_user(): user_context = get_authenticated_user() and get_authenticated_user().username signature = generate_signed_token(grants, user_context) response.headers["WWW-Authenticate"] = signature response.headers["X-Docker-Token"] = signature return response
def identity_from_bearer_token(bearer_header): """ Process a bearer header and return the loaded identity, or raise InvalidJWTException if an identity could not be loaded. Expects tokens and grants in the format of the Docker registry v2 auth spec: https://docs.docker.com/registry/spec/auth/token/ """ logger.debug("Validating auth header: %s", bearer_header) try: payload = decode_bearer_header(bearer_header, instance_keys, app.config) except InvalidBearerTokenException as bte: logger.exception("Invalid bearer token: %s", bte) raise InvalidJWTException(bte) loaded_identity = Identity(payload["sub"], "signed_jwt") # Process the grants from the payload if "access" in payload: try: validate(payload["access"], ACCESS_SCHEMA) except ValidationError: logger.exception("We should not be minting invalid credentials") raise InvalidJWTException( "Token contained invalid or malformed access grants") lib_namespace = app.config["LIBRARY_NAMESPACE"] for grant in payload["access"]: namespace, repo_name = parse_namespace_repository( grant["name"], lib_namespace) if "*" in grant["actions"]: loaded_identity.provides.add( repository_admin_grant(namespace, repo_name)) elif "push" in grant["actions"]: loaded_identity.provides.add( repository_write_grant(namespace, repo_name)) elif "pull" in grant["actions"]: loaded_identity.provides.add( repository_read_grant(namespace, repo_name)) default_context = {"kind": "anonymous"} if payload["sub"] != ANONYMOUS_SUB: default_context = { "kind": "user", "user": payload["sub"], } return loaded_identity, payload.get("context", default_context)
def identity_from_bearer_token(bearer_header): """ Process a bearer header and return the loaded identity, or raise InvalidJWTException if an identity could not be loaded. Expects tokens and grants in the format of the Docker registry v2 auth spec: https://docs.docker.com/registry/spec/auth/token/ """ logger.debug('Validating auth header: %s', bearer_header) try: payload = decode_bearer_header(bearer_header, instance_keys, app.config, metric_queue=metric_queue) except InvalidBearerTokenException as bte: logger.exception('Invalid bearer token: %s', bte) raise InvalidJWTException(bte) loaded_identity = Identity(payload['sub'], 'signed_jwt') # Process the grants from the payload if 'access' in payload: try: validate(payload['access'], ACCESS_SCHEMA) except ValidationError: logger.exception('We should not be minting invalid credentials') raise InvalidJWTException( 'Token contained invalid or malformed access grants') lib_namespace = app.config['LIBRARY_NAMESPACE'] for grant in payload['access']: namespace, repo_name = parse_namespace_repository( grant['name'], lib_namespace) if '*' in grant['actions']: loaded_identity.provides.add( repository_admin_grant(namespace, repo_name)) elif 'push' in grant['actions']: loaded_identity.provides.add( repository_write_grant(namespace, repo_name)) elif 'pull' in grant['actions']: loaded_identity.provides.add( repository_read_grant(namespace, repo_name)) default_context = {'kind': 'anonymous'} if payload['sub'] != ANONYMOUS_SUB: default_context = { 'kind': 'user', 'user': payload['sub'], } return loaded_identity, payload.get('context', default_context)