Restructure solution layout by module
	
		
			
	
		
	
	
		
	
		
			Some checks failed
		
		
	
	
		
			
				
	
				Docs CI / lint-and-preview (push) Has been cancelled
				
			
		
		
	
	
				
					
				
			
		
			Some checks failed
		
		
	
	Docs CI / lint-and-preview (push) Has been cancelled
				
			This commit is contained in:
		| @@ -1,337 +1,337 @@ | ||||
| # StellaOps Authority configuration template. | ||||
| # Copy to ../etc/authority.yaml (relative to the Authority content root) | ||||
| # and adjust values to fit your environment. Environment variables | ||||
| # prefixed with STELLAOPS_AUTHORITY_ override these values at runtime. | ||||
| # Example: STELLAOPS_AUTHORITY__ISSUER=https://authority.example.com | ||||
|  | ||||
| schemaVersion: 1 | ||||
|  | ||||
| # Absolute issuer URI advertised to clients. Use HTTPS for anything | ||||
| # beyond loopback development. | ||||
| issuer: "https://authority.stella-ops.local" | ||||
|  | ||||
| # Token lifetimes expressed as HH:MM:SS or DD.HH:MM:SS. | ||||
| accessTokenLifetime: "00:02:00" | ||||
| refreshTokenLifetime: "30.00:00:00" | ||||
| identityTokenLifetime: "00:05:00" | ||||
| authorizationCodeLifetime: "00:05:00" | ||||
| deviceCodeLifetime: "00:15:00" | ||||
|  | ||||
| # MongoDB storage connection details. | ||||
| storage: | ||||
|   connectionString: "mongodb://localhost:27017/stellaops-authority" | ||||
|   # databaseName: "stellaops_authority" | ||||
|   commandTimeout: "00:00:30" | ||||
|  | ||||
| # Signing configuration for revocation bundles and JWKS. | ||||
| signing: | ||||
|   enabled: true | ||||
|   activeKeyId: "authority-signing-2025-dev" | ||||
|   keyPath: "../certificates/authority-signing-2025-dev.pem" | ||||
|   algorithm: "ES256" | ||||
|   keySource: "file" | ||||
|   # provider: "default" | ||||
|   additionalKeys: | ||||
|     - keyId: "authority-signing-dev" | ||||
|       path: "../certificates/authority-signing-dev.pem" | ||||
|       source: "file" | ||||
|   # Rotation flow: | ||||
|   #   1. Generate a new PEM under ./certificates (e.g. authority-signing-2026-dev.pem). | ||||
|   #   2. Trigger the .gitea/workflows/authority-key-rotation.yml workflow (or run | ||||
|   #      ops/authority/key-rotation.sh) with the new keyId/keyPath. | ||||
|   #   3. Update activeKeyId/keyPath above and move the previous key into additionalKeys | ||||
|   #      so restarts retain retired material for JWKS consumers. | ||||
|  | ||||
| # Bootstrap administrative endpoints (initial provisioning). | ||||
| bootstrap: | ||||
|   enabled: false | ||||
|   apiKey: "change-me" | ||||
|   defaultIdentityProvider: "standard" | ||||
|  | ||||
| # Directories scanned for Authority plug-ins. Relative paths resolve | ||||
| # against the application content root, enabling air-gapped deployments | ||||
| # that package plug-ins alongside binaries. | ||||
| pluginDirectories: | ||||
|   - "../StellaOps.Authority.PluginBinaries" | ||||
|   # "/var/lib/stellaops/authority/plugins" | ||||
|  | ||||
| # Plug-in manifests live in descriptors below; per-plugin settings are stored | ||||
| # in the configurationDirectory (YAML files). Authority will load any enabled | ||||
| # plugins and surface their metadata/capabilities to the host. | ||||
| plugins: | ||||
|   configurationDirectory: "../etc/authority.plugins" | ||||
|   descriptors: | ||||
|     standard: | ||||
|       type: "standard" | ||||
|       assemblyName: "StellaOps.Authority.Plugin.Standard" | ||||
|       enabled: true | ||||
|       configFile: "standard.yaml" | ||||
|       capabilities: | ||||
|         - password | ||||
|         - bootstrap | ||||
|         - clientProvisioning | ||||
|       metadata: | ||||
|         defaultRole: "operators" | ||||
|     # Example for an external identity provider plugin. Leave disabled unless | ||||
|     # the plug-in package exists under StellaOps.Authority.PluginBinaries. | ||||
|     ldap: | ||||
|       type: "ldap" | ||||
|       assemblyName: "StellaOps.Authority.Plugin.Ldap" | ||||
|       enabled: false | ||||
|       configFile: "ldap.yaml" | ||||
|       capabilities: | ||||
|         - password | ||||
|         - mfa | ||||
|  | ||||
| # OAuth client registrations issued by Authority. These examples cover Notify WebService | ||||
| # in dev (notify.dev audience) and production (notify audience). Replace the secret files | ||||
| # with paths to your sealed credentials before enabling bootstrap mode. | ||||
| clients: | ||||
|   - clientId: "notify-web-dev" | ||||
|     displayName: "Notify WebService (dev)" | ||||
|     grantTypes: [ "client_credentials" ] | ||||
|     audiences: [ "notify.dev" ] | ||||
|     scopes: [ "notify.read", "notify.admin" ] | ||||
|     senderConstraint: "dpop" | ||||
|     auth: | ||||
|       type: "client_secret" | ||||
|       secretFile: "../secrets/notify-web-dev.secret" | ||||
|   - clientId: "notify-web" | ||||
|     displayName: "Notify WebService" | ||||
|     grantTypes: [ "client_credentials" ] | ||||
|     audiences: [ "notify" ] | ||||
|     scopes: [ "notify.read", "notify.admin" ] | ||||
|     senderConstraint: "dpop" | ||||
|     auth: | ||||
|       type: "client_secret" | ||||
|       secretFile: "../secrets/notify-web.secret" | ||||
|   - clientId: "concelier-ingest" | ||||
|     displayName: "Concelier Ingestion" | ||||
|     grantTypes: [ "client_credentials" ] | ||||
|     audiences: [ "api://concelier" ] | ||||
|     scopes: [ "advisory:ingest", "advisory:read" ] | ||||
|     tenant: "tenant-default" | ||||
|     senderConstraint: "dpop" | ||||
|     auth: | ||||
|       type: "client_secret" | ||||
|       secretFile: "../secrets/concelier-ingest.secret" | ||||
|   - clientId: "excitor-ingest" | ||||
|     displayName: "Excititor VEX Ingestion" | ||||
|     grantTypes: [ "client_credentials" ] | ||||
|     audiences: [ "api://excitor" ] | ||||
|     scopes: [ "vex:ingest", "vex:read" ] | ||||
|     tenant: "tenant-default" | ||||
|     senderConstraint: "dpop" | ||||
|     auth: | ||||
|       type: "client_secret" | ||||
|       secretFile: "../secrets/excitor-ingest.secret" | ||||
|   - clientId: "aoc-verifier" | ||||
|     displayName: "AOC Verification Agent" | ||||
|     grantTypes: [ "client_credentials" ] | ||||
|     audiences: [ "api://concelier", "api://excitor" ] | ||||
|     scopes: [ "aoc:verify", "advisory:read", "vex:read" ] | ||||
|     tenant: "tenant-default" | ||||
|     senderConstraint: "dpop" | ||||
|     auth: | ||||
|       type: "client_secret" | ||||
|       secretFile: "../secrets/aoc-verifier.secret" | ||||
|   - clientId: "policy-engine" | ||||
|     displayName: "Policy Engine Service" | ||||
|     grantTypes: [ "client_credentials" ] | ||||
|     audiences: [ "api://policy-engine" ] | ||||
|     scopes: [ "policy:run", "findings:read", "effective:write" ] | ||||
|     tenant: "tenant-default" | ||||
|     properties: | ||||
|       serviceIdentity: "policy-engine" | ||||
|     senderConstraint: "dpop" | ||||
|     auth: | ||||
|       type: "client_secret" | ||||
|       secretFile: "../secrets/policy-engine.secret" | ||||
|   - clientId: "policy-cli" | ||||
|     displayName: "Policy Automation CLI" | ||||
|     grantTypes: [ "client_credentials" ] | ||||
|     audiences: [ "api://policy-engine" ] | ||||
|     scopes: [ "policy:read", "policy:author", "policy:review", "policy:simulate", "findings:read" ] | ||||
|     tenant: "tenant-default" | ||||
|     senderConstraint: "dpop" | ||||
|     auth: | ||||
|       type: "client_secret" | ||||
|       secretFile: "../secrets/policy-cli.secret" | ||||
|   - clientId: "exceptions-service" | ||||
|     displayName: "Policy Engine Exceptions Worker" | ||||
|     grantTypes: [ "client_credentials" ] | ||||
|     audiences: [ "api://policy-engine" ] | ||||
|     scopes: [ "exceptions:read", "exceptions:write" ] | ||||
|     tenant: "tenant-default" | ||||
|     senderConstraint: "dpop" | ||||
|     auth: | ||||
|       type: "client_secret" | ||||
|       secretFile: "../secrets/exceptions-service.secret" | ||||
|   - clientId: "console-web" | ||||
|     displayName: "StellaOps Console" | ||||
|     grantTypes: [ "authorization_code", "refresh_token" ] | ||||
|     audiences: [ "console" ] | ||||
|     scopes: [ "openid", "profile", "email", "ui.read", "authority:tenants.read", "advisory:read", "vex:read", "exceptions:read", "exceptions:approve", "aoc:verify", "findings:read", "orch:read", "vuln:read" ] | ||||
|     # exceptions:approve is elevated via fresh-auth and requires an MFA-capable identity provider. | ||||
|     tenant: "tenant-default" | ||||
|     senderConstraint: "dpop" | ||||
|     redirectUris: | ||||
|       - "https://console.stella-ops.local/oidc/callback" | ||||
|     postLogoutRedirectUris: | ||||
|       - "https://console.stella-ops.local/" | ||||
|     # Gateway must forward X-Stella-Tenant for /console endpoints; fresh-auth window (300s) | ||||
|     # returned by /console/profile governs admin actions in the Console UI. | ||||
|     auth: | ||||
|       type: "client_secret" | ||||
|       secretFile: "../secrets/console-web.secret" | ||||
|   - clientId: "cartographer-service" | ||||
|     displayName: "Cartographer Service" | ||||
|     grantTypes: [ "client_credentials" ] | ||||
|     audiences: [ "api://cartographer" ] | ||||
|     scopes: [ "graph:write", "graph:read" ] | ||||
|     tenant: "tenant-default" | ||||
|     properties: | ||||
|       serviceIdentity: "cartographer" | ||||
|     senderConstraint: "dpop" | ||||
|     auth: | ||||
|       type: "client_secret" | ||||
|       secretFile: "../secrets/cartographer-service.secret" | ||||
|   - clientId: "graph-api" | ||||
|     displayName: "Graph API Gateway" | ||||
|     grantTypes: [ "client_credentials" ] | ||||
|     audiences: [ "api://graph-api" ] | ||||
|     scopes: [ "graph:read", "graph:export", "graph:simulate" ] | ||||
|     tenant: "tenant-default" | ||||
|     senderConstraint: "dpop" | ||||
|     auth: | ||||
|       type: "client_secret" | ||||
|       secretFile: "../secrets/graph-api.secret" | ||||
|   - clientId: "export-center-operator" | ||||
|     displayName: "Export Center Operator" | ||||
|     grantTypes: [ "client_credentials" ] | ||||
|     audiences: [ "api://export-center" ] | ||||
|     scopes: [ "export.viewer", "export.operator" ] | ||||
|     tenant: "tenant-default" | ||||
|     senderConstraint: "dpop" | ||||
|     auth: | ||||
|       type: "client_secret" | ||||
|       secretFile: "../secrets/export-center-operator.secret" | ||||
|   - clientId: "export-center-admin" | ||||
|     displayName: "Export Center Admin" | ||||
|     grantTypes: [ "client_credentials" ] | ||||
|     audiences: [ "api://export-center" ] | ||||
|     scopes: [ "export.viewer", "export.operator", "export.admin" ] | ||||
|     tenant: "tenant-default" | ||||
|     senderConstraint: "dpop" | ||||
|     auth: | ||||
|       type: "client_secret" | ||||
|       secretFile: "../secrets/export-center-admin.secret" | ||||
|   - clientId: "vuln-explorer-ui" | ||||
|     displayName: "Vuln Explorer UI" | ||||
|     grantTypes: [ "client_credentials" ] | ||||
|     audiences: [ "api://vuln-explorer" ] | ||||
|     scopes: [ "vuln:read" ] | ||||
|     tenant: "tenant-default" | ||||
|     senderConstraint: "dpop" | ||||
|     auth: | ||||
|       type: "client_secret" | ||||
|       secretFile: "../secrets/vuln-explorer-ui.secret" | ||||
|   # Signals sensors must request aoc:verify alongside write scope. | ||||
|   - clientId: "signals-uploader" | ||||
|     displayName: "Signals Sensor" | ||||
|     grantTypes: [ "client_credentials" ] | ||||
|     audiences: [ "api://signals" ] | ||||
|     scopes: [ "signals:write", "signals:read", "aoc:verify" ] | ||||
|     tenant: "tenant-default" | ||||
|     senderConstraint: "dpop" | ||||
|     auth: | ||||
|       type: "client_secret" | ||||
|       secretFile: "../secrets/signals-uploader.secret" | ||||
|  | ||||
| tenants: | ||||
|   - name: "tenant-default" | ||||
|     roles: | ||||
|       orch-viewer: | ||||
|         scopes: [ "orch:read" ] | ||||
|       orch-operator: | ||||
|         scopes: [ "orch:read", "orch:operate" ] | ||||
|       policy-author: | ||||
|         scopes: [ "policy:author", "policy:read", "policy:simulate", "findings:read" ] | ||||
|       policy-reviewer: | ||||
|         scopes: [ "policy:review", "policy:read", "policy:simulate", "findings:read" ] | ||||
|       policy-approver: | ||||
|         scopes: [ "policy:approve", "policy:review", "policy:read", "policy:simulate", "findings:read" ] | ||||
|       policy-operator: | ||||
|         scopes: [ "policy:operate", "policy:run", "policy:activate", "policy:read", "policy:simulate", "findings:read" ] | ||||
|       policy-auditor: | ||||
|         scopes: [ "policy:audit", "policy:read", "policy:simulate", "findings:read" ] | ||||
|       export-viewer: | ||||
|         scopes: [ "export.viewer" ] | ||||
|       export-operator: | ||||
|         scopes: [ "export.viewer", "export.operator" ] | ||||
|       export-admin: | ||||
|         scopes: [ "export.viewer", "export.operator", "export.admin" ] | ||||
|  | ||||
| # Exception approval routing templates used by Policy Engine and Console. | ||||
| exceptions: | ||||
|   routingTemplates: | ||||
|     - id: "secops" | ||||
|       authorityRouteId: "approvals/secops" | ||||
|       requireMfa: true | ||||
|       description: "Security Operations approval chain" | ||||
|     - id: "governance" | ||||
|       authorityRouteId: "approvals/governance" | ||||
|       requireMfa: false | ||||
|       description: "Governance review (non-production)" | ||||
|  | ||||
| # CIDR ranges that bypass network-sensitive policies (e.g. on-host cron jobs). | ||||
| # Keep the list tight: localhost is sufficient for most air-gapped installs. | ||||
| bypassNetworks: | ||||
|   - "127.0.0.1/32" | ||||
|   - "::1/128" | ||||
|  | ||||
| # Security posture (rate limiting + sender constraints). | ||||
| security: | ||||
|   rateLimiting: | ||||
|     token: | ||||
|       enabled: true | ||||
|       permitLimit: 30 | ||||
|       window: "00:01:00" | ||||
|       queueLimit: 0 | ||||
|     authorize: | ||||
|       enabled: true | ||||
|       permitLimit: 60 | ||||
|       window: "00:01:00" | ||||
|       queueLimit: 10 | ||||
|     internal: | ||||
|       enabled: false | ||||
|       permitLimit: 5 | ||||
|       window: "00:01:00" | ||||
|       queueLimit: 0 | ||||
|   senderConstraints: | ||||
|     dpop: | ||||
|       enabled: true | ||||
|       allowedAlgorithms: [ "ES256", "ES384" ] | ||||
|       proofLifetime: "00:02:00" | ||||
|       allowedClockSkew: "00:00:30" | ||||
|       replayWindow: "00:05:00" | ||||
|       nonce: | ||||
|         enabled: true | ||||
|         ttl: "00:10:00" | ||||
|         maxIssuancePerMinute: 120 | ||||
|         store: "memory" # Set to "redis" for multi-node Authority deployments. | ||||
|         requiredAudiences: | ||||
|           - "signer" | ||||
|           - "attestor" | ||||
|         # redisConnectionString: "redis://authority-redis:6379?ssl=false" | ||||
|     mtls: | ||||
|       enabled: false | ||||
|       requireChainValidation: true | ||||
|       rotationGrace: "00:15:00" | ||||
|       enforceForAudiences: | ||||
|         - "signer" # Requests for these audiences force mTLS sender constraints | ||||
|       allowedSanTypes: | ||||
|         - "dns" | ||||
|         - "uri" | ||||
|       allowedCertificateAuthorities: [ ] | ||||
|       allowedSubjectPatterns: [ ] | ||||
| # StellaOps Authority configuration template. | ||||
| # Copy to ../etc/authority.yaml (relative to the Authority content root) | ||||
| # and adjust values to fit your environment. Environment variables | ||||
| # prefixed with STELLAOPS_AUTHORITY_ override these values at runtime. | ||||
| # Example: STELLAOPS_AUTHORITY__ISSUER=https://authority.example.com | ||||
|  | ||||
| schemaVersion: 1 | ||||
|  | ||||
| # Absolute issuer URI advertised to clients. Use HTTPS for anything | ||||
| # beyond loopback development. | ||||
| issuer: "https://authority.stella-ops.local" | ||||
|  | ||||
| # Token lifetimes expressed as HH:MM:SS or DD.HH:MM:SS. | ||||
| accessTokenLifetime: "00:02:00" | ||||
| refreshTokenLifetime: "30.00:00:00" | ||||
| identityTokenLifetime: "00:05:00" | ||||
| authorizationCodeLifetime: "00:05:00" | ||||
| deviceCodeLifetime: "00:15:00" | ||||
|  | ||||
| # MongoDB storage connection details. | ||||
| storage: | ||||
|   connectionString: "mongodb://localhost:27017/stellaops-authority" | ||||
|   # databaseName: "stellaops_authority" | ||||
|   commandTimeout: "00:00:30" | ||||
|  | ||||
| # Signing configuration for revocation bundles and JWKS. | ||||
| signing: | ||||
|   enabled: true | ||||
|   activeKeyId: "authority-signing-2025-dev" | ||||
|   keyPath: "../certificates/authority-signing-2025-dev.pem" | ||||
|   algorithm: "ES256" | ||||
|   keySource: "file" | ||||
|   # provider: "default" | ||||
|   additionalKeys: | ||||
|     - keyId: "authority-signing-dev" | ||||
|       path: "../certificates/authority-signing-dev.pem" | ||||
|       source: "file" | ||||
|   # Rotation flow: | ||||
|   #   1. Generate a new PEM under ./certificates (e.g. authority-signing-2026-dev.pem). | ||||
|   #   2. Trigger the .gitea/workflows/authority-key-rotation.yml workflow (or run | ||||
|   #      ops/authority/key-rotation.sh) with the new keyId/keyPath. | ||||
|   #   3. Update activeKeyId/keyPath above and move the previous key into additionalKeys | ||||
|   #      so restarts retain retired material for JWKS consumers. | ||||
|  | ||||
| # Bootstrap administrative endpoints (initial provisioning). | ||||
| bootstrap: | ||||
|   enabled: false | ||||
|   apiKey: "change-me" | ||||
|   defaultIdentityProvider: "standard" | ||||
|  | ||||
| # Directories scanned for Authority plug-ins. Relative paths resolve | ||||
| # against the application content root, enabling air-gapped deployments | ||||
| # that package plug-ins alongside binaries. | ||||
| pluginDirectories: | ||||
|   - "../StellaOps.Authority.PluginBinaries" | ||||
|   # "/var/lib/stellaops/authority/plugins" | ||||
|  | ||||
| # Plug-in manifests live in descriptors below; per-plugin settings are stored | ||||
| # in the configurationDirectory (YAML files). Authority will load any enabled | ||||
| # plugins and surface their metadata/capabilities to the host. | ||||
| plugins: | ||||
|   configurationDirectory: "../etc/authority.plugins" | ||||
|   descriptors: | ||||
|     standard: | ||||
|       type: "standard" | ||||
|       assemblyName: "StellaOps.Authority.Plugin.Standard" | ||||
|       enabled: true | ||||
|       configFile: "standard.yaml" | ||||
|       capabilities: | ||||
|         - password | ||||
|         - bootstrap | ||||
|         - clientProvisioning | ||||
|       metadata: | ||||
|         defaultRole: "operators" | ||||
|     # Example for an external identity provider plugin. Leave disabled unless | ||||
|     # the plug-in package exists under StellaOps.Authority.PluginBinaries. | ||||
|     ldap: | ||||
|       type: "ldap" | ||||
|       assemblyName: "StellaOps.Authority.Plugin.Ldap" | ||||
|       enabled: false | ||||
|       configFile: "ldap.yaml" | ||||
|       capabilities: | ||||
|         - password | ||||
|         - mfa | ||||
|  | ||||
| # OAuth client registrations issued by Authority. These examples cover Notify WebService | ||||
| # in dev (notify.dev audience) and production (notify audience). Replace the secret files | ||||
| # with paths to your sealed credentials before enabling bootstrap mode. | ||||
| clients: | ||||
|   - clientId: "notify-web-dev" | ||||
|     displayName: "Notify WebService (dev)" | ||||
|     grantTypes: [ "client_credentials" ] | ||||
|     audiences: [ "notify.dev" ] | ||||
|     scopes: [ "notify.read", "notify.admin" ] | ||||
|     senderConstraint: "dpop" | ||||
|     auth: | ||||
|       type: "client_secret" | ||||
|       secretFile: "../secrets/notify-web-dev.secret" | ||||
|   - clientId: "notify-web" | ||||
|     displayName: "Notify WebService" | ||||
|     grantTypes: [ "client_credentials" ] | ||||
|     audiences: [ "notify" ] | ||||
|     scopes: [ "notify.read", "notify.admin" ] | ||||
|     senderConstraint: "dpop" | ||||
|     auth: | ||||
|       type: "client_secret" | ||||
|       secretFile: "../secrets/notify-web.secret" | ||||
|   - clientId: "concelier-ingest" | ||||
|     displayName: "Concelier Ingestion" | ||||
|     grantTypes: [ "client_credentials" ] | ||||
|     audiences: [ "api://concelier" ] | ||||
|     scopes: [ "advisory:ingest", "advisory:read" ] | ||||
|     tenant: "tenant-default" | ||||
|     senderConstraint: "dpop" | ||||
|     auth: | ||||
|       type: "client_secret" | ||||
|       secretFile: "../secrets/concelier-ingest.secret" | ||||
|   - clientId: "excitor-ingest" | ||||
|     displayName: "Excititor VEX Ingestion" | ||||
|     grantTypes: [ "client_credentials" ] | ||||
|     audiences: [ "api://excitor" ] | ||||
|     scopes: [ "vex:ingest", "vex:read" ] | ||||
|     tenant: "tenant-default" | ||||
|     senderConstraint: "dpop" | ||||
|     auth: | ||||
|       type: "client_secret" | ||||
|       secretFile: "../secrets/excitor-ingest.secret" | ||||
|   - clientId: "aoc-verifier" | ||||
|     displayName: "AOC Verification Agent" | ||||
|     grantTypes: [ "client_credentials" ] | ||||
|     audiences: [ "api://concelier", "api://excitor" ] | ||||
|     scopes: [ "aoc:verify", "advisory:read", "vex:read" ] | ||||
|     tenant: "tenant-default" | ||||
|     senderConstraint: "dpop" | ||||
|     auth: | ||||
|       type: "client_secret" | ||||
|       secretFile: "../secrets/aoc-verifier.secret" | ||||
|   - clientId: "policy-engine" | ||||
|     displayName: "Policy Engine Service" | ||||
|     grantTypes: [ "client_credentials" ] | ||||
|     audiences: [ "api://policy-engine" ] | ||||
|     scopes: [ "policy:run", "findings:read", "effective:write" ] | ||||
|     tenant: "tenant-default" | ||||
|     properties: | ||||
|       serviceIdentity: "policy-engine" | ||||
|     senderConstraint: "dpop" | ||||
|     auth: | ||||
|       type: "client_secret" | ||||
|       secretFile: "../secrets/policy-engine.secret" | ||||
|   - clientId: "policy-cli" | ||||
|     displayName: "Policy Automation CLI" | ||||
|     grantTypes: [ "client_credentials" ] | ||||
|     audiences: [ "api://policy-engine" ] | ||||
|     scopes: [ "policy:read", "policy:author", "policy:review", "policy:simulate", "findings:read" ] | ||||
|     tenant: "tenant-default" | ||||
|     senderConstraint: "dpop" | ||||
|     auth: | ||||
|       type: "client_secret" | ||||
|       secretFile: "../secrets/policy-cli.secret" | ||||
|   - clientId: "exceptions-service" | ||||
|     displayName: "Policy Engine Exceptions Worker" | ||||
|     grantTypes: [ "client_credentials" ] | ||||
|     audiences: [ "api://policy-engine" ] | ||||
|     scopes: [ "exceptions:read", "exceptions:write" ] | ||||
|     tenant: "tenant-default" | ||||
|     senderConstraint: "dpop" | ||||
|     auth: | ||||
|       type: "client_secret" | ||||
|       secretFile: "../secrets/exceptions-service.secret" | ||||
|   - clientId: "console-web" | ||||
|     displayName: "StellaOps Console" | ||||
|     grantTypes: [ "authorization_code", "refresh_token" ] | ||||
|     audiences: [ "console" ] | ||||
|     scopes: [ "openid", "profile", "email", "ui.read", "authority:tenants.read", "advisory:read", "vex:read", "exceptions:read", "exceptions:approve", "aoc:verify", "findings:read", "orch:read", "vuln:read" ] | ||||
|     # exceptions:approve is elevated via fresh-auth and requires an MFA-capable identity provider. | ||||
|     tenant: "tenant-default" | ||||
|     senderConstraint: "dpop" | ||||
|     redirectUris: | ||||
|       - "https://console.stella-ops.local/oidc/callback" | ||||
|     postLogoutRedirectUris: | ||||
|       - "https://console.stella-ops.local/" | ||||
|     # Gateway must forward X-Stella-Tenant for /console endpoints; fresh-auth window (300s) | ||||
|     # returned by /console/profile governs admin actions in the Console UI. | ||||
|     auth: | ||||
|       type: "client_secret" | ||||
|       secretFile: "../secrets/console-web.secret" | ||||
|   - clientId: "cartographer-service" | ||||
|     displayName: "Cartographer Service" | ||||
|     grantTypes: [ "client_credentials" ] | ||||
|     audiences: [ "api://cartographer" ] | ||||
|     scopes: [ "graph:write", "graph:read" ] | ||||
|     tenant: "tenant-default" | ||||
|     properties: | ||||
|       serviceIdentity: "cartographer" | ||||
|     senderConstraint: "dpop" | ||||
|     auth: | ||||
|       type: "client_secret" | ||||
|       secretFile: "../secrets/cartographer-service.secret" | ||||
|   - clientId: "graph-api" | ||||
|     displayName: "Graph API Gateway" | ||||
|     grantTypes: [ "client_credentials" ] | ||||
|     audiences: [ "api://graph-api" ] | ||||
|     scopes: [ "graph:read", "graph:export", "graph:simulate" ] | ||||
|     tenant: "tenant-default" | ||||
|     senderConstraint: "dpop" | ||||
|     auth: | ||||
|       type: "client_secret" | ||||
|       secretFile: "../secrets/graph-api.secret" | ||||
|   - clientId: "export-center-operator" | ||||
|     displayName: "Export Center Operator" | ||||
|     grantTypes: [ "client_credentials" ] | ||||
|     audiences: [ "api://export-center" ] | ||||
|     scopes: [ "export.viewer", "export.operator" ] | ||||
|     tenant: "tenant-default" | ||||
|     senderConstraint: "dpop" | ||||
|     auth: | ||||
|       type: "client_secret" | ||||
|       secretFile: "../secrets/export-center-operator.secret" | ||||
|   - clientId: "export-center-admin" | ||||
|     displayName: "Export Center Admin" | ||||
|     grantTypes: [ "client_credentials" ] | ||||
|     audiences: [ "api://export-center" ] | ||||
|     scopes: [ "export.viewer", "export.operator", "export.admin" ] | ||||
|     tenant: "tenant-default" | ||||
|     senderConstraint: "dpop" | ||||
|     auth: | ||||
|       type: "client_secret" | ||||
|       secretFile: "../secrets/export-center-admin.secret" | ||||
|   - clientId: "vuln-explorer-ui" | ||||
|     displayName: "Vuln Explorer UI" | ||||
|     grantTypes: [ "client_credentials" ] | ||||
|     audiences: [ "api://vuln-explorer" ] | ||||
|     scopes: [ "vuln:read" ] | ||||
|     tenant: "tenant-default" | ||||
|     senderConstraint: "dpop" | ||||
|     auth: | ||||
|       type: "client_secret" | ||||
|       secretFile: "../secrets/vuln-explorer-ui.secret" | ||||
|   # Signals sensors must request aoc:verify alongside write scope. | ||||
|   - clientId: "signals-uploader" | ||||
|     displayName: "Signals Sensor" | ||||
|     grantTypes: [ "client_credentials" ] | ||||
|     audiences: [ "api://signals" ] | ||||
|     scopes: [ "signals:write", "signals:read", "aoc:verify" ] | ||||
|     tenant: "tenant-default" | ||||
|     senderConstraint: "dpop" | ||||
|     auth: | ||||
|       type: "client_secret" | ||||
|       secretFile: "../secrets/signals-uploader.secret" | ||||
|  | ||||
| tenants: | ||||
|   - name: "tenant-default" | ||||
|     roles: | ||||
|       orch-viewer: | ||||
|         scopes: [ "orch:read" ] | ||||
|       orch-operator: | ||||
|         scopes: [ "orch:read", "orch:operate" ] | ||||
|       policy-author: | ||||
|         scopes: [ "policy:author", "policy:read", "policy:simulate", "findings:read" ] | ||||
|       policy-reviewer: | ||||
|         scopes: [ "policy:review", "policy:read", "policy:simulate", "findings:read" ] | ||||
|       policy-approver: | ||||
|         scopes: [ "policy:approve", "policy:review", "policy:read", "policy:simulate", "findings:read" ] | ||||
|       policy-operator: | ||||
|         scopes: [ "policy:operate", "policy:run", "policy:activate", "policy:read", "policy:simulate", "findings:read" ] | ||||
|       policy-auditor: | ||||
|         scopes: [ "policy:audit", "policy:read", "policy:simulate", "findings:read" ] | ||||
|       export-viewer: | ||||
|         scopes: [ "export.viewer" ] | ||||
|       export-operator: | ||||
|         scopes: [ "export.viewer", "export.operator" ] | ||||
|       export-admin: | ||||
|         scopes: [ "export.viewer", "export.operator", "export.admin" ] | ||||
|  | ||||
| # Exception approval routing templates used by Policy Engine and Console. | ||||
| exceptions: | ||||
|   routingTemplates: | ||||
|     - id: "secops" | ||||
|       authorityRouteId: "approvals/secops" | ||||
|       requireMfa: true | ||||
|       description: "Security Operations approval chain" | ||||
|     - id: "governance" | ||||
|       authorityRouteId: "approvals/governance" | ||||
|       requireMfa: false | ||||
|       description: "Governance review (non-production)" | ||||
|  | ||||
| # CIDR ranges that bypass network-sensitive policies (e.g. on-host cron jobs). | ||||
| # Keep the list tight: localhost is sufficient for most air-gapped installs. | ||||
| bypassNetworks: | ||||
|   - "127.0.0.1/32" | ||||
|   - "::1/128" | ||||
|  | ||||
| # Security posture (rate limiting + sender constraints). | ||||
| security: | ||||
|   rateLimiting: | ||||
|     token: | ||||
|       enabled: true | ||||
|       permitLimit: 30 | ||||
|       window: "00:01:00" | ||||
|       queueLimit: 0 | ||||
|     authorize: | ||||
|       enabled: true | ||||
|       permitLimit: 60 | ||||
|       window: "00:01:00" | ||||
|       queueLimit: 10 | ||||
|     internal: | ||||
|       enabled: false | ||||
|       permitLimit: 5 | ||||
|       window: "00:01:00" | ||||
|       queueLimit: 0 | ||||
|   senderConstraints: | ||||
|     dpop: | ||||
|       enabled: true | ||||
|       allowedAlgorithms: [ "ES256", "ES384" ] | ||||
|       proofLifetime: "00:02:00" | ||||
|       allowedClockSkew: "00:00:30" | ||||
|       replayWindow: "00:05:00" | ||||
|       nonce: | ||||
|         enabled: true | ||||
|         ttl: "00:10:00" | ||||
|         maxIssuancePerMinute: 120 | ||||
|         store: "memory" # Set to "redis" for multi-node Authority deployments. | ||||
|         requiredAudiences: | ||||
|           - "signer" | ||||
|           - "attestor" | ||||
|         # redisConnectionString: "redis://authority-redis:6379?ssl=false" | ||||
|     mtls: | ||||
|       enabled: false | ||||
|       requireChainValidation: true | ||||
|       rotationGrace: "00:15:00" | ||||
|       enforceForAudiences: | ||||
|         - "signer" # Requests for these audiences force mTLS sender constraints | ||||
|       allowedSanTypes: | ||||
|         - "dns" | ||||
|         - "uri" | ||||
|       allowedCertificateAuthorities: [ ] | ||||
|       allowedSubjectPatterns: [ ] | ||||
|   | ||||
		Reference in New Issue
	
	Block a user