Some checks failed
Docs CI / lint-and-preview (push) Has been cancelled
This commit introduces the OpenSslLegacyShim class, which sets the LD_LIBRARY_PATH environment variable to include the directory containing OpenSSL 1.1 native libraries. This is necessary for Mongo2Go to function correctly on Linux platforms that do not ship these libraries by default. The shim checks if the current operating system is Linux and whether the required directory exists before modifying the environment variable.
527 lines
18 KiB
Plaintext
527 lines
18 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"
|
|
jwksCacheLifetime: "00:05:00"
|
|
# 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.
|
|
|
|
notifications:
|
|
ackTokens:
|
|
enabled: true
|
|
payloadType: "application/vnd.stellaops.notify-ack-token+json"
|
|
defaultLifetime: "00:15:00"
|
|
maxLifetime: "00:30:00"
|
|
algorithm: "ES256"
|
|
keySource: "file"
|
|
activeKeyId: "notify-ack-2025-dev"
|
|
keyPath: "../certificates/notify-ack-2025-dev.pem"
|
|
keyUse: "notify-ack"
|
|
jwksCacheLifetime: "00:05:00"
|
|
additionalKeys: []
|
|
webhooks:
|
|
enabled: true
|
|
allowedHosts:
|
|
- "hooks.slack.com"
|
|
- "*.pagerduty.com"
|
|
escalation:
|
|
scope: "notify.escalate"
|
|
requireAdminScope: true
|
|
|
|
apiLifecycle:
|
|
legacyAuth:
|
|
enabled: true
|
|
deprecationDate: "2025-11-01T00:00:00Z"
|
|
sunsetDate: "2026-05-01T00:00:00Z"
|
|
documentationUrl: "https://docs.stella-ops.org/migrations/authority/legacy-auth-endpoints"
|
|
notificationTopic: "authority.api.deprecation"
|
|
|
|
advisoryAi:
|
|
remoteInference:
|
|
enabled: false
|
|
requireTenantConsent: true
|
|
allowedProfiles:
|
|
- "cloud-openai"
|
|
- "sovereign-local"
|
|
|
|
# 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: "airgap-operator"
|
|
displayName: "AirGap Operations CLI"
|
|
grantTypes: [ "client_credentials" ]
|
|
audiences: [ "api://airgap-controller", "api://airgap-importer" ]
|
|
scopes: [ "airgap:status:read", "airgap:import", "airgap:seal" ]
|
|
tenant: "tenant-default"
|
|
senderConstraint: "dpop"
|
|
auth:
|
|
type: "client_secret"
|
|
secretFile: "../secrets/airgap-operator.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", "airgap:status:read", "obs:read", "obs:incident", "timeline:read", "evidence:read", "attest: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: "packs-registry"
|
|
displayName: "Packs Registry Service"
|
|
grantTypes: [ "client_credentials" ]
|
|
audiences: [ "api://packs-registry" ]
|
|
scopes: [ "packs.read", "packs.write" ]
|
|
tenant: "tenant-default"
|
|
senderConstraint: "dpop"
|
|
auth:
|
|
type: "client_secret"
|
|
secretFile: "../secrets/packs-registry.secret"
|
|
- clientId: "task-runner"
|
|
displayName: "Task Runner Service"
|
|
grantTypes: [ "client_credentials" ]
|
|
audiences: [ "api://task-runner" ]
|
|
scopes: [ "packs.run", "packs.read" ]
|
|
tenant: "tenant-default"
|
|
senderConstraint: "dpop"
|
|
auth:
|
|
type: "client_secret"
|
|
secretFile: "../secrets/task-runner.secret"
|
|
- clientId: "pack-approver"
|
|
displayName: "Pack Approver Automation"
|
|
grantTypes: [ "client_credentials" ]
|
|
audiences: [ "api://task-runner" ]
|
|
scopes: [ "packs.approve", "packs.read" ]
|
|
tenant: "tenant-default"
|
|
senderConstraint: "dpop"
|
|
auth:
|
|
type: "client_secret"
|
|
secretFile: "../secrets/pack-approver.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: "notify-service"
|
|
displayName: "Notify WebService"
|
|
grantTypes: [ "client_credentials" ]
|
|
audiences: [ "api://notify" ]
|
|
scopes: [ "notify.viewer", "notify.operator" ]
|
|
tenant: "tenant-default"
|
|
senderConstraint: "dpop"
|
|
auth:
|
|
type: "client_secret"
|
|
secretFile: "../secrets/notify-service.secret"
|
|
- clientId: "notify-admin"
|
|
displayName: "Notify Admin Automation"
|
|
grantTypes: [ "client_credentials" ]
|
|
audiences: [ "api://notify" ]
|
|
scopes: [ "notify.viewer", "notify.operator", "notify.admin" ]
|
|
tenant: "tenant-default"
|
|
senderConstraint: "dpop"
|
|
auth:
|
|
type: "client_secret"
|
|
secretFile: "../secrets/notify-admin.secret"
|
|
- clientId: "observability-web"
|
|
displayName: "Observability Console Backend"
|
|
grantTypes: [ "client_credentials" ]
|
|
audiences: [ "api://observability" ]
|
|
scopes: [ "obs:read", "timeline:read", "evidence:read", "attest:read" ]
|
|
tenant: "tenant-default"
|
|
senderConstraint: "dpop"
|
|
auth:
|
|
type: "client_secret"
|
|
secretFile: "../secrets/observability-web.secret"
|
|
- clientId: "timeline-indexer"
|
|
displayName: "Timeline Indexer Worker"
|
|
grantTypes: [ "client_credentials" ]
|
|
audiences: [ "api://timeline" ]
|
|
scopes: [ "timeline:write", "timeline:read", "obs:read" ]
|
|
tenant: "tenant-default"
|
|
senderConstraint: "dpop"
|
|
auth:
|
|
type: "client_secret"
|
|
secretFile: "../secrets/timeline-indexer.secret"
|
|
- clientId: "evidence-locker"
|
|
displayName: "Evidence Locker Service"
|
|
grantTypes: [ "client_credentials" ]
|
|
audiences: [ "api://evidence" ]
|
|
scopes: [ "evidence:create", "evidence:read", "evidence:hold" ]
|
|
tenant: "tenant-default"
|
|
senderConstraint: "dpop"
|
|
auth:
|
|
type: "client_secret"
|
|
secretFile: "../secrets/evidence-locker.secret"
|
|
- clientId: "incident-bridge"
|
|
displayName: "Incident Bridge Automation"
|
|
grantTypes: [ "client_credentials" ]
|
|
audiences: [ "api://observability" ]
|
|
scopes: [ "obs:incident", "obs:read", "timeline:read", "timeline:write", "evidence:create" ]
|
|
tenant: "tenant-default"
|
|
senderConstraint: "dpop"
|
|
auth:
|
|
type: "client_secret"
|
|
secretFile: "../secrets/incident-bridge.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" ]
|
|
orch-admin:
|
|
scopes: [ "orch:read", "orch:operate", "orch:quota", "orch:backfill" ]
|
|
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" ]
|
|
pack-viewer:
|
|
scopes: [ "packs.read" ]
|
|
pack-operator:
|
|
scopes: [ "packs.read", "packs.run" ]
|
|
pack-publisher:
|
|
scopes: [ "packs.read", "packs.write" ]
|
|
pack-approver:
|
|
scopes: [ "packs.read", "packs.approve" ]
|
|
pack-admin:
|
|
scopes: [ "packs.read", "packs.write", "packs.run", "packs.approve" ]
|
|
export-viewer:
|
|
scopes: [ "export.viewer" ]
|
|
export-operator:
|
|
scopes: [ "export.viewer", "export.operator" ]
|
|
export-admin:
|
|
scopes: [ "export.viewer", "export.operator", "export.admin" ]
|
|
notify-viewer:
|
|
scopes: [ "notify.viewer" ]
|
|
notify-operator:
|
|
scopes: [ "notify.viewer", "notify.operator" ]
|
|
notify-admin:
|
|
scopes: [ "notify.viewer", "notify.operator", "notify.admin" ]
|
|
observability-viewer:
|
|
scopes: [ "obs:read", "timeline:read", "evidence:read", "attest:read" ]
|
|
observability-investigator:
|
|
scopes: [ "obs:read", "timeline:read", "timeline:write", "evidence:read", "evidence:create", "attest:read" ]
|
|
observability-legal:
|
|
scopes: [ "evidence:read", "evidence:hold" ]
|
|
observability-incident-commander:
|
|
scopes: [ "obs:read", "obs:incident", "timeline:read", "timeline:write", "evidence:create", "evidence:read", "attest:read" ]
|
|
airgap-viewer:
|
|
scopes: [ "airgap:status:read" ]
|
|
airgap-operator:
|
|
scopes: [ "airgap:status:read", "airgap:import" ]
|
|
airgap-admin:
|
|
scopes: [ "airgap:status:read", "airgap:import", "airgap:seal" ]
|
|
advisory-ai-viewer:
|
|
scopes: [ "advisory-ai:view" ]
|
|
advisory-ai-operator:
|
|
scopes: [ "advisory-ai:view", "advisory-ai:operate" ]
|
|
advisory-ai-admin:
|
|
scopes: [ "advisory-ai:view", "advisory-ai:operate", "advisory-ai:admin" ]
|
|
advisoryAi:
|
|
remoteInference:
|
|
consentGranted: false
|
|
consentVersion: ""
|
|
consentedAt: ""
|
|
consentedBy: ""
|
|
|
|
# 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: [ ]
|
|
|
|
advisoryAi:
|
|
remoteInference:
|
|
enabled: false
|
|
requireTenantConsent: true
|
|
allowedProfiles: []
|