Initial curated RAGcore source from c16667f0c9397e2bfc8dd0255b114fba23c8d05e

This commit is contained in:
Public Source Publisher committed 2026-10-01 01:34:21 +02:00
commit 7ca726caf2
659 files changed
+98171

No files matched your search

+241
View File
@@ -0,0 +1,241 @@
"""Adversarial tests for service-account bearer credential lifecycle."""
from __future__ import annotations
import asyncio
from datetime import UTC, datetime, timedelta
from uuid import UUID, uuid4
import pytest
from ragcore.application.identity import ServiceAccountCredentialService
from ragcore.domain.control import Scope, ServiceAccount, Workspace
from ragcore.domain.identity import CredentialLimitExceeded, CredentialScopeViolation
from ragcore.infrastructure.database.identity import InMemoryCredentialRepository
NOW = datetime(2026, 1, 1, tzinfo=UTC)
PEPPER = "test-credential-pepper-that-is-long-enough"
def service_account(*, active: bool = True) -> ServiceAccount:
workspace = Workspace(uuid4(), "Test", "test")
application = workspace.create_application(
id=uuid4(), name="Client", slug="client", scopes={Scope.SEARCH, Scope.CONTEXT}
)
return ServiceAccount(
id=uuid4(),
workspace_id=workspace.id,
application_id=application.id,
name="Worker",
scopes={Scope.SEARCH, Scope.CONTEXT},
active=active,
)
def token_factory(credential_id: UUID) -> str:
return f"rc_sa_{credential_id.hex}_{'a' * 43}"
def build_service(
repository: InMemoryCredentialRepository, accounts: tuple[ServiceAccount, ...]
) -> tuple[ServiceAccountCredentialService, dict[UUID, ServiceAccount]]:
state = {account.id: account for account in accounts}
async def load(account_id: UUID) -> ServiceAccount | None:
return state.get(account_id)
return (
ServiceAccountCredentialService(
repository,
PEPPER,
service_account_loader=load,
clock=lambda: NOW,
token_factory=token_factory,
),
state,
)
@pytest.mark.security
async def test_plaintext_is_returned_once_and_never_stored() -> None:
repository = InMemoryCredentialRepository()
account = service_account()
service, _ = build_service(repository, (account,))
issued = await service.issue(account, scopes={Scope.SEARCH})
assert issued.token.startswith("rc_sa_")
record = await repository.get(issued.credential.id, account.id, account.workspace_id)
assert record is not None
assert issued.token not in repr(record)
assert issued.token.encode() != record.token_digest
assert issued.token not in repr(repository.snapshot())
@pytest.mark.security
async def test_wrong_scope_wrong_token_expired_and_revoked_fail_closed() -> None:
repository = InMemoryCredentialRepository()
account = service_account()
service, _ = build_service(repository, (account,))
issued = await service.issue(
account, scopes={Scope.SEARCH}, expires_at=NOW + timedelta(hours=1)
)
assert await service.verify(
issued.token, service_account=account, required_scopes={Scope.SEARCH}
)
assert (
await service.verify(issued.token, service_account=account, required_scopes={Scope.CONTEXT})
is None
)
assert await service.verify(issued.token[:-1] + "b", service_account=account) is None
assert (
await service.verify(issued.token, service_account=account, now=NOW + timedelta(hours=1))
is None
)
assert await service.revoke(issued.credential.id, account)
assert await service.verify(issued.token, service_account=account) is None
@pytest.mark.security
async def test_authoritative_deactivation_and_scope_reduction_fail_closed() -> None:
repository = InMemoryCredentialRepository()
account = service_account()
service, state = build_service(repository, (account,))
issued = await service.issue(account, scopes={Scope.SEARCH, Scope.CONTEXT})
state[account.id] = ServiceAccount(
id=account.id,
workspace_id=account.workspace_id,
application_id=account.application_id,
name=account.name,
scopes={Scope.SEARCH},
active=True,
)
assert (
await service.verify(issued.token, service_account=account, required_scopes={Scope.CONTEXT})
is None
)
state[account.id] = ServiceAccount(
id=account.id,
workspace_id=account.workspace_id,
application_id=account.application_id,
name=account.name,
scopes={Scope.SEARCH},
active=False,
)
assert await service.verify(issued.token, service_account=account) is None
@pytest.mark.security
async def test_inactive_service_accounts_fail_closed() -> None:
repository = InMemoryCredentialRepository()
account = service_account()
service, state = build_service(repository, (account,))
inactive_account = ServiceAccount(
id=account.id,
workspace_id=account.workspace_id,
application_id=account.application_id,
name=account.name,
scopes=account.scopes,
active=False,
)
state[account.id] = inactive_account
with pytest.raises(ValueError, match="authoritative"):
await service.issue(inactive_account, scopes={Scope.SEARCH})
@pytest.mark.security
async def test_scope_escalation_is_rejected() -> None:
repository = InMemoryCredentialRepository()
account = service_account()
service, _ = build_service(repository, (account,))
with pytest.raises(CredentialScopeViolation):
await service.issue(account, scopes={Scope.ANSWER})
@pytest.mark.security
async def test_rotation_keeps_at_most_two_active_credentials_with_overlap() -> None:
repository = InMemoryCredentialRepository()
account = service_account()
service, _ = build_service(repository, (account,))
first = await service.issue(account, scopes={Scope.SEARCH})
second = await service.issue(account, scopes={Scope.SEARCH})
with pytest.raises(CredentialLimitExceeded):
await service.issue(account, scopes={Scope.SEARCH})
third = await service.issue(account, scopes={Scope.SEARCH}, rotate=True)
assert await service.verify(first.token, service_account=account) is None
assert await service.verify(second.token, service_account=account)
assert await service.verify(third.token, service_account=account)
assert len(await repository.list_active(account.id, account.workspace_id, NOW)) == 2
@pytest.mark.security
async def test_authenticate_accepts_valid_token_without_a_caller_supplied_account() -> None:
repository = InMemoryCredentialRepository()
account = service_account()
service, _ = build_service(repository, (account,))
issued = await service.issue(account, scopes={Scope.SEARCH})
authenticated = await service.authenticate(issued.token, required_scopes={Scope.SEARCH})
assert authenticated is not None
assert authenticated.service_account_id == account.id
assert authenticated.workspace_id == account.workspace_id
@pytest.mark.security
async def test_authenticate_rejects_malformed_unknown_wrong_scope_expired_and_revoked() -> None:
repository = InMemoryCredentialRepository()
account = service_account()
service, _ = build_service(repository, (account,))
issued = await service.issue(
account, scopes={Scope.SEARCH}, expires_at=NOW + timedelta(hours=1)
)
assert await service.authenticate("not-a-real-token") is None
assert await service.authenticate(f"rc_sa_{uuid4().hex}_{'a' * 43}") is None
assert await service.authenticate(issued.token[:-1] + "b") is None
assert await service.authenticate(issued.token, required_scopes={Scope.CONTEXT}) is None
assert (
await service.authenticate(issued.token, now=NOW + timedelta(hours=1)) is None
)
assert await service.revoke(issued.credential.id, account)
assert await service.authenticate(issued.token) is None
@pytest.mark.security
async def test_authenticate_rejects_deactivated_service_account() -> None:
repository = InMemoryCredentialRepository()
account = service_account()
service, state = build_service(repository, (account,))
issued = await service.issue(account, scopes={Scope.SEARCH})
state[account.id] = ServiceAccount(
id=account.id,
workspace_id=account.workspace_id,
application_id=account.application_id,
name=account.name,
scopes=account.scopes,
active=False,
)
assert await service.authenticate(issued.token) is None
@pytest.mark.security
async def test_concurrent_issuance_stays_within_rotation_limit() -> None:
repository = InMemoryCredentialRepository()
account = service_account()
service, _ = build_service(repository, (account,))
results = await asyncio.gather(
*(service.issue(account, scopes={Scope.SEARCH}) for _ in range(3)),
return_exceptions=True,
)
assert sum(not isinstance(result, CredentialLimitExceeded) for result in results) == 2
assert len(await repository.list_active(account.id, account.workspace_id, NOW)) == 2