- Implemented RustFsArtifactObjectStore for managing artifacts in RustFS. - Added unit tests for RustFsArtifactObjectStore functionality. - Created a RustFS migrator tool to transfer objects from S3 to RustFS. - Introduced policy preview and report models for API integration. - Added fixtures and tests for policy preview and report functionality. - Included necessary metadata and scripts for cache_pkg package.
		
			
				
	
	
	
		
			12 KiB
		
	
	
	
	
	
	
	
			
		
		
	
	Authority DPoP & mTLS Implementation Plan (2025-10-19)
Purpose
- Provide the implementation blueprint for AUTH-DPOP-11-001 and AUTH-MTLS-11-002.
- Unify sender-constraint validation across Authority, downstream services, and clients.
- Capture deterministic, testable steps that unblock UI/Signer guilds depending on DPoP/mTLS hardening.
Scope
- Token endpoint validation, issuance, and storage changes inside StellaOps.Authority.
- Shared security primitives consumed by Authority, Scanner, Signer, CLI, and UI.
- Operator-facing configuration, auditing, and observability.
- Out of scope: PoE enforcement (Signer) and CLI/UI client UX; those teams consume the new capabilities.
Status update (2025-10-19):
ValidateDpopProofHandler,AuthorityClientCertificateValidator, and the supporting storage/audit plumbing now live insrc/StellaOps.Authority. DPoP proofs populatecnf.jkt, mTLS bindings enforce certificate thumbprints viacnf.x5t#S256, and token documents persist the sender constraint metadata. In-memory nonce issuance is wired (Redis implementation to follow). Documentation and configuration references were updated (docs/11_AUTHORITY.md). Targeted unit/integration tests were added; running the broader test suite is currently blocked by pre-existingStellaOps.Concelier.Storage.Mongobuild errors.Status update (2025-10-20): Redis-backed nonce configuration is exposed through
security.senderConstraints.dpop.noncewith sample YAML (etc/authority.yaml.sample) and architecture docs refreshed. Operator guide now includes concrete Redis/required audiences snippet; nonce challenge regression remains covered byValidateDpopProof_IssuesNonceChallenge_WhenNonceMissing.Status update (2025-10-23): mTLS enforcement now honours
security.senderConstraints.mtls.enforceForAudiences, automatically rejecting non-mTLS clients targeting audiences such assigner. Certificate bindings validate thumbprint, issuer, subject, serial number, and SAN values, producing deterministic error codes for operators. Introspection responses includecnf.x5t#S256, and new unit tests cover audience enforcement, binding mismatches, and bootstrap storage. Docs/sample config updated accordingly.
Design Summary
- Extract the existing Scanner DpopProofValidatorstack into a sharedStellaOps.Auth.Securitylibrary used by Authority and resource servers.
- Extend Authority configuration (authority.yaml) with strongly-typedsenderConstraints.dpopandsenderConstraints.mtlssections (map to sample already shown in architecture doc).
- Require DPoP proofs on /tokenwhen the registered client policy issenderConstraint=dpop; bind issued access tokens viacnf.jkt.
- Introduce Authority-managed nonce issuance for “high value” audiences (default: signer,attestor) with Redis-backed persistence and deterministic auditing.
- Enable OAuth 2.0 mTLS (RFC 8705) by storing certificate bindings per client, requesting client certificates at TLS termination, and stamping cnf.x5t#S256into issued tokens plus introspection output.
- Surface structured logs and counters for both DPoP and mTLS flows; provide integration tests that cover success, replay, invalid proof, and certificate mismatch cases.
AUTH-DPOP-11-001 — Proof Validation & Nonce Handling
Shared validator
- Move DpopProofValidator, option types, and replay cache interfaces fromStellaOps.Scanner.Coreinto a new assemblyStellaOps.Auth.Security.
- Provide pluggable caches: InMemoryDpopReplayCache(existing) and newRedisDpopReplayCache(leveraging the Authority Redis connection).
- Ensure the validator exposes the validated SecurityKey,jti, andiatso Authority can construct thecnfclaim and compute nonce expiry.
Configuration model
- Extend StellaOpsAuthorityOptions.Securitywith aSenderConstraintsproperty containing:- Dpop(- enabled,- allowedAlgorithms,- maxAgeSeconds,- clockSkewSeconds,- replayWindowSeconds,- noncesettings with- enabled,- ttlSeconds,- requiredAudiences,- maxIssuancePerMinute).
- Mtls(- enabled,- requireChainValidation,- clientCaBundle,- allowedSubjectPatterns,- allowedSanTypes).
 
