- 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 withenabled,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.issuedandauthority.dpop.nonce.consumed.
 - Metrics (Prometheus style):
authority_dpop_validations_total{result,reason}.authority_dpop_nonce_issued_total{audience}andauthority_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 (defaultssigner,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.