- Add ConsoleSessionStore for managing console session state including tenants, profile, and token information. - Create OperatorContextService to manage operator context for orchestrator actions. - Implement OperatorMetadataInterceptor to enrich HTTP requests with operator context metadata. - Develop ConsoleProfileComponent to display user profile and session details, including tenant information and access tokens. - Add corresponding HTML and SCSS for ConsoleProfileComponent to enhance UI presentation. - Write unit tests for ConsoleProfileComponent to ensure correct rendering and functionality.
		
			
				
	
	
		
			338 lines
		
	
	
		
			12 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
			
		
		
	
	
			338 lines
		
	
	
		
			12 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
| # 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: [ ]
 |