Files
git.stella-ops.org/etc/authority.yaml.sample
master 1d962ee6fc
Some checks failed
Docs CI / lint-and-preview (push) Has been cancelled
Add OpenSslLegacyShim to ensure OpenSSL 1.1 libraries are accessible on Linux
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.
2025-11-02 21:41:03 +02:00

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: []