Publish curated Unraid-AppOps-Gateway source from 68878c3167dacf2b424c16780e60e0d60815e477

This commit is contained in:
Public Source Publisher committed 2026-10-08 18:33:13 +00:00
1 parent 837c263cd8
commit 551de41e9f
18 files changed
+1183 -58

No files matched your search

+111 -4
View File
@@ -1,5 +1,7 @@
from pathlib import Path
import pytest
from fastapi.testclient import TestClient
from sqlmodel import SQLModel, create_engine
@@ -133,6 +135,7 @@ def test_oidc_template_requires_the_exact_enrolled_role_claim():
from backend.app.core.config import settings
previous = _set_authentik_config()
_set_deployment_identity_template()
settings.apis['AUTHENTIK_OIDC_AUTHORIZATION_FLOW'] = 'flow-default-auth'
settings.apis['AUTHENTIK_OIDC_INVALIDATION_FLOW'] = 'flow-default-invalidation'
settings.apis['AUTHENTIK_OIDC_GROUP_CLAIM_MAPPING'] = 'mapping-groups'
@@ -151,11 +154,86 @@ def test_oidc_template_requires_the_exact_enrolled_role_claim():
_restore_config(previous)
def _set_deployment_identity_template():
from backend.app.core.config import settings
settings.apis.update({
'AUTHENTIK_OIDC_OPENID_CLAIM_MAPPING': 'openid-id',
'AUTHENTIK_OIDC_EMAIL_CLAIM_MAPPING': 'email-id',
'AUTHENTIK_OIDC_PROFILE_CLAIM_MAPPING': 'profile-id',
'AUTHENTIK_OIDC_SIGNING_KEY_ID': 'rsa-key-id',
})
@pytest.mark.parametrize("failure", [None, "flow", "flow_missing", "flow_duplicate", "mapping", "scope", "signing", "unreachable", "openid_roles", "email_roles", "profile_roles"])
def test_enrollment_template_verifies_remote_flows_and_filtered_role_claim(monkeypatch, failure):
from backend.app.connectors.authentik import AuthentikConnector
from backend.app.core.config import settings
previous = _set_authentik_config()
_set_deployment_identity_template()
settings.apis.update({
'AUTHENTIK_OIDC_AUTHORIZATION_FLOW': 'authorization-id',
'AUTHENTIK_OIDC_INVALIDATION_FLOW': 'invalidation-id',
'AUTHENTIK_OIDC_GROUP_CLAIM_MAPPING': 'roles-id',
'AUTHENTIK_OIDC_ROLE_CLAIM': 'roles',
})
expression = 'return {"roles": sorted({group.name for group in request.user.ak_groups.all() if group.name in ["Administrator", "ReadOnly", "SupportAgent"]})}'
def request(self, path, params=None):
if failure == 'unreachable':
raise RuntimeError('SECRET_SENTINEL')
for scope in ('openid', 'email', 'profile'):
if path == f'/propertymappings/provider/scope/{scope}-id/':
expressions = {
'openid': '# This scope is required by the OpenID-spec, and must as such exist in authentik.\n# The scope by itself does not grant any information\nreturn {}',
'email': 'return {\n "email": request.user.email,\n "email_verified": False\n}',
'profile': 'return delete_none_values({\n "name": request.user.name,\n "preferred_username": request.user.username,\n})',
}
return {
'pk': f'{scope}-id', 'scope_name': 'wrong' if failure == 'scope' else scope,
'managed': f'goauthentik.io/providers/oauth2/scope-{scope}' if scope != 'profile' else None,
'expression': 'return {"roles": ["Administrator"]}' if failure == f'{scope}_roles' else expressions[scope],
}
if path.startswith('/flows/instances/'):
raise RuntimeError('HTTP 404: flow detail requires slug, not UUID')
return {
'/propertymappings/provider/scope/roles-id/': {
'pk': 'roles-id', 'scope_name': 'roles',
'expression': 'return {"roles": ["Administrator"]}' if failure == 'mapping' else expression,
},
}[path]
monkeypatch.setattr(AuthentikConnector, '_request', request)
def paged(self, path, params=None):
if path == '/flows/instances/':
authorization = {'pk': 'authorization-id', 'slug': 'default-provider-authorization-implicit-consent', 'designation': 'authentication' if failure == 'flow' else 'authorization'}
flows = [{'pk': 'invalidation-id', 'slug': 'default-provider-invalidation-flow', 'designation': 'invalidation'}]
if failure != 'flow_missing':
flows.append(authorization)
if failure == 'flow_duplicate':
flows.append(authorization)
return flows
assert path == '/crypto/certificatekeypairs/'
return [{'pk': 'rsa-key-id', 'key_type': 'ec' if failure == 'signing' else 'rsa', 'private_key_available': True}]
monkeypatch.setattr(AuthentikConnector, '_paged', paged)
try:
result = AuthentikConnector().validate_deployment_oidc_template(
role_claim='roles', role_groups=('Administrator', 'SupportAgent', 'ReadOnly'),
)
assert (result['status'] == 'ready') is (failure is None)
assert 'SECRET_SENTINEL' not in str(result)
assert 'expression' not in result
finally:
_restore_config(previous)
def test_typed_oidc_provisioning_is_bounded_and_never_returns_client_secret(monkeypatch):
from backend.app.connectors.authentik import AuthentikConnector
from backend.app.core.config import settings
previous = _set_authentik_config()
_set_deployment_identity_template()
settings.apis['AUTHENTIK_OIDC_AUTHORIZATION_FLOW'] = 'flow-default-auth'
settings.apis['AUTHENTIK_OIDC_INVALIDATION_FLOW'] = 'flow-default-invalidation'
settings.apis['AUTHENTIK_OIDC_GROUP_CLAIM_MAPPING'] = 'mapping-groups'
@@ -195,6 +273,9 @@ def test_typed_oidc_provisioning_is_bounded_and_never_returns_client_secret(monk
}
assert writes[0][0:2] == ('POST', '/providers/oauth2/')
assert writes[0][2]['client_secret'] == secret
assert writes[0][2]['redirect_uris'] == [{'matching_mode': 'strict', 'url': 'https://support.itworx.test/signin-oidc'}]
assert writes[0][2]['signing_key'] == 'rsa-key-id'
assert set(writes[0][2]['property_mappings']) == {'openid-id', 'email-id', 'profile-id', 'mapping-groups'}
assert secret not in str(result)
_restore_config(previous)
@@ -204,6 +285,7 @@ def test_typed_oidc_provisioning_removes_new_provider_when_application_create_fa
from backend.app.core.config import settings
previous = _set_authentik_config()
_set_deployment_identity_template()
settings.apis['AUTHENTIK_OIDC_AUTHORIZATION_FLOW'] = 'flow-default-auth'
settings.apis['AUTHENTIK_OIDC_INVALIDATION_FLOW'] = 'flow-default-invalidation'
settings.apis['AUTHENTIK_OIDC_GROUP_CLAIM_MAPPING'] = 'mapping-groups'
@@ -248,21 +330,40 @@ def test_typed_oidc_provisioning_removes_new_provider_when_application_create_fa
_restore_config(previous)
def test_typed_oidc_existing_application_requires_matching_provider_contract(monkeypatch):
@pytest.mark.parametrize('damage', [None, 'client', 'regex', 'extra_mapping', 'signing_key', 'issuer'])
def test_typed_oidc_existing_application_requires_matching_provider_contract(monkeypatch, damage):
from backend.app.connectors.authentik import AuthentikConnector
from backend.app.core.config import settings
previous = _set_authentik_config()
_set_deployment_identity_template()
settings.apis['AUTHENTIK_OIDC_AUTHORIZATION_FLOW'] = 'flow-default-auth'
settings.apis['AUTHENTIK_OIDC_INVALIDATION_FLOW'] = 'flow-default-invalidation'
settings.apis['AUTHENTIK_OIDC_GROUP_CLAIM_MAPPING'] = 'mapping-groups'
provider = {
'pk': 'provider-1', 'client_id': 'wsbc-portal', 'client_type': 'confidential',
'redirect_uris': [{'matching_mode': 'strict', 'url': 'https://support.itworx.test/signin-oidc'}],
'property_mappings': ['openid-id', 'email-id', 'profile-id', 'mapping-groups'],
'authorization_flow': 'flow-default-auth', 'invalidation_flow': 'flow-default-invalidation',
'signing_key': 'rsa-key-id', 'issuer_mode': 'per_provider',
}
if damage == 'client':
provider['client_id'] = 'unexpected-client'
elif damage == 'regex':
provider['redirect_uris'][0]['matching_mode'] = 'regex'
elif damage == 'extra_mapping':
provider['property_mappings'].append('other-roles')
elif damage == 'signing_key':
provider['signing_key'] = None
elif damage == 'issuer':
provider['issuer_mode'] = 'global'
monkeypatch.setattr(
AuthentikConnector,
'_paged',
lambda self, path, params=None: {
'/core/groups/': [{'name': 'Administrator'}, {'name': 'SupportAgent'}, {'name': 'ReadOnly'}],
'/core/applications/': [{'pk': 'application-1', 'slug': 'wsbc-portal', 'meta_launch_url': 'https://support.itworx.test', 'provider': 'provider-1'}],
'/providers/oauth2/': [{'pk': 'provider-1', 'client_id': 'unexpected-client', 'client_type': 'confidential', 'redirect_uris': ['https://support.itworx.test/signin-oidc'], 'property_mappings': ['mapping-groups'], 'authorization_flow': 'flow-default-auth', 'invalidation_flow': 'flow-default-invalidation'}],
'/providers/oauth2/': [provider],
}[path],
raising=True,
)
@@ -279,11 +380,17 @@ def test_typed_oidc_existing_application_requires_matching_provider_contract(mon
finally:
_restore_config(previous)
assert result == {
assert result == ({
'success': True,
'status': 'already_managed',
'message': 'oidc_application_already_matches_typed_plan',
'applicationId': 'application-1',
'clientSecretCreated': False,
} if damage is None else {
'success': False,
'status': 'conflict',
'message': 'existing_oidc_provider_does_not_match_managed_contract',
}
})
def test_authentik_health_success_and_auth_failure_redact_token(monkeypatch):