feat: Implement console session management with tenant and profile handling
- 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.
This commit is contained in:
		| @@ -6,7 +6,7 @@ schemaVersion: 1 | ||||
|  | ||||
| issuer: "https://authority.localtest.me" | ||||
|  | ||||
| accessTokenLifetime: "00:15:00" | ||||
| accessTokenLifetime: "00:02:00" | ||||
| refreshTokenLifetime: "30.00:00:00" | ||||
| identityTokenLifetime: "00:05:00" | ||||
| authorizationCodeLifetime: "00:05:00" | ||||
| @@ -61,6 +61,17 @@ clients: | ||||
|       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: "cartographer-service" | ||||
|     displayName: "Cartographer Service" | ||||
|     grantTypes: [ "client_credentials" ] | ||||
| @@ -84,6 +95,26 @@ clients: | ||||
|     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: "concelier-ingest" | ||||
|     displayName: "Concelier Ingestion" | ||||
| @@ -118,6 +149,30 @@ clients: | ||||
|       type: "client_secret" | ||||
|       secretFile: "../secrets/graph-api-cli.secret" | ||||
|  | ||||
| tenants: | ||||
|   - name: "tenant-default" | ||||
|     roles: | ||||
|       orch-viewer: | ||||
|         scopes: [ "orch:read" ] | ||||
|       orch-operator: | ||||
|         scopes: [ "orch:read", "orch:operate" ] | ||||
|       export-viewer: | ||||
|         scopes: [ "export.viewer" ] | ||||
|       export-operator: | ||||
|         scopes: [ "export.viewer", "export.operator" ] | ||||
|       export-admin: | ||||
|         scopes: [ "export.viewer", "export.operator", "export.admin" ] | ||||
|       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" ] | ||||
|  | ||||
| security: | ||||
|   rateLimiting: | ||||
|     token: | ||||
|   | ||||
| @@ -11,7 +11,7 @@ schemaVersion: 1 | ||||
| issuer: "https://authority.stella-ops.local" | ||||
|  | ||||
| # Token lifetimes expressed as HH:MM:SS or DD.HH:MM:SS. | ||||
| accessTokenLifetime: "00:15:00" | ||||
| accessTokenLifetime: "00:02:00" | ||||
| refreshTokenLifetime: "30.00:00:00" | ||||
| identityTokenLifetime: "00:05:00" | ||||
| authorizationCodeLifetime: "00:05:00" | ||||
| @@ -151,12 +151,39 @@ clients: | ||||
|     displayName: "Policy Automation CLI" | ||||
|     grantTypes: [ "client_credentials" ] | ||||
|     audiences: [ "api://policy-engine" ] | ||||
|     scopes: [ "policy:write", "policy:submit", "policy:run", "findings:read" ] | ||||
|     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" ] | ||||
| @@ -179,6 +206,26 @@ clients: | ||||
|     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" ] | ||||
| @@ -189,6 +236,53 @@ clients: | ||||
|     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. | ||||
|   | ||||
							
								
								
									
										39
									
								
								etc/policy-gateway.yaml.sample
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										39
									
								
								etc/policy-gateway.yaml.sample
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,39 @@ | ||||
| # StellaOps Policy Gateway configuration template. | ||||
| # Copy to ../etc/policy-gateway.yaml (relative to the gateway content root) | ||||
| # and adjust values to fit your environment. Environment variables prefixed with | ||||
| # STELLAOPS_POLICY_GATEWAY_ override these values at runtime. | ||||
|  | ||||
| schemaVersion: 1 | ||||
|  | ||||
| telemetry: | ||||
|   minimumLogLevel: Information | ||||
|  | ||||
| resourceServer: | ||||
|   authority: "https://authority.stella-ops.local" | ||||
|   metadataAddress: "https://authority.stella-ops.local/.well-known/openid-configuration" | ||||
|   audiences: [ "api://policy-gateway" ] | ||||
|   requiredScopes: [ "policy:read", "policy:author", "policy:review", "policy:approve", "policy:operate", "policy:simulate", "policy:run", "policy:activate" ] | ||||
|   requiredTenants: [ ] | ||||
|   bypassNetworks: | ||||
|     - "127.0.0.1/32" | ||||
|     - "::1/128" | ||||
|   requireHttpsMetadata: true | ||||
|   backchannelTimeoutSeconds: 30 | ||||
|   tokenClockSkewSeconds: 60 | ||||
|  | ||||
| policyEngine: | ||||
|   baseAddress: "https://policy-engine.stella-ops.local" | ||||
|   audience: "api://policy-engine" | ||||
|   clientCredentials: | ||||
|     enabled: true | ||||
|     clientId: "policy-gateway" | ||||
|     clientSecret: "change-me" | ||||
|     scopes: [ "policy:read", "policy:author", "policy:review", "policy:approve", "policy:operate", "policy:simulate", "policy:run", "policy:activate" ] | ||||
|     backchannelTimeoutSeconds: 30 | ||||
|   dpop: | ||||
|     enabled: false | ||||
|     keyPath: "../etc/policy-gateway-dpop.pem" | ||||
|     keyPassphrase: "" | ||||
|     algorithm: "ES256" | ||||
|     proofLifetime: "00:02:00" | ||||
|     clockSkew: "00:00:30" | ||||
							
								
								
									
										2
									
								
								etc/secrets/console-web.secret
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										2
									
								
								etc/secrets/console-web.secret
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,2 @@ | ||||
| # replace with a strong shared secret for the console-web client | ||||
| console-web-secret-change-me | ||||
							
								
								
									
										2
									
								
								etc/secrets/policy-cli.secret
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										2
									
								
								etc/secrets/policy-cli.secret
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,2 @@ | ||||
| # generated 2025-10-27T21:55:11Z via scripts/rotate-policy-cli-secret.sh | ||||
| policy-cli-iOHhrE+K1sx+iyWQOd9pqYh0LwbXRauO/zdv0AeFUvLKAtZsc1wTIB5qZ8YIfKEo | ||||
							
								
								
									
										28
									
								
								etc/signals.yaml.sample
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										28
									
								
								etc/signals.yaml.sample
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,28 @@ | ||||
| # Signals service configuration template. | ||||
| # Copy to ../etc/signals.yaml (relative to the Signals content root) | ||||
| # and adjust values to fit your environment. | ||||
|  | ||||
| schemaVersion: 1 | ||||
|  | ||||
| Signals: | ||||
|   Authority: | ||||
|     Enabled: true | ||||
|     Issuer: "https://authority.stella-ops.local" | ||||
|     AllowAnonymousFallback: false | ||||
|     Audiences: | ||||
|       - "api://signals" | ||||
|     RequiredTenants: | ||||
|       - "tenant-default" | ||||
|     RequiredScopes: | ||||
|       - "signals:read" | ||||
|       - "signals:write" | ||||
|       - "signals:admin" | ||||
|     BypassNetworks: | ||||
|       - "127.0.0.1/32" | ||||
|       - "::1/128" | ||||
|   Mongo: | ||||
|     ConnectionString: "mongodb://localhost:27017/signals" | ||||
|     Database: "signals" | ||||
|     CallgraphsCollection: "callgraphs" | ||||
|   Storage: | ||||
|     RootPath: "../data/signals-artifacts" | ||||
		Reference in New Issue
	
	Block a user