- Bind from YAML (authority.security.senderConstraints.*) while preserving backwards compatibility (defaults keep both disabled).
Token endpoint pipeline
- Introduce a scoped OpenIddict handler ValidateDpopProofHandlerinserted beforeValidateClientCredentialsHandler.
- Determine the required sender constraint from client metadata:
- Add AuthorityClientMetadataKeys.SenderConstraintstoringdpopormtls.
- Optionally allow per-client overrides for nonce requirement.
 
- Add 
- When dpopis required:- Read the DPoPheader from the ASP.NET request, reject withinvalid_token+WWW-Authenticate: DPoP error="invalid_dpop_proof"if absent.
- Call the shared validator with method/URI. Enforce algorithm allowlist and iatwindow from options.
- Persist the jktthumbprint plus replay cache state in the OpenIddict transaction (AuthorityOpenIddictConstants.DpopKeyThumbprintProperty,DpopIssuedAtProperty).
- When the requested audience intersects SenderConstraints.Dpop.Nonce.RequiredAudiences, requirenoncein the proof; on first failure respond with HTTP 401,error="use_dpop_nonce", and includeDPoP-Nonceheader (see nonce note below). Cache the rejection reason for audit logging.
 
- Read the 
Nonce service
- Add IDpopNonceStorewith methodsIssueAsync(audience, clientId, jkt)andTryConsumeAsync(nonce, audience, clientId, jkt).
- Default implementation RedisDpopNonceStorestoring SHA-256 hashes of nonces keyed byaudience:clientId:jkt. TTL comes fromSenderConstraints.Dpop.Nonce.Ttl.
- Create helper DpopNonceIssuerused byValidateDpopProofHandlerto issue nonces when missing/expired, enforcing issuance rate limits (per options) and tagging audit/log records.
- On successful validation (nonce supplied and consumed) stamp metadata into the transaction for auditing.
- Update ClientCredentialsHandlersto observe nonce enforcement: when a nonce challenge was sent, emit structured audit withnonce_issued,audiences, andretry.
Token issuance
- In HandleClientCredentialsHandler, if the transaction contains a validated DPoP key:- Build cnf.jktusing thumbprint from validator.
- Include auth_time/dpop_jtias needed for diagnostics.
- Persist the thumbprint alongside token metadata in Mongo (extend AuthorityTokenDocumentwithSenderConstraint,KeyThumbprint,Noncefields).
 
- Build 
Auditing & observability
- Emit new audit events:
- authority.dpop.proof.validated(success/failure, clientId, audience, thumbprint, nonce status, jti).
- authority.dpop.nonce.issuedand- authority.dpop.nonce.consumed.
 
- Metrics (Prometheus style):
- authority_dpop_validations_total{result,reason}.
- authority_dpop_nonce_issued_total{audience}and- authority_dpop_nonce_fails_total{reason}.
 
- Structured logs include authority.sender_constraint=dpop,authority.dpop_thumbprint,authority.dpop_nonce.
Testing
- Unit tests for the handler pipeline using fake OpenIddict transactions.
- Replay/nonce tests with in-memory and Redis stores.
- Integration tests in StellaOps.Authority.Testscovering:- Valid DPoP proof issuing cnf.jkt.
- Missing header → challenge with nonce.
- Replayed jtirejected.
- Invalid nonce rejected even after issuance.
 
- Valid DPoP proof issuing 
- Contract tests to ensure /.well-known/openid-configurationadvertisesdpop_signing_alg_values_supportedanddpop_nonce_supportedwhen enabled.
AUTH-MTLS-11-002 — Certificate-Bound Tokens
Configuration model
- Reuse SenderConstraints.Mtlsdescribed above; include:- enforceForAudienceslist (defaults- signer,- attestor,- scheduler).
- certificateRotationGraceSecondsfor overlap.
- allowedClientCertificateAuthoritiesabsolute paths.
 
Kestrel/TLS pipeline
- Configure Kestrel with ClientCertificateMode.AllowCertificateglobally and implement middleware that enforces certificate presence only when the resolved client requires mTLS.
- Add IAuthorityClientCertificateValidatorthat validates presented certificate chain, SANs (dns,uri, optional SPIFFE), and thumbprint matches one of the stored bindings.
- Cache validation results per connection id to avoid rehashing on every request.
Client registration & storage
- Extend AuthorityClientDocumentwithList<AuthorityClientCertificateBinding>containing:- Thumbprint,- SerialNumber,- Subject,- NotBefore,- NotAfter,- Sans,- CreatedAt,- UpdatedAt,- Label.
 
- Provide admin API mutations (/admin/clients/{id}/certificates) for ops tooling (deferred implementation but schema ready).
- Update plugin provisioning store (StandardClientProvisioningStore) to map descriptors with certificate bindings andsenderConstraint.
- Persist binding state in Mongo migrations (index on {clientId, thumbprint}).
Token issuance & introspection
- Add a transaction property capturing the validated client certificate thumbprint.
- HandleClientCredentialsHandler:- When mTLS required, ensure certificate info present; reject otherwise.
- Stamp cnfclaim:principal.SetClaim("cnf", JsonSerializer.Serialize(new { x5t#S256 = thumbprint })).
- Store binding metadata in issued token document for audit.
 
- Update ValidateAccessTokenHandlerand introspection responses to surfacecnf.x5t#S256.
- Ensure refresh tokens (if ever enabled) copy the binding data.
Auditing & observability
- Audit events:
- authority.mtls.handshake(success/failure, clientId, thumbprint, issuer, subject).
- authority.mtls.binding.missingwhen a required client posts without a cert.
 
- Metrics:
- authority_mtls_handshakes_total{result}.
- authority_mtls_certificate_rotations_total.
 
- Logs include authority.sender_constraint=mtls,authority.mtls_thumbprint,authority.mtls_subject.
Testing
- Unit tests for certificate validation rules (SAN mismatches, expiry, CA trust).
- Integration tests running Kestrel with test certificates:
- Successful token issuance with bound certificate.
- Request without certificate → invalid_client.
- Token introspection reveals cnf.x5t#S256.
- Rotation scenario (old + new cert allowed during grace window).
 
Implementation Checklist
DPoP work-stream
- Extract shared validator into StellaOps.Auth.Security; update Scanner references.
- Introduce configuration classes and bind from YAML/environment.
- Implement nonce store (Redis + in-memory), handler integration, and OpenIddict transaction plumbing.
- Stamp cnf.jkt, audit events, and metrics; update Mongo documents and migrations.
- Extend docs: docs/ARCHITECTURE_AUTHORITY.md,docs/security/audit-events.md,docs/security/rate-limits.md, CLI/UI references.
mTLS work-stream
- Extend client document/schema and provisioning stores with certificate bindings + sender constraint flag.
- Configure Kestrel/middleware for optional client certificates and validation service.
- Update token issuance/introspection to honour certificate bindings and emit cnf.x5t#S256.
- Add auditing/metrics and integration tests (happy path + failure).
- Refresh operator documentation (docs/ops/authority-backup-restore.md,docs/ops/authority-monitoring.md, sampleauthority.yaml) to cover certificate lifecycle.
Both streams should conclude with dotnet test src/StellaOps.Authority.sln and documentation cross-links so dependent guilds can unblock UI/Signer work.