CD/CD consolidation

This commit is contained in:
StellaOps Bot
2025-12-26 17:32:23 +02:00
parent a866eb6277
commit c786faae84
638 changed files with 3821 additions and 181 deletions

View File

@@ -0,0 +1,6 @@
apiVersion: v2
name: stellaops
description: Stella Ops core stack (authority, signing, scanner, UI) with infrastructure primitives.
type: application
version: 0.1.0
appVersion: "2025.10.0"

View File

@@ -0,0 +1,64 @@
# StellaOps Helm Install Guide
This guide ships with the `stellaops` chart and provides deterministic install steps for **prod** and **airgap** profiles. All images are pinned by digest from `deploy/releases/<channel>.yaml`.
## Prerequisites
- Helm ≥ 3.14 and kubectl configured for the target cluster.
- Pull secrets for `registry.stella-ops.org` (or your mirrored registry in air-gapped mode).
- TLS/ingress secrets created if you enable ingress in the values files.
## Channels and values
- Prod/stable: `deploy/releases/2025.09-stable.yaml` + `values-prod.yaml`
- Airgap: `deploy/releases/2025.09-airgap.yaml` + `values-airgap.yaml`
- Mirror (optional): `values-mirror.yaml` overlays registry endpoints when using a private mirror.
## Quick install (prod)
```bash
export RELEASE_CHANNEL=2025.09-stable
export NAMESPACE=stellaops
helm upgrade --install stellaops ./deploy/helm/stellaops \
--namespace "$NAMESPACE" --create-namespace \
-f deploy/helm/stellaops/values-prod.yaml \
--set global.release.channel=stable \
--set global.release.version="2025.09.2" \
--set global.release.manifestSha256="dc3c8fe1ab83941c838ccc5a8a5862f7ddfa38c2078e580b5649db26554565b7"
```
## Quick install (airgap)
Assumes images are already loaded into your private registry and `values-airgap.yaml` points to that registry.
```bash
export NAMESPACE=stellaops
helm upgrade --install stellaops ./deploy/helm/stellaops \
--namespace "$NAMESPACE" --create-namespace \
-f deploy/helm/stellaops/values-airgap.yaml \
--set global.release.channel=airgap \
--set global.release.version="2025.09.0-airgap" \
--set global.release.manifestSha256="d422ae3ea01d5f27ea8b5fdc5b19667cb4e3e2c153a35cb761cb53a6ce4f6ba4"
```
## Mirror overlay
If using a mirrored registry, layer the mirror values:
```bash
helm upgrade --install stellaops ./deploy/helm/stellaops \
--namespace "$NAMESPACE" --create-namespace \
-f deploy/helm/stellaops/values-prod.yaml \
-f deploy/helm/stellaops/values-mirror.yaml \
--set global.release.version="2025.09.2" \
--set global.release.manifestSha256="dc3c8fe1ab83941c838ccc5a8a5862f7ddfa38c2078e580b5649db26554565b7"
```
## Validate chart and digests
```bash
deploy/tools/check-channel-alignment.py --manifest deploy/releases/$RELEASE_CHANNEL.yaml \
--values deploy/helm/stellaops/values-prod.yaml
helm lint ./deploy/helm/stellaops
helm template stellaops ./deploy/helm/stellaops -f deploy/helm/stellaops/values-prod.yaml >/tmp/stellaops.yaml
```
## Notes
- Surface.Env and Surface.Secrets defaults are defined in `values*.yaml`; adjust endpoints, cache roots, and providers before promotion.
- Keep `global.release.*` in sync with the chosen release manifest; never deploy with empty version/channel/manifestSha256.
- For offline clusters, run image preload and secret creation before `helm upgrade` to avoid pull failures.

View File

@@ -0,0 +1,16 @@
# Mock Overlay (Dev Only)
Purpose: let deployment tasks progress with placeholder digests until real releases land.
Use:
```bash
helm template mock ./deploy/helm/stellaops -f deploy/helm/stellaops/values-mock.yaml
```
Contents:
- Mock deployments for orchestrator, policy-registry, packs-registry, task-runner, VEX Lens, issuer-directory, findings-ledger, vuln-explorer-api.
- Image pins pulled from `deploy/releases/2025.09-mock-dev.yaml`.
Notes:
- Annotated with `stellaops.dev/mock: "true"` to discourage production use.
- Swap to real values once official digests publish; keep mock overlay gated behind `mock.enabled`.

View File

@@ -0,0 +1,64 @@
receivers:
otlp:
protocols:
grpc:
endpoint: 0.0.0.0:4317
tls:
cert_file: ${STELLAOPS_OTEL_TLS_CERT:?STELLAOPS_OTEL_TLS_CERT not set}
key_file: ${STELLAOPS_OTEL_TLS_KEY:?STELLAOPS_OTEL_TLS_KEY not set}
client_ca_file: ${STELLAOPS_OTEL_TLS_CA:?STELLAOPS_OTEL_TLS_CA not set}
require_client_certificate: ${STELLAOPS_OTEL_REQUIRE_CLIENT_CERT:true}
http:
endpoint: 0.0.0.0:4318
tls:
cert_file: ${STELLAOPS_OTEL_TLS_CERT:?STELLAOPS_OTEL_TLS_CERT not set}
key_file: ${STELLAOPS_OTEL_TLS_KEY:?STELLAOPS_OTEL_TLS_KEY not set}
client_ca_file: ${STELLAOPS_OTEL_TLS_CA:?STELLAOPS_OTEL_TLS_CA not set}
require_client_certificate: ${STELLAOPS_OTEL_REQUIRE_CLIENT_CERT:true}
processors:
attributes/tenant-tag:
actions:
- key: tenant.id
action: insert
value: ${STELLAOPS_TENANT_ID:unknown}
batch:
send_batch_size: 1024
timeout: 5s
exporters:
logging:
verbosity: normal
prometheus:
endpoint: ${STELLAOPS_OTEL_PROMETHEUS_ENDPOINT:0.0.0.0:9464}
enable_open_metrics: true
metric_expiration: 5m
tls:
cert_file: ${STELLAOPS_OTEL_TLS_CERT:?STELLAOPS_OTEL_TLS_CERT not set}
key_file: ${STELLAOPS_OTEL_TLS_KEY:?STELLAOPS_OTEL_TLS_KEY not set}
client_ca_file: ${STELLAOPS_OTEL_TLS_CA:?STELLAOPS_OTEL_TLS_CA not set}
extensions:
health_check:
endpoint: ${STELLAOPS_OTEL_HEALTH_ENDPOINT:0.0.0.0:13133}
pprof:
endpoint: ${STELLAOPS_OTEL_PPROF_ENDPOINT:0.0.0.0:1777}
service:
telemetry:
logs:
level: ${STELLAOPS_OTEL_LOG_LEVEL:info}
extensions: [health_check, pprof]
pipelines:
traces:
receivers: [otlp]
processors: [attributes/tenant-tag, batch]
exporters: [logging]
metrics:
receivers: [otlp]
processors: [attributes/tenant-tag, batch]
exporters: [logging, prometheus]
logs:
receivers: [otlp]
processors: [attributes/tenant-tag, batch]
exporters: [logging]

View File

@@ -0,0 +1,43 @@
{{- define "stellaops.name" -}}
{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" -}}
{{- end -}}
{{- define "stellaops.telemetryCollector.config" -}}
{{- if .Values.telemetry.collector.config }}
{{ tpl .Values.telemetry.collector.config . }}
{{- else }}
{{ tpl (.Files.Get "files/otel-collector-config.yaml") . }}
{{- end }}
{{- end -}}
{{- define "stellaops.telemetryCollector.fullname" -}}
{{- printf "%s-otel-collector" (include "stellaops.name" .) | trunc 63 | trimSuffix "-" -}}
{{- end -}}
{{- define "stellaops.fullname" -}}
{{- $name := default .root.Chart.Name .root.Values.fullnameOverride -}}
{{- printf "%s-%s" $name .name | trunc 63 | trimSuffix "-" -}}
{{- end -}}
{{- define "stellaops.selectorLabels" -}}
app.kubernetes.io/name: {{ include "stellaops.name" .root | quote }}
app.kubernetes.io/instance: {{ .root.Release.Name | quote }}
app.kubernetes.io/component: {{ .name | quote }}
{{- if .svc.class }}
app.kubernetes.io/part-of: {{ printf "stellaops-%s" .svc.class | quote }}
{{- else }}
app.kubernetes.io/part-of: "stellaops-core"
{{- end }}
{{- end -}}
{{- define "stellaops.labels" -}}
{{ include "stellaops.selectorLabels" . }}
helm.sh/chart: {{ printf "%s-%s" .root.Chart.Name .root.Chart.Version | quote }}
app.kubernetes.io/version: {{ .root.Values.global.release.version | quote }}
app.kubernetes.io/managed-by: {{ .root.Release.Service | quote }}
stellaops.release/channel: {{ .root.Values.global.release.channel | quote }}
stellaops.profile: {{ .root.Values.global.profile | quote }}
{{- range $k, $v := .root.Values.global.labels }}
{{ $k }}: {{ $v | quote }}
{{- end }}
{{- end -}}

View File

@@ -0,0 +1,10 @@
apiVersion: v1
kind: ConfigMap
metadata:
name: {{ include "stellaops.fullname" (dict "root" . "name" "release") }}
labels:
{{- include "stellaops.labels" (dict "root" . "name" "release" "svc" (dict "class" "meta")) | nindent 4 }}
data:
version: {{ .Values.global.release.version | quote }}
channel: {{ .Values.global.release.channel | quote }}
manifestSha256: {{ default "" .Values.global.release.manifestSha256 | quote }}

View File

@@ -0,0 +1,15 @@
{{- $root := . -}}
{{- range $name, $cfg := .Values.configMaps }}
apiVersion: v1
kind: ConfigMap
metadata:
name: {{ include "stellaops.fullname" (dict "root" $root "name" $name) }}
labels:
{{- include "stellaops.labels" (dict "root" $root "name" $name "svc" (dict "class" "config")) | nindent 4 }}
data:
{{- range $fileName, $content := $cfg.data }}
{{ $fileName }}: |
{{ tpl $content $root | nindent 4 }}
{{- end }}
---
{{- end }}

View File

@@ -0,0 +1,108 @@
{{- if .Values.console.enabled }}
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ include "stellaops.fullname" . }}-console
labels:
app.kubernetes.io/component: console
{{- include "stellaops.labels" . | nindent 4 }}
spec:
replicas: {{ .Values.console.replicas | default 1 }}
selector:
matchLabels:
app.kubernetes.io/component: console
{{- include "stellaops.selectorLabels" . | nindent 6 }}
template:
metadata:
labels:
app.kubernetes.io/component: console
{{- include "stellaops.selectorLabels" . | nindent 8 }}
spec:
securityContext:
{{- toYaml .Values.console.securityContext | nindent 8 }}
containers:
- name: console
image: {{ .Values.console.image }}
imagePullPolicy: {{ .Values.global.image.pullPolicy | default "IfNotPresent" }}
ports:
- name: http
containerPort: {{ .Values.console.port | default 8080 }}
protocol: TCP
securityContext:
{{- toYaml .Values.console.containerSecurityContext | nindent 12 }}
livenessProbe:
{{- toYaml .Values.console.livenessProbe | nindent 12 }}
readinessProbe:
{{- toYaml .Values.console.readinessProbe | nindent 12 }}
resources:
{{- toYaml .Values.console.resources | nindent 12 }}
volumeMounts:
{{- toYaml .Values.console.volumeMounts | nindent 12 }}
env:
- name: APP_PORT
value: "{{ .Values.console.port | default 8080 }}"
volumes:
{{- toYaml .Values.console.volumes | nindent 8 }}
---
apiVersion: v1
kind: Service
metadata:
name: {{ include "stellaops.fullname" . }}-console
labels:
app.kubernetes.io/component: console
{{- include "stellaops.labels" . | nindent 4 }}
spec:
type: {{ .Values.console.service.type | default "ClusterIP" }}
ports:
- port: {{ .Values.console.service.port | default 80 }}
targetPort: {{ .Values.console.service.targetPort | default 8080 }}
protocol: TCP
name: http
selector:
app.kubernetes.io/component: console
{{- include "stellaops.selectorLabels" . | nindent 4 }}
{{- if .Values.console.ingress.enabled }}
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: {{ include "stellaops.fullname" . }}-console
labels:
app.kubernetes.io/component: console
{{- include "stellaops.labels" . | nindent 4 }}
{{- with .Values.console.ingress.annotations }}
annotations:
{{- toYaml . | nindent 4 }}
{{- end }}
spec:
{{- if .Values.console.ingress.className }}
ingressClassName: {{ .Values.console.ingress.className }}
{{- end }}
{{- if .Values.console.ingress.tls }}
tls:
{{- range .Values.console.ingress.tls }}
- hosts:
{{- range .hosts }}
- {{ . | quote }}
{{- end }}
secretName: {{ .secretName }}
{{- end }}
{{- end }}
rules:
{{- range .Values.console.ingress.hosts }}
- host: {{ .host | quote }}
http:
paths:
{{- range .paths }}
- path: {{ .path }}
pathType: {{ .pathType | default "Prefix" }}
backend:
service:
name: {{ include "stellaops.fullname" $ }}-console
port:
name: http
{{- end }}
{{- end }}
{{- end }}
{{- end }}

View File

@@ -0,0 +1,225 @@
{{- $root := . -}}
{{- $configMaps := default (dict) .Values.configMaps -}}
{{- $hasPolicyActivationConfig := hasKey $configMaps "policy-engine-activation" -}}
{{- $policyActivationConfigName := "" -}}
{{- if $hasPolicyActivationConfig -}}
{{- $policyActivationConfigName = include "stellaops.fullname" (dict "root" $root "name" "policy-engine-activation") -}}
{{- end -}}
{{- $policyActivationTargets := dict "policy-engine" true "policy-gateway" true -}}
{{- range $name, $svc := .Values.services }}
{{- $configMounts := (default (list) $svc.configMounts) }}
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ include "stellaops.fullname" (dict "root" $root "name" $name) }}
labels:
{{- include "stellaops.labels" (dict "root" $root "name" $name "svc" $svc) | nindent 4 }}
spec:
replicas: {{ default 1 $svc.replicas }}
selector:
matchLabels:
{{- include "stellaops.selectorLabels" (dict "root" $root "name" $name "svc" $svc) | nindent 6 }}
template:
metadata:
labels:
{{- include "stellaops.selectorLabels" (dict "root" $root "name" $name "svc" $svc) | nindent 8 }}
{{- if $svc.podAnnotations }}
annotations:
{{ toYaml $svc.podAnnotations | nindent 8 }}
{{- end }}
annotations:
stellaops.release/version: {{ $root.Values.global.release.version | quote }}
stellaops.release/channel: {{ $root.Values.global.release.channel | quote }}
spec:
{{- if $svc.podSecurityContext }}
securityContext:
{{ toYaml $svc.podSecurityContext | nindent 6 }}
{{- end }}
containers:
- name: {{ $name }}
image: {{ $svc.image | quote }}
imagePullPolicy: {{ default $root.Values.global.image.pullPolicy $svc.imagePullPolicy }}
{{- if $svc.securityContext }}
securityContext:
{{ toYaml $svc.securityContext | nindent 12 }}
{{- end }}
{{- if $svc.command }}
command:
{{- range $cmd := $svc.command }}
- {{ $cmd | quote }}
{{- end }}
{{- end }}
{{- if $svc.args }}
args:
{{- range $arg := $svc.args }}
- {{ $arg | quote }}
{{- end }}
{{- end }}
{{- if $svc.env }}
env:
{{- range $envName, $envValue := $svc.env }}
- name: {{ $envName }}
value: {{ $envValue | quote }}
{{- end }}
{{- end }}
{{- $needsPolicyActivation := and $hasPolicyActivationConfig (hasKey $policyActivationTargets $name) }}
{{- $envFrom := default (list) $svc.envFrom }}
{{- if and (hasKey $root.Values.configMaps "surface-env") (or (hasPrefix "scanner-" $name) (hasPrefix "zastava-" $name)) }}
{{- $envFrom = append $envFrom (dict "configMapRef" (dict "name" (include "stellaops.fullname" (dict "root" $root "name" "surface-env")))) }}
{{- end }}
{{- if and $needsPolicyActivation (ne $policyActivationConfigName "") }}
{{- $hasActivationReference := false }}
{{- range $envFromEntry := $envFrom }}
{{- if and (hasKey $envFromEntry "configMapRef") (eq (index (index $envFromEntry "configMapRef") "name") $policyActivationConfigName) }}
{{- $hasActivationReference = true }}
{{- end }}
{{- end }}
{{- if not $hasActivationReference }}
{{- $envFrom = append $envFrom (dict "configMapRef" (dict "name" $policyActivationConfigName)) }}
{{- end }}
{{- end }}
{{- if $envFrom }}
envFrom:
{{ toYaml $envFrom | nindent 12 }}
{{- end }}
{{- if $svc.ports }}
ports:
{{- range $port := $svc.ports }}
- name: {{ default (printf "%s-%v" $name $port.containerPort) $port.name | trunc 63 | trimSuffix "-" }}
containerPort: {{ $port.containerPort }}
protocol: {{ default "TCP" $port.protocol }}
{{- end }}
{{- else if and $svc.service (hasKey $svc.service "port") }}
{{- $svcService := $svc.service }}
ports:
- name: {{ printf "%s-http" $name | trunc 63 | trimSuffix "-" }}
containerPort: {{ default (index $svcService "port") (index $svcService "targetPort") }}
protocol: {{ default "TCP" (index $svcService "protocol") }}
{{- end }}
{{- if $svc.resources }}
resources:
{{ toYaml $svc.resources | nindent 12 }}
{{- end }}
{{- if $svc.securityContext }}
securityContext:
{{ toYaml $svc.securityContext | nindent 12 }}
{{- end }}
{{- if $svc.securityContext }}
securityContext:
{{ toYaml $svc.securityContext | nindent 12 }}
{{- end }}
{{- if $svc.livenessProbe }}
livenessProbe:
{{ toYaml $svc.livenessProbe | nindent 12 }}
{{- end }}
{{- if $svc.readinessProbe }}
readinessProbe:
{{ toYaml $svc.readinessProbe | nindent 12 }}
{{- end }}
{{- if $svc.prometheus }}
{{- $pr := $svc.prometheus }}
{{- if $pr.enabled }}
{{- if not $svc.podAnnotations }}
{{- $svc = merge $svc (dict "podAnnotations" (dict)) }}
{{- end }}
{{- $svc.podAnnotations = merge $svc.podAnnotations (dict "prometheus.io/scrape" "true" "prometheus.io/path" (default "/metrics" $pr.path) "prometheus.io/port" (toString (default 8080 $pr.port)) "prometheus.io/scheme" (default "http" $pr.scheme))) }}
{{- end }}
{{- end }}
{{- if or $svc.volumeMounts $configMounts }}
volumeMounts:
{{- if $svc.volumeMounts }}
{{ toYaml $svc.volumeMounts | nindent 12 }}
{{- end }}
{{- range $mount := $configMounts }}
- name: {{ $mount.name }}
mountPath: {{ $mount.mountPath }}
{{- if $mount.subPath }}
subPath: {{ $mount.subPath }}
{{- end }}
{{- if hasKey $mount "readOnly" }}
readOnly: {{ $mount.readOnly }}
{{- else }}
readOnly: true
{{- end }}
{{- end }}
{{- end }}
{{- if or $svc.volumes (or $svc.volumeClaims $configMounts) }}
volumes:
{{- if $svc.volumes }}
{{ toYaml $svc.volumes | nindent 8 }}
{{- end }}
{{- if $svc.volumeClaims }}
{{- range $claim := $svc.volumeClaims }}
- name: {{ $claim.name }}
persistentVolumeClaim:
claimName: {{ $claim.claimName }}
{{- end }}
{{- end }}
{{- range $mount := $configMounts }}
- name: {{ $mount.name }}
configMap:
name: {{ include "stellaops.fullname" (dict "root" $root "name" $mount.configMap) }}
{{- if $mount.items }}
items:
{{ toYaml $mount.items | nindent 12 }}
{{- else if $mount.subPath }}
items:
- key: {{ $mount.subPath }}
path: {{ $mount.subPath }}
{{- end }}
{{- end }}
{{- end }}
{{- if $svc.serviceAccount }}
serviceAccountName: {{ $svc.serviceAccount | quote }}
{{- end }}
{{- if $svc.nodeSelector }}
nodeSelector:
{{ toYaml $svc.nodeSelector | nindent 8 }}
{{- end }}
{{- if $svc.affinity }}
affinity:
{{ toYaml $svc.affinity | nindent 8 }}
{{- end }}
{{- if $svc.tolerations }}
tolerations:
{{ toYaml $svc.tolerations | nindent 8 }}
{{- end }}
{{- if $svc.pdb }}
---
apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
name: {{ include "stellaops.fullname" (dict "root" $root "name" $name) }}
labels:
{{- include "stellaops.labels" (dict "root" $root "name" $name "svc" $svc) | nindent 4 }}
spec:
{{- if $svc.pdb.minAvailable }}
minAvailable: {{ $svc.pdb.minAvailable }}
{{- end }}
{{- if $svc.pdb.maxUnavailable }}
maxUnavailable: {{ $svc.pdb.maxUnavailable }}
{{- end }}
selector:
matchLabels:
{{- include "stellaops.selectorLabels" (dict "root" $root "name" $name "svc" $svc) | nindent 6 }}
{{- end }}
---
{{- if $svc.service }}
apiVersion: v1
kind: Service
metadata:
name: {{ include "stellaops.fullname" (dict "root" $root "name" $name) }}
labels:
{{- include "stellaops.labels" (dict "root" $root "name" $name "svc" $svc) | nindent 4 }}
spec:
type: {{ default "ClusterIP" $svc.service.type }}
selector:
{{- include "stellaops.selectorLabels" (dict "root" $root "name" $name "svc" $svc) | nindent 4 }}
ports:
- name: {{ default "http" $svc.service.portName }}
port: {{ $svc.service.port }}
targetPort: {{ $svc.service.targetPort | default $svc.service.port }}
protocol: {{ default "TCP" $svc.service.protocol }}
---
{{- end }}
{{- end }}

View File

@@ -0,0 +1,28 @@
{{- if and .Values.externalSecrets.enabled .Values.externalSecrets.secrets }}
{{- range $secret := .Values.externalSecrets.secrets }}
apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata:
name: {{ include "stellaops.fullname" $ }}-{{ $secret.name }}
labels:
{{- include "stellaops.labels" $ | nindent 4 }}
spec:
refreshInterval: {{ default "1h" $secret.refreshInterval }}
secretStoreRef:
name: {{ $secret.storeRef.name }}
kind: {{ default "ClusterSecretStore" $secret.storeRef.kind }}
target:
name: {{ $secret.target.name | default (printf "%s-%s" (include "stellaops.fullname" $) $secret.name) }}
creationPolicy: {{ default "Owner" $secret.target.creationPolicy }}
data:
{{- range $secret.data }}
- secretKey: {{ .key }}
remoteRef:
key: {{ .remoteKey }}
{{- if .property }}
property: {{ .property }}
{{- end }}
{{- end }}
---
{{- end }}
{{- end }}

View File

@@ -0,0 +1,39 @@
{{- if and .Values.hpa.enabled .Values.services }}
{{- range $name, $svc := .Values.services }}
{{- if and $svc.hpa $svc.hpa.enabled }}
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: {{ include "stellaops.fullname" (dict "root" $ "name" $name) }}
labels:
{{- include "stellaops.labels" (dict "root" $ "name" $name "svc" $svc) | nindent 4 }}
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: {{ include "stellaops.fullname" (dict "root" $ "name" $name) }}
minReplicas: {{ default $.Values.hpa.minReplicas $svc.hpa.minReplicas }}
maxReplicas: {{ default $.Values.hpa.maxReplicas $svc.hpa.maxReplicas }}
metrics:
{{- $cpu := coalesce $svc.hpa.cpu.targetPercentage $.Values.hpa.cpu.targetPercentage -}}
{{- if $cpu }}
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: {{ $cpu }}
{{- end }}
{{- $mem := coalesce $svc.hpa.memory.targetPercentage $.Values.hpa.memory.targetPercentage -}}
{{- if $mem }}
- type: Resource
resource:
name: memory
target:
type: Utilization
averageUtilization: {{ $mem }}
{{- end }}
---
{{- end }}
{{- end }}
{{- end }}

View File

@@ -0,0 +1,32 @@
{{- if and .Values.ingress.enabled .Values.ingress.hosts }}
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: {{ include "stellaops.fullname" . }}
labels:
{{- include "stellaops.labels" . | nindent 4 }}
annotations:
{{- range $k, $v := .Values.ingress.annotations }}
{{ $k }}: {{ $v | quote }}
{{- end }}
spec:
ingressClassName: {{ .Values.ingress.className | default "nginx" | quote }}
tls:
{{- range .Values.ingress.tls }}
- hosts: {{ toYaml .hosts | nindent 6 }}
secretName: {{ .secretName }}
{{- end }}
rules:
{{- range .Values.ingress.hosts }}
- host: {{ .host }}
http:
paths:
- path: {{ .path | default "/" }}
pathType: Prefix
backend:
service:
name: {{ include "stellaops.fullname" $ }}-gateway
port:
number: {{ .servicePort | default 80 }}
{{- end }}
{{- end }}

View File

@@ -0,0 +1,50 @@
{{- if and .Values.migrations.enabled .Values.migrations.jobs }}
{{- range $job := .Values.migrations.jobs }}
apiVersion: batch/v1
kind: Job
metadata:
name: {{ include "stellaops.fullname" $ }}-migration-{{ $job.name | trunc 30 | trimSuffix "-" }}
labels:
{{- include "stellaops.labels" $ | nindent 4 }}
stellaops.io/component: migration
stellaops.io/migration-name: {{ $job.name | quote }}
spec:
backoffLimit: {{ default 3 $job.backoffLimit }}
ttlSecondsAfterFinished: {{ default 3600 $job.ttlSecondsAfterFinished }}
template:
metadata:
labels:
{{- include "stellaops.selectorLabels" $ | nindent 8 }}
stellaops.io/component: migration
stellaops.io/migration-name: {{ $job.name | quote }}
spec:
restartPolicy: {{ default "Never" $job.restartPolicy }}
serviceAccountName: {{ default "default" $job.serviceAccountName }}
containers:
- name: {{ $job.name | trunc 50 | trimSuffix "-" }}
image: {{ $job.image | quote }}
imagePullPolicy: {{ default "IfNotPresent" $job.imagePullPolicy }}
command: {{- if $job.command }} {{ toJson $job.command }} {{- else }} null {{- end }}
args: {{- if $job.args }} {{ toJson $job.args }} {{- else }} null {{- end }}
env:
{{- if $job.env }}
{{- range $k, $v := $job.env }}
- name: {{ $k }}
value: {{ $v | quote }}
{{- end }}
{{- end }}
envFrom:
{{- if $job.envFrom }}
{{- toYaml $job.envFrom | nindent 12 }}
{{- end }}
resources:
{{- if $job.resources }}
{{- toYaml $job.resources | nindent 12 }}
{{- else }}{}
{{- end }}
imagePullSecrets:
{{- if $.Values.global.image.pullSecrets }}
{{- toYaml $.Values.global.image.pullSecrets | nindent 8 }}
{{- end }}
{{- end }}
{{- end }}

View File

@@ -0,0 +1,45 @@
{{- if .Values.networkPolicy.enabled }}
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: {{ include "stellaops.fullname" . }}-default
labels:
{{- include "stellaops.labels" . | nindent 4 }}
spec:
podSelector:
matchLabels:
{{- include "stellaops.selectorLabelsRoot" . | nindent 6 }}
policyTypes:
- Ingress
- Egress
ingress:
- from:
{{- if .Values.networkPolicy.ingressNamespaces }}
- namespaceSelector:
matchLabels:
{{- toYaml .Values.networkPolicy.ingressNamespaces | nindent 14 }}
{{- end }}
{{- if .Values.networkPolicy.ingressPods }}
- podSelector:
matchLabels:
{{- toYaml .Values.networkPolicy.ingressPods | nindent 14 }}
{{- end }}
ports:
- protocol: TCP
port: {{ default 80 .Values.networkPolicy.ingressPort }}
egress:
- to:
{{- if .Values.networkPolicy.egressNamespaces }}
- namespaceSelector:
matchLabels:
{{- toYaml .Values.networkPolicy.egressNamespaces | nindent 14 }}
{{- end }}
{{- if .Values.networkPolicy.egressPods }}
- podSelector:
matchLabels:
{{- toYaml .Values.networkPolicy.egressPods | nindent 14 }}
{{- end }}
ports:
- protocol: TCP
port: {{ default 443 .Values.networkPolicy.egressPort }}
{{- end }}

View File

@@ -0,0 +1,22 @@
{{- if .Values.mock.enabled }}
apiVersion: apps/v1
kind: Deployment
metadata:
name: orchestrator-mock
annotations:
stellaops.dev/mock: "true"
spec:
replicas: 1
selector:
matchLabels:
app: orchestrator-mock
template:
metadata:
labels:
app: orchestrator-mock
spec:
containers:
- name: orchestrator
image: "{{ .Values.mock.orchestrator.image }}"
args: ["dotnet", "StellaOps.Orchestrator.WebService.dll"]
{{- end }}

View File

@@ -0,0 +1,121 @@
{{- if .Values.telemetry.collector.enabled }}
apiVersion: v1
kind: ConfigMap
metadata:
name: {{ include "stellaops.telemetryCollector.fullname" . }}
labels:
{{- include "stellaops.labels" (dict "root" . "name" "otel-collector" "svc" (dict "class" "telemetry")) | nindent 4 }}
data:
config.yaml: |
{{ include "stellaops.telemetryCollector.config" . | indent 4 }}
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ include "stellaops.telemetryCollector.fullname" . }}
labels:
{{- include "stellaops.labels" (dict "root" . "name" "otel-collector" "svc" (dict "class" "telemetry")) | nindent 4 }}
spec:
replicas: {{ .Values.telemetry.collector.replicas | default 1 }}
selector:
matchLabels:
app.kubernetes.io/name: {{ include "stellaops.name" . | quote }}
app.kubernetes.io/component: "otel-collector"
template:
metadata:
labels:
app.kubernetes.io/name: {{ include "stellaops.name" . | quote }}
app.kubernetes.io/component: "otel-collector"
stellaops.profile: {{ .Values.global.profile | quote }}
spec:
containers:
- name: otel-collector
image: {{ .Values.telemetry.collector.image | default "otel/opentelemetry-collector:0.105.0" | quote }}
args:
- "--config=/etc/otel/config.yaml"
ports:
- name: otlp-grpc
containerPort: 4317
- name: otlp-http
containerPort: 4318
- name: metrics
containerPort: 9464
- name: health
containerPort: 13133
- name: pprof
containerPort: 1777
env:
- name: STELLAOPS_OTEL_TLS_CERT
value: {{ .Values.telemetry.collector.tls.certPath | default "/etc/otel/tls/tls.crt" | quote }}
- name: STELLAOPS_OTEL_TLS_KEY
value: {{ .Values.telemetry.collector.tls.keyPath | default "/etc/otel/tls/tls.key" | quote }}
- name: STELLAOPS_OTEL_TLS_CA
value: {{ .Values.telemetry.collector.tls.caPath | default "/etc/otel/tls/ca.crt" | quote }}
- name: STELLAOPS_OTEL_PROMETHEUS_ENDPOINT
value: {{ .Values.telemetry.collector.prometheusEndpoint | default "0.0.0.0:9464" | quote }}
- name: STELLAOPS_OTEL_REQUIRE_CLIENT_CERT
value: {{ .Values.telemetry.collector.requireClientCert | default true | quote }}
- name: STELLAOPS_TENANT_ID
value: {{ .Values.telemetry.collector.defaultTenant | default "unknown" | quote }}
- name: STELLAOPS_OTEL_LOG_LEVEL
value: {{ .Values.telemetry.collector.logLevel | default "info" | quote }}
volumeMounts:
- name: config
mountPath: /etc/otel/config.yaml
subPath: config.yaml
readOnly: true
- name: tls
mountPath: /etc/otel/tls
readOnly: true
livenessProbe:
httpGet:
scheme: HTTPS
port: health
path: /healthz
initialDelaySeconds: 10
periodSeconds: 30
readinessProbe:
httpGet:
scheme: HTTPS
port: health
path: /healthz
initialDelaySeconds: 5
periodSeconds: 15
{{- with .Values.telemetry.collector.resources }}
resources:
{{ toYaml . | indent 12 }}
{{- end }}
volumes:
- name: config
configMap:
name: {{ include "stellaops.telemetryCollector.fullname" . }}
- name: tls
secret:
secretName: {{ .Values.telemetry.collector.tls.secretName | required "telemetry.collector.tls.secretName is required" }}
{{- if .Values.telemetry.collector.tls.items }}
items:
{{ toYaml .Values.telemetry.collector.tls.items | indent 14 }}
{{- end }}
---
apiVersion: v1
kind: Service
metadata:
name: {{ include "stellaops.telemetryCollector.fullname" . }}
labels:
{{- include "stellaops.labels" (dict "root" . "name" "otel-collector" "svc" (dict "class" "telemetry")) | nindent 4 }}
spec:
type: ClusterIP
selector:
app.kubernetes.io/name: {{ include "stellaops.name" . | quote }}
app.kubernetes.io/component: "otel-collector"
ports:
- name: otlp-grpc
port: {{ .Values.telemetry.collector.service.grpcPort | default 4317 }}
targetPort: otlp-grpc
- name: otlp-http
port: {{ .Values.telemetry.collector.service.httpPort | default 4318 }}
targetPort: otlp-http
- name: metrics
port: {{ .Values.telemetry.collector.service.metricsPort | default 9464 }}
targetPort: metrics
{{- end }}

View File

@@ -0,0 +1,44 @@
{{- if .Values.mock.enabled }}
apiVersion: apps/v1
kind: Deployment
metadata:
name: packs-registry-mock
annotations:
stellaops.dev/mock: "true"
spec:
replicas: 1
selector:
matchLabels:
app: packs-registry-mock
template:
metadata:
labels:
app: packs-registry-mock
spec:
containers:
- name: packs-registry
image: "{{ .Values.mock.packsRegistry.image }}"
args: ["dotnet", "StellaOps.PacksRegistry.dll"]
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: task-runner-mock
annotations:
stellaops.dev/mock: "true"
spec:
replicas: 1
selector:
matchLabels:
app: task-runner-mock
template:
metadata:
labels:
app: task-runner-mock
spec:
containers:
- name: task-runner
image: "{{ .Values.mock.taskRunner.image }}"
args: ["dotnet", "StellaOps.TaskRunner.WebService.dll"]
{{- end }}

View File

@@ -0,0 +1,22 @@
{{- if .Values.mock.enabled }}
apiVersion: apps/v1
kind: Deployment
metadata:
name: policy-registry-mock
annotations:
stellaops.dev/mock: "true"
spec:
replicas: 1
selector:
matchLabels:
app: policy-registry-mock
template:
metadata:
labels:
app: policy-registry-mock
spec:
containers:
- name: policy-registry
image: "{{ .Values.mock.policyRegistry.image }}"
args: ["dotnet", "StellaOps.Policy.Engine.dll"]
{{- end }}

View File

@@ -0,0 +1,22 @@
{{- if .Values.mock.enabled }}
apiVersion: apps/v1
kind: Deployment
metadata:
name: vex-lens-mock
annotations:
stellaops.dev/mock: "true"
spec:
replicas: 1
selector:
matchLabels:
app: vex-lens-mock
template:
metadata:
labels:
app: vex-lens-mock
spec:
containers:
- name: vex-lens
image: "{{ .Values.mock.vexLens.image }}"
args: ["dotnet", "StellaOps.VexLens.dll"]
{{- end }}

View File

@@ -0,0 +1,44 @@
{{- if .Values.mock.enabled }}
apiVersion: apps/v1
kind: Deployment
metadata:
name: findings-ledger-mock
annotations:
stellaops.dev/mock: "true"
spec:
replicas: 1
selector:
matchLabels:
app: findings-ledger-mock
template:
metadata:
labels:
app: findings-ledger-mock
spec:
containers:
- name: findings-ledger
image: "{{ .Values.mock.findingsLedger.image }}"
args: ["dotnet", "StellaOps.Findings.Ledger.WebService.dll"]
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: vuln-explorer-api-mock
annotations:
stellaops.dev/mock: "true"
spec:
replicas: 1
selector:
matchLabels:
app: vuln-explorer-api-mock
template:
metadata:
labels:
app: vuln-explorer-api-mock
spec:
containers:
- name: vuln-explorer-api
image: "{{ .Values.mock.vulnExplorerApi.image }}"
args: ["dotnet", "StellaOps.VulnExplorer.Api.dll"]
{{- end }}

View File

@@ -0,0 +1,314 @@
global:
profile: airgap
release:
version: "2025.09.2-airgap"
channel: airgap
manifestSha256: "b787b833dddd73960c31338279daa0b0a0dce2ef32bd32ef1aaf953d66135f94"
image:
pullPolicy: IfNotPresent
labels:
stellaops.io/channel: airgap
migrations:
enabled: false
jobs: []
networkPolicy:
enabled: true
ingressPort: 8443
egressPort: 443
ingressNamespaces:
kubernetes.io/metadata.name: stellaops
egressNamespaces:
kubernetes.io/metadata.name: stellaops
ingress:
enabled: false
className: nginx
annotations: {}
hosts: []
tls: []
externalSecrets:
enabled: false
secrets: []
prometheus:
enabled: true
path: /metrics
port: 8080
scheme: http
hpa:
enabled: false
minReplicas: 1
maxReplicas: 3
cpu:
targetPercentage: 70
memory:
targetPercentage: 80
configMaps:
notify-config:
data:
notify.yaml: |
storage:
driver: mongo
connectionString: "mongodb://notify-mongo.prod.svc.cluster.local:27017"
database: "stellaops_notify"
commandTimeoutSeconds: 60
authority:
enabled: true
issuer: "https://authority.stella-ops.org"
metadataAddress: "https://authority.stella-ops.org/.well-known/openid-configuration"
requireHttpsMetadata: true
allowAnonymousFallback: false
backchannelTimeoutSeconds: 30
tokenClockSkewSeconds: 60
audiences:
- notify
readScope: notify.read
adminScope: notify.admin
api:
basePath: "/api/v1/notify"
internalBasePath: "/internal/notify"
tenantHeader: "X-StellaOps-Tenant"
plugins:
baseDirectory: "/var/opt/stellaops"
directory: "plugins/notify"
searchPatterns:
- "StellaOps.Notify.Connectors.*.dll"
orderedPlugins:
- StellaOps.Notify.Connectors.Slack
- StellaOps.Notify.Connectors.Teams
- StellaOps.Notify.Connectors.Email
- StellaOps.Notify.Connectors.Webhook
telemetry:
enableRequestLogging: true
minimumLogLevel: Warning
policy-engine-activation:
data:
STELLAOPS_POLICY_ENGINE__ACTIVATION__FORCETWOPERSONAPPROVAL: "true"
STELLAOPS_POLICY_ENGINE__ACTIVATION__DEFAULTREQUIRESTWOPERSONAPPROVAL: "true"
STELLAOPS_POLICY_ENGINE__ACTIVATION__EMITAUDITLOGS: "true"
services:
authority:
image: registry.stella-ops.org/stellaops/authority@sha256:5551a3269b7008cd5aceecf45df018c67459ed519557ccbe48b093b926a39bcc
service:
port: 8440
env:
STELLAOPS_AUTHORITY__ISSUER: "https://stellaops-authority:8440"
STELLAOPS_AUTHORITY__MONGO__CONNECTIONSTRING: "mongodb://stellaops-airgap:stellaops-airgap@stellaops-mongo:27017"
STELLAOPS_AUTHORITY__ALLOWANONYMOUSFALLBACK: "false"
signer:
image: registry.stella-ops.org/stellaops/signer@sha256:ddbbd664a42846cea6b40fca6465bc679b30f72851158f300d01a8571c5478fc
service:
port: 8441
env:
SIGNER__AUTHORITY__BASEURL: "https://stellaops-authority:8440"
SIGNER__POE__INTROSPECTURL: "file:///offline/poe/introspect.json"
SIGNER__STORAGE__MONGO__CONNECTIONSTRING: "mongodb://stellaops-airgap:stellaops-airgap@stellaops-mongo:27017"
attestor:
image: registry.stella-ops.org/stellaops/attestor@sha256:1ff0a3124d66d3a2702d8e421df40fbd98cc75cb605d95510598ebbae1433c50
service:
port: 8442
env:
ATTESTOR__SIGNER__BASEURL: "https://stellaops-signer:8441"
ATTESTOR__MONGO__CONNECTIONSTRING: "mongodb://stellaops-airgap:stellaops-airgap@stellaops-mongo:27017"
concelier:
image: registry.stella-ops.org/stellaops/concelier@sha256:29e2e1a0972707e092cbd3d370701341f9fec2aa9316fb5d8100480f2a1c76b5
service:
port: 8445
env:
CONCELIER__STORAGE__MONGO__CONNECTIONSTRING: "mongodb://stellaops-airgap:stellaops-airgap@stellaops-mongo:27017"
CONCELIER__STORAGE__S3__ENDPOINT: "http://stellaops-minio:9000"
CONCELIER__STORAGE__S3__ACCESSKEYID: "stellaops-airgap"
CONCELIER__STORAGE__S3__SECRETACCESSKEY: "airgap-minio-secret"
CONCELIER__AUTHORITY__BASEURL: "https://stellaops-authority:8440"
CONCELIER__AUTHORITY__RESILIENCE__ALLOWOFFLINECACHEFALLBACK: "true"
CONCELIER__AUTHORITY__RESILIENCE__OFFLINECACHETOLERANCE: "00:45:00"
volumeMounts:
- name: concelier-jobs
mountPath: /var/lib/concelier/jobs
volumeClaims:
- name: concelier-jobs
claimName: stellaops-concelier-jobs
scanner-web:
image: registry.stella-ops.org/stellaops/scanner-web@sha256:3df8ca21878126758203c1a0444e39fd97f77ddacf04a69685cda9f1e5e94718
service:
port: 8444
env:
SCANNER__STORAGE__MONGO__CONNECTIONSTRING: "mongodb://stellaops-airgap:stellaops-airgap@stellaops-mongo:27017"
SCANNER__ARTIFACTSTORE__DRIVER: "rustfs"
SCANNER__ARTIFACTSTORE__ENDPOINT: "http://stellaops-rustfs:8080/api/v1"
SCANNER__ARTIFACTSTORE__BUCKET: "scanner-artifacts"
SCANNER__ARTIFACTSTORE__TIMEOUTSECONDS: "30"
SCANNER__QUEUE__BROKER: "nats://stellaops-nats:4222"
SCANNER__EVENTS__ENABLED: "false"
SCANNER__EVENTS__DRIVER: "redis"
SCANNER__EVENTS__DSN: ""
SCANNER__EVENTS__STREAM: "stella.events"
SCANNER__EVENTS__PUBLISHTIMEOUTSECONDS: "5"
SCANNER__EVENTS__MAXSTREAMLENGTH: "10000"
SCANNER__OFFLINEKIT__ENABLED: "false"
SCANNER__OFFLINEKIT__REQUIREDSSE: "true"
SCANNER__OFFLINEKIT__REKOROFFLINEMODE: "true"
SCANNER__OFFLINEKIT__TRUSTROOTDIRECTORY: "/etc/stellaops/trust-roots"
SCANNER__OFFLINEKIT__REKORSNAPSHOTDIRECTORY: "/var/lib/stellaops/rekor-snapshot"
SCANNER_SURFACE_FS_ENDPOINT: "http://stellaops-rustfs:8080/api/v1"
SCANNER_SURFACE_CACHE_ROOT: "/var/lib/stellaops/surface"
SCANNER_SURFACE_SECRETS_PROVIDER: "file"
SCANNER_SURFACE_SECRETS_ROOT: "/etc/stellaops/secrets"
scanner-worker:
image: registry.stella-ops.org/stellaops/scanner-worker@sha256:eea5d6cfe7835950c5ec7a735a651f2f0d727d3e470cf9027a4a402ea89c4fb5
env:
SCANNER__STORAGE__MONGO__CONNECTIONSTRING: "mongodb://stellaops-airgap:stellaops-airgap@stellaops-mongo:27017"
SCANNER__ARTIFACTSTORE__DRIVER: "rustfs"
SCANNER__ARTIFACTSTORE__ENDPOINT: "http://stellaops-rustfs:8080/api/v1"
SCANNER__ARTIFACTSTORE__BUCKET: "scanner-artifacts"
SCANNER__ARTIFACTSTORE__TIMEOUTSECONDS: "30"
SCANNER__QUEUE__BROKER: "nats://stellaops-nats:4222"
SCANNER__EVENTS__ENABLED: "false"
SCANNER__EVENTS__DRIVER: "redis"
SCANNER__EVENTS__DSN: ""
SCANNER__EVENTS__STREAM: "stella.events"
SCANNER__EVENTS__PUBLISHTIMEOUTSECONDS: "5"
SCANNER__EVENTS__MAXSTREAMLENGTH: "10000"
SCANNER_SURFACE_FS_ENDPOINT: "http://stellaops-rustfs:8080/api/v1"
SCANNER_SURFACE_CACHE_ROOT: "/var/lib/stellaops/surface"
SCANNER_SURFACE_SECRETS_PROVIDER: "file"
SCANNER_SURFACE_SECRETS_ROOT: "/etc/stellaops/secrets"
notify-web:
image: registry.stella-ops.org/stellaops/notify-web:2025.09.2
service:
port: 8446
env:
DOTNET_ENVIRONMENT: Production
configMounts:
- name: notify-config
mountPath: /app/etc/notify.yaml
subPath: notify.yaml
configMap: notify-config
excititor:
image: registry.stella-ops.org/stellaops/excititor@sha256:65c0ee13f773efe920d7181512349a09d363ab3f3e177d276136bd2742325a68
env:
EXCITITOR__CONCELIER__BASEURL: "https://stellaops-concelier:8445"
EXCITITOR__STORAGE__MONGO__CONNECTIONSTRING: "mongodb://stellaops-airgap:stellaops-airgap@stellaops-mongo:27017"
advisory-ai-web:
image: registry.stella-ops.org/stellaops/advisory-ai-web:2025.09.2-airgap
service:
port: 8448
env:
ADVISORYAI__AdvisoryAI__SbomBaseAddress: https://stellaops-scanner-web:8444
ADVISORYAI__AdvisoryAI__Queue__DirectoryPath: /var/lib/advisory-ai/queue
ADVISORYAI__AdvisoryAI__Storage__PlanCacheDirectory: /var/lib/advisory-ai/plans
ADVISORYAI__AdvisoryAI__Storage__OutputDirectory: /var/lib/advisory-ai/outputs
ADVISORYAI__AdvisoryAI__Inference__Mode: Local
ADVISORYAI__AdvisoryAI__Inference__Remote__BaseAddress: ""
ADVISORYAI__AdvisoryAI__Inference__Remote__ApiKey: ""
volumeMounts:
- name: advisory-ai-data
mountPath: /var/lib/advisory-ai
volumeClaims:
- name: advisory-ai-data
claimName: stellaops-advisory-ai-data
advisory-ai-worker:
image: registry.stella-ops.org/stellaops/advisory-ai-worker:2025.09.2-airgap
env:
ADVISORYAI__AdvisoryAI__SbomBaseAddress: https://stellaops-scanner-web:8444
ADVISORYAI__AdvisoryAI__Queue__DirectoryPath: /var/lib/advisory-ai/queue
ADVISORYAI__AdvisoryAI__Storage__PlanCacheDirectory: /var/lib/advisory-ai/plans
ADVISORYAI__AdvisoryAI__Storage__OutputDirectory: /var/lib/advisory-ai/outputs
ADVISORYAI__AdvisoryAI__Inference__Mode: Local
ADVISORYAI__AdvisoryAI__Inference__Remote__BaseAddress: ""
ADVISORYAI__AdvisoryAI__Inference__Remote__ApiKey: ""
volumeMounts:
- name: advisory-ai-data
mountPath: /var/lib/advisory-ai
volumeClaims:
- name: advisory-ai-data
claimName: stellaops-advisory-ai-data
web-ui:
image: registry.stella-ops.org/stellaops/web-ui@sha256:bee9668011ff414572131dc777faab4da24473fe12c230893f161cabee092a1d
service:
port: 9443
targetPort: 8443
env:
STELLAOPS_UI__BACKEND__BASEURL: "https://stellaops-scanner-web:8444"
mongo:
class: infrastructure
image: docker.io/library/mongo@sha256:c258b26dbb7774f97f52aff52231ca5f228273a84329c5f5e451c3739457db49
service:
port: 27017
command:
- mongod
- --bind_ip_all
env:
MONGO_INITDB_ROOT_USERNAME: stellaops-airgap
MONGO_INITDB_ROOT_PASSWORD: stellaops-airgap
volumeMounts:
- name: mongo-data
mountPath: /data/db
volumeClaims:
- name: mongo-data
claimName: stellaops-mongo-data
minio:
class: infrastructure
image: docker.io/minio/minio@sha256:14cea493d9a34af32f524e538b8346cf79f3321eff8e708c1e2960462bd8936e
service:
port: 9000
command:
- server
- /data
- --console-address
- :9001
env:
MINIO_ROOT_USER: stellaops-airgap
MINIO_ROOT_PASSWORD: airgap-minio-secret
volumeMounts:
- name: minio-data
mountPath: /data
volumeClaims:
- name: minio-data
claimName: stellaops-minio-data
rustfs:
class: infrastructure
image: registry.stella-ops.org/stellaops/rustfs:2025.10.0-edge
service:
port: 8080
command:
- serve
- --listen
- 0.0.0.0:8080
- --root
- /data
env:
RUSTFS__LOG__LEVEL: info
RUSTFS__STORAGE__PATH: /data
volumeMounts:
- name: rustfs-data
mountPath: /data
volumeClaims:
- name: rustfs-data
claimName: stellaops-rustfs-data
nats:
class: infrastructure
image: docker.io/library/nats@sha256:c82559e4476289481a8a5196e675ebfe67eea81d95e5161e3e78eccfe766608e
service:
port: 4222
command:
- -js
- -sd
- /data
volumeMounts:
- name: nats-data
mountPath: /data
volumeClaims:
- name: nats-data
claimName: stellaops-nats-data

View File

@@ -0,0 +1,84 @@
# Console (Angular SPA) values overlay
# Use: helm install stellaops . -f values-console.yaml
console:
enabled: true
image: registry.stella-ops.org/stellaops/console:2025.10.0-edge
replicas: 1
port: 8080
# Backend API URL injected via config.json at startup
apiBaseUrl: ""
# Authority URL for OAuth/OIDC
authorityUrl: ""
# Tenant header name
tenantHeader: "X-StellaOps-Tenant"
# Resource limits (nginx is lightweight)
resources:
limits:
cpu: "200m"
memory: "128Mi"
requests:
cpu: "50m"
memory: "64Mi"
# Service configuration
service:
type: ClusterIP
port: 80
targetPort: 8080
# Ingress configuration (enable for external access)
ingress:
enabled: false
className: nginx
annotations:
nginx.ingress.kubernetes.io/proxy-body-size: "10m"
hosts:
- host: console.local
paths:
- path: /
pathType: Prefix
tls: []
# Health probes
livenessProbe:
httpGet:
path: /
port: 8080
initialDelaySeconds: 10
periodSeconds: 30
readinessProbe:
httpGet:
path: /
port: 8080
initialDelaySeconds: 5
periodSeconds: 10
# Pod security context (non-root per DOCKER-44-001)
securityContext:
runAsNonRoot: true
runAsUser: 101
runAsGroup: 101
fsGroup: 101
# Container security context
containerSecurityContext:
allowPrivilegeEscalation: false
readOnlyRootFilesystem: true
capabilities:
drop:
- ALL
# Volume mounts for nginx temp directories (RO rootfs)
volumeMounts:
- name: nginx-cache
mountPath: /var/cache/nginx
- name: nginx-run
mountPath: /var/run
volumes:
- name: nginx-cache
emptyDir: {}
- name: nginx-run
emptyDir: {}

View File

@@ -0,0 +1,272 @@
global:
profile: dev
release:
version: "2025.10.0-edge"
channel: edge
manifestSha256: "822f82987529ea38d2321dbdd2ef6874a4062a117116a20861c26a8df1807beb"
image:
pullPolicy: IfNotPresent
labels:
stellaops.io/channel: edge
telemetry:
collector:
enabled: true
defaultTenant: dev
tls:
secretName: stellaops-otel-tls
configMaps:
notify-config:
data:
notify.yaml: |
storage:
driver: mongo
connectionString: "mongodb://notify-mongo.dev.svc.cluster.local:27017"
database: "stellaops_notify_dev"
commandTimeoutSeconds: 30
authority:
enabled: true
issuer: "https://authority.dev.stella-ops.local"
metadataAddress: "https://authority.dev.stella-ops.local/.well-known/openid-configuration"
requireHttpsMetadata: false
allowAnonymousFallback: false
backchannelTimeoutSeconds: 30
tokenClockSkewSeconds: 60
audiences:
- notify.dev
readScope: notify.read
adminScope: notify.admin
api:
basePath: "/api/v1/notify"
internalBasePath: "/internal/notify"
tenantHeader: "X-StellaOps-Tenant"
plugins:
baseDirectory: "../"
directory: "plugins/notify"
searchPatterns:
- "StellaOps.Notify.Connectors.*.dll"
orderedPlugins:
- StellaOps.Notify.Connectors.Slack
- StellaOps.Notify.Connectors.Teams
- StellaOps.Notify.Connectors.Email
- StellaOps.Notify.Connectors.Webhook
telemetry:
enableRequestLogging: true
minimumLogLevel: Debug
policy-engine-activation:
data:
STELLAOPS_POLICY_ENGINE__ACTIVATION__FORCETWOPERSONAPPROVAL: "false"
STELLAOPS_POLICY_ENGINE__ACTIVATION__DEFAULTREQUIRESTWOPERSONAPPROVAL: "false"
STELLAOPS_POLICY_ENGINE__ACTIVATION__EMITAUDITLOGS: "true"
services:
authority:
image: registry.stella-ops.org/stellaops/authority@sha256:a8e8faec44a579aa5714e58be835f25575710430b1ad2ccd1282a018cd9ffcdd
service:
port: 8440
env:
STELLAOPS_AUTHORITY__ISSUER: "https://stellaops-authority:8440"
STELLAOPS_AUTHORITY__MONGO__CONNECTIONSTRING: "mongodb://stellaops:stellaops@stellaops-mongo:27017"
STELLAOPS_AUTHORITY__PLUGINDIRECTORIES__0: "/app/plugins"
STELLAOPS_AUTHORITY__PLUGINS__CONFIGURATIONDIRECTORY: "/app/etc/authority.plugins"
signer:
image: registry.stella-ops.org/stellaops/signer@sha256:8bfef9a75783883d49fc18e3566553934e970b00ee090abee9cb110d2d5c3298
service:
port: 8441
env:
SIGNER__AUTHORITY__BASEURL: "https://stellaops-authority:8440"
SIGNER__POE__INTROSPECTURL: "https://licensing.svc.local/introspect"
SIGNER__STORAGE__MONGO__CONNECTIONSTRING: "mongodb://stellaops:stellaops@stellaops-mongo:27017"
attestor:
image: registry.stella-ops.org/stellaops/attestor@sha256:5cc417948c029da01dccf36e4645d961a3f6d8de7e62fe98d845f07cd2282114
service:
port: 8442
env:
ATTESTOR__SIGNER__BASEURL: "https://stellaops-signer:8441"
ATTESTOR__MONGO__CONNECTIONSTRING: "mongodb://stellaops:stellaops@stellaops-mongo:27017"
concelier:
image: registry.stella-ops.org/stellaops/concelier@sha256:dafef3954eb4b837e2c424dd2d23e1e4d60fa83794840fac9cd3dea1d43bd085
service:
port: 8445
env:
CONCELIER__STORAGE__MONGO__CONNECTIONSTRING: "mongodb://stellaops:stellaops@stellaops-mongo:27017"
CONCELIER__STORAGE__S3__ENDPOINT: "http://stellaops-minio:9000"
CONCELIER__STORAGE__S3__ACCESSKEYID: "stellaops"
CONCELIER__STORAGE__S3__SECRETACCESSKEY: "dev-minio-secret"
CONCELIER__AUTHORITY__BASEURL: "https://stellaops-authority:8440"
volumeMounts:
- name: concelier-jobs
mountPath: /var/lib/concelier/jobs
volumes:
- name: concelier-jobs
emptyDir: {}
scanner-web:
image: registry.stella-ops.org/stellaops/scanner-web@sha256:e0dfdb087e330585a5953029fb4757f5abdf7610820a085bd61b457dbead9a11
service:
port: 8444
env:
SCANNER__STORAGE__MONGO__CONNECTIONSTRING: "mongodb://stellaops:stellaops@stellaops-mongo:27017"
SCANNER__ARTIFACTSTORE__DRIVER: "rustfs"
SCANNER__ARTIFACTSTORE__ENDPOINT: "http://stellaops-rustfs:8080/api/v1"
SCANNER__ARTIFACTSTORE__BUCKET: "scanner-artifacts"
SCANNER__ARTIFACTSTORE__TIMEOUTSECONDS: "30"
SCANNER__QUEUE__BROKER: "nats://stellaops-nats:4222"
SCANNER__EVENTS__ENABLED: "false"
SCANNER__EVENTS__DRIVER: "redis"
SCANNER__EVENTS__DSN: ""
SCANNER__EVENTS__STREAM: "stella.events"
SCANNER__EVENTS__PUBLISHTIMEOUTSECONDS: "5"
SCANNER__EVENTS__MAXSTREAMLENGTH: "10000"
SCANNER__OFFLINEKIT__ENABLED: "false"
SCANNER__OFFLINEKIT__REQUIREDSSE: "true"
SCANNER__OFFLINEKIT__REKOROFFLINEMODE: "true"
SCANNER__OFFLINEKIT__TRUSTROOTDIRECTORY: "/etc/stellaops/trust-roots"
SCANNER__OFFLINEKIT__REKORSNAPSHOTDIRECTORY: "/var/lib/stellaops/rekor-snapshot"
SCANNER_SURFACE_FS_ENDPOINT: "http://stellaops-rustfs:8080/api/v1"
SCANNER_SURFACE_CACHE_ROOT: "/var/lib/stellaops/surface"
SCANNER_SURFACE_SECRETS_PROVIDER: "inline"
SCANNER_SURFACE_SECRETS_ROOT: ""
scanner-worker:
image: registry.stella-ops.org/stellaops/scanner-worker@sha256:92dda42f6f64b2d9522104a5c9ffb61d37b34dd193132b68457a259748008f37
env:
SCANNER__STORAGE__MONGO__CONNECTIONSTRING: "mongodb://stellaops:stellaops@stellaops-mongo:27017"
SCANNER__ARTIFACTSTORE__DRIVER: "rustfs"
SCANNER__ARTIFACTSTORE__ENDPOINT: "http://stellaops-rustfs:8080/api/v1"
SCANNER__ARTIFACTSTORE__BUCKET: "scanner-artifacts"
SCANNER__ARTIFACTSTORE__TIMEOUTSECONDS: "30"
SCANNER__QUEUE__BROKER: "nats://stellaops-nats:4222"
SCANNER__EVENTS__ENABLED: "false"
SCANNER__EVENTS__DRIVER: "redis"
SCANNER__EVENTS__DSN: ""
SCANNER__EVENTS__STREAM: "stella.events"
SCANNER__EVENTS__PUBLISHTIMEOUTSECONDS: "5"
SCANNER__EVENTS__MAXSTREAMLENGTH: "10000"
SCANNER_SURFACE_FS_ENDPOINT: "http://stellaops-rustfs:8080/api/v1"
SCANNER_SURFACE_CACHE_ROOT: "/var/lib/stellaops/surface"
SCANNER_SURFACE_SECRETS_PROVIDER: "inline"
SCANNER_SURFACE_SECRETS_ROOT: ""
notify-web:
image: registry.stella-ops.org/stellaops/notify-web:2025.10.0-edge
service:
port: 8446
env:
DOTNET_ENVIRONMENT: Development
configMounts:
- name: notify-config
mountPath: /app/etc/notify.yaml
subPath: notify.yaml
configMap: notify-config
excititor:
image: registry.stella-ops.org/stellaops/excititor@sha256:d9bd5cadf1eab427447ce3df7302c30ded837239771cc6433b9befb895054285
env:
EXCITITOR__CONCELIER__BASEURL: "https://stellaops-concelier:8445"
EXCITITOR__STORAGE__MONGO__CONNECTIONSTRING: "mongodb://stellaops:stellaops@stellaops-mongo:27017"
advisory-ai-web:
image: registry.stella-ops.org/stellaops/advisory-ai-web:2025.10.0-edge
service:
port: 8448
env:
ADVISORYAI__AdvisoryAI__SbomBaseAddress: http://stellaops-scanner-web:8444
ADVISORYAI__AdvisoryAI__Queue__DirectoryPath: /var/lib/advisory-ai/queue
ADVISORYAI__AdvisoryAI__Storage__PlanCacheDirectory: /var/lib/advisory-ai/plans
ADVISORYAI__AdvisoryAI__Storage__OutputDirectory: /var/lib/advisory-ai/outputs
ADVISORYAI__AdvisoryAI__Inference__Mode: Local
ADVISORYAI__AdvisoryAI__Inference__Remote__BaseAddress: ""
ADVISORYAI__AdvisoryAI__Inference__Remote__ApiKey: ""
volumeMounts:
- name: advisory-ai-data
mountPath: /var/lib/advisory-ai
volumeClaims:
- name: advisory-ai-data
claimName: stellaops-advisory-ai-data
advisory-ai-worker:
image: registry.stella-ops.org/stellaops/advisory-ai-worker:2025.10.0-edge
env:
ADVISORYAI__AdvisoryAI__SbomBaseAddress: http://stellaops-scanner-web:8444
ADVISORYAI__AdvisoryAI__Queue__DirectoryPath: /var/lib/advisory-ai/queue
ADVISORYAI__AdvisoryAI__Storage__PlanCacheDirectory: /var/lib/advisory-ai/plans
ADVISORYAI__AdvisoryAI__Storage__OutputDirectory: /var/lib/advisory-ai/outputs
ADVISORYAI__AdvisoryAI__Inference__Mode: Local
ADVISORYAI__AdvisoryAI__Inference__Remote__BaseAddress: ""
ADVISORYAI__AdvisoryAI__Inference__Remote__ApiKey: ""
volumeMounts:
- name: advisory-ai-data
mountPath: /var/lib/advisory-ai
volumeClaims:
- name: advisory-ai-data
claimName: stellaops-advisory-ai-data
web-ui:
image: registry.stella-ops.org/stellaops/web-ui@sha256:38b225fa7767a5b94ebae4dae8696044126aac429415e93de514d5dd95748dcf
service:
port: 8443
env:
STELLAOPS_UI__BACKEND__BASEURL: "https://stellaops-scanner-web:8444"
mongo:
class: infrastructure
image: docker.io/library/mongo@sha256:c258b26dbb7774f97f52aff52231ca5f228273a84329c5f5e451c3739457db49
service:
port: 27017
command:
- mongod
- --bind_ip_all
env:
MONGO_INITDB_ROOT_USERNAME: stellaops
MONGO_INITDB_ROOT_PASSWORD: stellaops
volumeMounts:
- name: mongo-data
mountPath: /data/db
volumes:
- name: mongo-data
emptyDir: {}
minio:
class: infrastructure
image: docker.io/minio/minio@sha256:14cea493d9a34af32f524e538b8346cf79f3321eff8e708c1e2960462bd8936e
service:
port: 9000
command:
- server
- /data
- --console-address
- :9001
env:
MINIO_ROOT_USER: stellaops
MINIO_ROOT_PASSWORD: dev-minio-secret
volumeMounts:
- name: minio-data
mountPath: /data
volumes:
- name: minio-data
emptyDir: {}
rustfs:
class: infrastructure
image: registry.stella-ops.org/stellaops/rustfs:2025.10.0-edge
service:
port: 8080
env:
RUSTFS__LOG__LEVEL: info
RUSTFS__STORAGE__PATH: /data
volumeMounts:
- name: rustfs-data
mountPath: /data
volumes:
- name: rustfs-data
emptyDir: {}
nats:
class: infrastructure
image: docker.io/library/nats@sha256:c82559e4476289481a8a5196e675ebfe67eea81d95e5161e3e78eccfe766608e
service:
port: 4222
command:
- -js
- -sd
- /data
volumeMounts:
- name: nats-data
mountPath: /data
volumes:
- name: nats-data
emptyDir: {}

View File

@@ -0,0 +1,14 @@
exportcenter:
image:
repository: registry.stella-ops.org/export-center
tag: latest
objectStorage:
endpoint: http://minio:9000
bucket: export-prod
accessKeySecret: exportcenter-minio
secretKeySecret: exportcenter-minio
signing:
kmsKey: exportcenter-kms
kmsRegion: us-east-1
dsse:
enabled: true

View File

@@ -0,0 +1,58 @@
# Exporter (Export Center) values overlay
# Use: helm install stellaops . -f values-exporter.yaml
exporter:
enabled: true
image: registry.stella-ops.org/stellaops/exporter:2025.10.0-edge
replicas: 1
port: 8080
# Export configuration
storage:
# Object store for export artifacts
endpoint: ""
bucket: "stellaops-exports"
region: ""
# Retention policy
retention:
defaultDays: 30
maxDays: 365
resources:
limits:
cpu: "500m"
memory: "512Mi"
requests:
cpu: "100m"
memory: "256Mi"
service:
type: ClusterIP
port: 8080
livenessProbe:
httpGet:
path: /health/liveness
port: 8080
initialDelaySeconds: 10
periodSeconds: 30
readinessProbe:
httpGet:
path: /health/readiness
port: 8080
initialDelaySeconds: 5
periodSeconds: 10
securityContext:
runAsNonRoot: true
runAsUser: 10001
runAsGroup: 10001
containerSecurityContext:
allowPrivilegeEscalation: false
readOnlyRootFilesystem: true
capabilities:
drop:
- ALL

View File

@@ -0,0 +1,59 @@
# Ledger (Findings Ledger) values overlay
# Use: helm install stellaops . -f values-ledger.yaml
ledger:
enabled: true
image: registry.stella-ops.org/stellaops/findings-ledger:2025.10.0-edge
replicas: 1
port: 8080
# Database configuration
postgres:
host: ""
port: 5432
database: "stellaops_ledger"
schema: "findings"
# Connection string override (takes precedence)
connectionString: ""
# Tenant isolation
multiTenant: true
defaultTenant: "default"
resources:
limits:
cpu: "1000m"
memory: "1Gi"
requests:
cpu: "200m"
memory: "512Mi"
service:
type: ClusterIP
port: 8080
livenessProbe:
httpGet:
path: /health/liveness
port: 8080
initialDelaySeconds: 15
periodSeconds: 30
readinessProbe:
httpGet:
path: /health/readiness
port: 8080
initialDelaySeconds: 10
periodSeconds: 10
securityContext:
runAsNonRoot: true
runAsUser: 10001
runAsGroup: 10001
containerSecurityContext:
allowPrivilegeEscalation: false
readOnlyRootFilesystem: true
capabilities:
drop:
- ALL

View File

@@ -0,0 +1,289 @@
global:
profile: mirror-managed
release:
version: "2025.10.0-edge"
channel: edge
manifestSha256: "822f82987529ea38d2321dbdd2ef6874a4062a117116a20861c26a8df1807beb"
image:
pullPolicy: IfNotPresent
labels:
stellaops.io/channel: edge
configMaps:
mirror-gateway:
data:
mirror.conf: |
proxy_cache_path /var/cache/nginx/mirror levels=1:2 keys_zone=mirror_cache:100m max_size=10g inactive=12h use_temp_path=off;
map $request_uri $mirror_cache_key {
default $scheme$request_method$host$request_uri;
}
upstream concelier_backend {
server stellaops-concelier:8445;
keepalive 32;
}
upstream excititor_backend {
server stellaops-excititor:8448;
keepalive 32;
}
server {
listen 80;
server_name _;
return 301 https://$host$request_uri;
}
server {
listen 443 ssl http2;
server_name mirror-primary.stella-ops.org;
ssl_certificate /etc/nginx/tls/mirror-primary.crt;
ssl_certificate_key /etc/nginx/tls/mirror-primary.key;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_prefer_server_ciphers on;
auth_basic "StellaOps Mirror primary";
auth_basic_user_file /etc/nginx/secrets/mirror-primary.htpasswd;
include /etc/nginx/conf.d/mirror-locations.conf;
}
server {
listen 443 ssl http2;
server_name mirror-community.stella-ops.org;
ssl_certificate /etc/nginx/tls/mirror-community.crt;
ssl_certificate_key /etc/nginx/tls/mirror-community.key;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_prefer_server_ciphers on;
auth_basic "StellaOps Mirror community";
auth_basic_user_file /etc/nginx/secrets/mirror-community.htpasswd;
include /etc/nginx/conf.d/mirror-locations.conf;
}
mirror-locations.conf: |
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_redirect off;
add_header X-Cache-Status $upstream_cache_status always;
location = /healthz {
default_type application/json;
return 200 '{"status":"ok"}';
}
location /concelier/exports/ {
proxy_pass http://concelier_backend/concelier/exports/;
proxy_cache mirror_cache;
proxy_cache_key $mirror_cache_key;
proxy_cache_valid 200 5m;
proxy_cache_valid 404 1m;
add_header Cache-Control "public, max-age=300, immutable" always;
}
location /concelier/ {
proxy_pass http://concelier_backend/concelier/;
proxy_cache off;
}
location /excititor/mirror/ {
proxy_pass http://excititor_backend/excititor/mirror/;
proxy_cache mirror_cache;
proxy_cache_key $mirror_cache_key;
proxy_cache_valid 200 5m;
proxy_cache_valid 404 1m;
add_header Cache-Control "public, max-age=300, immutable" always;
}
location /excititor/ {
proxy_pass http://excititor_backend/excititor/;
proxy_cache off;
}
location / {
return 404;
}
policy-engine-activation:
data:
STELLAOPS_POLICY_ENGINE__ACTIVATION__FORCETWOPERSONAPPROVAL: "true"
STELLAOPS_POLICY_ENGINE__ACTIVATION__DEFAULTREQUIRESTWOPERSONAPPROVAL: "true"
STELLAOPS_POLICY_ENGINE__ACTIVATION__EMITAUDITLOGS: "true"
services:
concelier:
image: registry.stella-ops.org/stellaops/concelier@sha256:dafef3954eb4b837e2c424dd2d23e1e4d60fa83794840fac9cd3dea1d43bd085
service:
port: 8445
env:
ASPNETCORE_URLS: "http://+:8445"
CONCELIER__STORAGE__MONGO__CONNECTIONSTRING: "mongodb://stellaops_mirror:mirror-password@stellaops-mongo:27017/concelier?authSource=admin"
CONCELIER__STORAGE__S3__ENDPOINT: "http://stellaops-minio:9000"
CONCELIER__STORAGE__S3__ACCESSKEYID: "stellaops-mirror"
CONCELIER__STORAGE__S3__SECRETACCESSKEY: "mirror-minio-secret"
CONCELIER__TELEMETRY__SERVICENAME: "stellaops-concelier-mirror"
CONCELIER__MIRROR__ENABLED: "true"
CONCELIER__MIRROR__EXPORTROOT: "/exports/json"
CONCELIER__MIRROR__LATESTDIRECTORYNAME: "latest"
CONCELIER__MIRROR__MIRRORDIRECTORYNAME: "mirror"
CONCELIER__MIRROR__REQUIREAUTHENTICATION: "true"
CONCELIER__MIRROR__MAXINDEXREQUESTSPERHOUR: "600"
CONCELIER__MIRROR__DOMAINS__0__ID: "primary"
CONCELIER__MIRROR__DOMAINS__0__DISPLAYNAME: "Primary Mirror"
CONCELIER__MIRROR__DOMAINS__0__REQUIREAUTHENTICATION: "true"
CONCELIER__MIRROR__DOMAINS__0__MAXDOWNLOADREQUESTSPERHOUR: "3600"
CONCELIER__MIRROR__DOMAINS__1__ID: "community"
CONCELIER__MIRROR__DOMAINS__1__DISPLAYNAME: "Community Mirror"
CONCELIER__MIRROR__DOMAINS__1__REQUIREAUTHENTICATION: "false"
CONCELIER__MIRROR__DOMAINS__1__MAXDOWNLOADREQUESTSPERHOUR: "1800"
CONCELIER__AUTHORITY__ENABLED: "true"
CONCELIER__AUTHORITY__ALLOWANONYMOUSFALLBACK: "false"
CONCELIER__AUTHORITY__ISSUER: "https://authority.stella-ops.org"
CONCELIER__AUTHORITY__METADATAADDRESS: ""
CONCELIER__AUTHORITY__CLIENTID: "stellaops-concelier-mirror"
CONCELIER__AUTHORITY__CLIENTSECRETFILE: "/run/secrets/concelier-authority-client"
CONCELIER__AUTHORITY__CLIENTSCOPES__0: "concelier.mirror.read"
CONCELIER__AUTHORITY__AUDIENCES__0: "api://concelier.mirror"
CONCELIER__AUTHORITY__BYPASSNETWORKS__0: "10.0.0.0/8"
CONCELIER__AUTHORITY__BYPASSNETWORKS__1: "127.0.0.1/32"
CONCELIER__AUTHORITY__BYPASSNETWORKS__2: "::1/128"
CONCELIER__AUTHORITY__RESILIENCE__ENABLERETRIES: "true"
CONCELIER__AUTHORITY__RESILIENCE__RETRYDELAYS__0: "00:00:01"
CONCELIER__AUTHORITY__RESILIENCE__RETRYDELAYS__1: "00:00:02"
CONCELIER__AUTHORITY__RESILIENCE__RETRYDELAYS__2: "00:00:05"
CONCELIER__AUTHORITY__RESILIENCE__ALLOWOFFLINECACHEFALLBACK: "true"
CONCELIER__AUTHORITY__RESILIENCE__OFFLINECACHETOLERANCE: "00:10:00"
volumeMounts:
- name: concelier-jobs
mountPath: /var/lib/concelier/jobs
- name: concelier-exports
mountPath: /exports/json
- name: concelier-secrets
mountPath: /run/secrets
readOnly: true
volumes:
- name: concelier-jobs
persistentVolumeClaim:
claimName: concelier-mirror-jobs
- name: concelier-exports
persistentVolumeClaim:
claimName: concelier-mirror-exports
- name: concelier-secrets
secret:
secretName: concelier-mirror-auth
excititor:
image: registry.stella-ops.org/stellaops/excititor@sha256:d9bd5cadf1eab427447ce3df7302c30ded837239771cc6433b9befb895054285
env:
ASPNETCORE_URLS: "http://+:8448"
EXCITITOR__STORAGE__MONGO__CONNECTIONSTRING: "mongodb://stellaops_mirror:mirror-password@stellaops-mongo:27017/excititor?authSource=admin"
EXCITITOR__STORAGE__MONGO__DATABASENAME: "excititor"
EXCITITOR__ARTIFACTS__FILESYSTEM__ROOT: "/exports"
EXCITITOR__ARTIFACTS__FILESYSTEM__OVERWRITEEXISTING: "false"
EXCITITOR__MIRROR__DOMAINS__0__ID: "primary"
EXCITITOR__MIRROR__DOMAINS__0__DISPLAYNAME: "Primary Mirror"
EXCITITOR__MIRROR__DOMAINS__0__REQUIREAUTHENTICATION: "true"
EXCITITOR__MIRROR__DOMAINS__0__MAXINDEXREQUESTSPERHOUR: "300"
EXCITITOR__MIRROR__DOMAINS__0__MAXDOWNLOADREQUESTSPERHOUR: "2400"
EXCITITOR__MIRROR__DOMAINS__0__EXPORTS__0__KEY: "consensus-json"
EXCITITOR__MIRROR__DOMAINS__0__EXPORTS__0__FORMAT: "json"
EXCITITOR__MIRROR__DOMAINS__0__EXPORTS__0__VIEW: "consensus"
EXCITITOR__MIRROR__DOMAINS__0__EXPORTS__1__KEY: "consensus-openvex"
EXCITITOR__MIRROR__DOMAINS__0__EXPORTS__1__FORMAT: "openvex"
EXCITITOR__MIRROR__DOMAINS__0__EXPORTS__1__VIEW: "consensus"
EXCITITOR__MIRROR__DOMAINS__1__ID: "community"
EXCITITOR__MIRROR__DOMAINS__1__DISPLAYNAME: "Community Mirror"
EXCITITOR__MIRROR__DOMAINS__1__REQUIREAUTHENTICATION: "false"
EXCITITOR__MIRROR__DOMAINS__1__MAXINDEXREQUESTSPERHOUR: "120"
EXCITITOR__MIRROR__DOMAINS__1__MAXDOWNLOADREQUESTSPERHOUR: "600"
EXCITITOR__MIRROR__DOMAINS__1__EXPORTS__0__KEY: "community-consensus"
EXCITITOR__MIRROR__DOMAINS__1__EXPORTS__0__FORMAT: "json"
EXCITITOR__MIRROR__DOMAINS__1__EXPORTS__0__VIEW: "consensus"
volumeMounts:
- name: excititor-exports
mountPath: /exports
- name: excititor-secrets
mountPath: /run/secrets
readOnly: true
volumes:
- name: excititor-exports
persistentVolumeClaim:
claimName: excititor-mirror-exports
- name: excititor-secrets
secret:
secretName: excititor-mirror-auth
mongo:
class: infrastructure
image: docker.io/library/mongo@sha256:c258b26dbb7774f97f52aff52231ca5f228273a84329c5f5e451c3739457db49
service:
port: 27017
command:
- mongod
- --bind_ip_all
env:
MONGO_INITDB_ROOT_USERNAME: "stellaops_mirror"
MONGO_INITDB_ROOT_PASSWORD: "mirror-password"
volumeMounts:
- name: mongo-data
mountPath: /data/db
volumeClaims:
- name: mongo-data
claimName: mirror-mongo-data
minio:
class: infrastructure
image: docker.io/minio/minio@sha256:14cea493d9a34af32f524e538b8346cf79f3321eff8e708c1e2960462bd8936e
service:
port: 9000
command:
- server
- /data
- --console-address
- :9001
env:
MINIO_ROOT_USER: "stellaops-mirror"
MINIO_ROOT_PASSWORD: "mirror-minio-secret"
volumeMounts:
- name: minio-data
mountPath: /data
volumeClaims:
- name: minio-data
claimName: mirror-minio-data
mirror-gateway:
image: docker.io/library/nginx@sha256:208b70eefac13ee9be00e486f79c695b15cef861c680527171a27d253d834be9
service:
type: LoadBalancer
port: 443
portName: https
targetPort: 443
configMounts:
- name: mirror-gateway-conf
mountPath: /etc/nginx/conf.d
configMap: mirror-gateway
volumeMounts:
- name: mirror-gateway-tls
mountPath: /etc/nginx/tls
readOnly: true
- name: mirror-gateway-secrets
mountPath: /etc/nginx/secrets
readOnly: true
- name: mirror-cache
mountPath: /var/cache/nginx
volumes:
- name: mirror-gateway-tls
secret:
secretName: mirror-gateway-tls
- name: mirror-gateway-secrets
secret:
secretName: mirror-gateway-htpasswd
- name: mirror-cache
emptyDir: {}

View File

@@ -0,0 +1,18 @@
mock:
enabled: true
orchestrator:
image: registry.stella-ops.org/stellaops/orchestrator@sha256:97f12856ce870bafd3328bda86833bcccbf56d255941d804966b5557f6610119
policyRegistry:
image: registry.stella-ops.org/stellaops/policy-registry@sha256:c6cad8055e9827ebcbebb6ad4d6866dce4b83a0a49b0a8a6500b736a5cb26fa7
packsRegistry:
image: registry.stella-ops.org/stellaops/packs-registry@sha256:1f5e9416c4dc608594ad6fad87c24d72134427f899c192b494e22b268499c791
taskRunner:
image: registry.stella-ops.org/stellaops/task-runner@sha256:eb5ad992b49a41554f41516be1a6afcfa6522faf2111c08ff2b3664ad2fc954b
vexLens:
image: registry.stella-ops.org/stellaops/vex-lens@sha256:b44e63ecfeebc345a70c073c1ce5ace709c58be0ffaad0e2862758aeee3092fb
issuerDirectory:
image: registry.stella-ops.org/stellaops/issuer-directory@sha256:67e8ef02c97d3156741e857756994888f30c373ace8e84886762edba9dc51914
findingsLedger:
image: registry.stella-ops.org/stellaops/findings-ledger@sha256:71d4c361ba8b2f8b69d652597bc3f2efc8a64f93fab854ce25272a88506df49c
vulnExplorerApi:
image: registry.stella-ops.org/stellaops/vuln-explorer-api@sha256:7fc7e43a05cbeb0106ce7d4d634612e83de6fdc119aaab754a71c1d60b82841d

View File

@@ -0,0 +1,15 @@
notify:
image:
repository: registry.stella-ops.org/notify
tag: latest
smtp:
host: smtp.example.com
port: 587
usernameSecret: notify-smtp
passwordSecret: notify-smtp
webhook:
allowedHosts: ["https://hooks.slack.com"]
chat:
webhookSecret: notify-chat
tls:
secretName: notify-tls

View File

@@ -0,0 +1,209 @@
# Orchestrator Service Helm Values Overlay
# Enables job scheduling, DAG planning, and worker coordination.
#
# Usage:
# helm upgrade stellaops ./stellaops -f values.yaml -f values-orchestrator.yaml
global:
labels:
stellaops.io/component: orchestrator
# Orchestrator-specific ConfigMaps
configMaps:
orchestrator-config:
data:
orchestrator.yaml: |
Orchestrator:
# Telemetry configuration
telemetry:
minimumLogLevel: Information
enableRequestLogging: true
otelEndpoint: ""
# Authority integration (disable for standalone testing)
authority:
enabled: true
issuer: https://authority.svc.cluster.local/realms/stellaops
requireHttpsMetadata: true
audiences:
- stellaops-platform
readScope: orchestrator:read
writeScope: orchestrator:write
adminScope: orchestrator:admin
# Tenant resolution
tenantHeader: X-StellaOps-Tenant
# PostgreSQL connection
storage:
connectionString: "Host=orchestrator-postgres;Database=stellaops_orchestrator;Username=orchestrator;Password=${POSTGRES_PASSWORD}"
commandTimeoutSeconds: 60
enableSensitiveDataLogging: false
# Scheduler configuration
scheduler:
# Maximum concurrent jobs per tenant
defaultConcurrencyLimit: 100
# Default rate limit (requests per second)
defaultRateLimit: 50
# Job claim timeout before re-queue
claimTimeoutMinutes: 30
# Heartbeat interval for active jobs
heartbeatIntervalSeconds: 30
# Maximum heartbeat misses before job marked stale
maxHeartbeatMisses: 3
# Autoscaling configuration
autoscaling:
# Enable autoscaling metrics endpoint
enabled: true
# Queue depth threshold for scale-up signal
queueDepthThreshold: 10000
# Dispatch latency P95 threshold (ms)
latencyP95ThresholdMs: 150
# Scale-up cooldown period
scaleUpCooldownSeconds: 60
# Scale-down cooldown period
scaleDownCooldownSeconds: 300
# Load shedding configuration
loadShedding:
enabled: true
# Warning threshold (load factor)
warningThreshold: 0.8
# Critical threshold (load factor)
criticalThreshold: 1.0
# Emergency threshold (load factor)
emergencyThreshold: 1.5
# Recovery cooldown
recoveryCooldownSeconds: 30
# Dead letter configuration
deadLetter:
# Maximum replay attempts
maxReplayAttempts: 3
# Entry expiration (days)
expirationDays: 30
# Purge interval
purgeIntervalHours: 24
# Backfill configuration
backfill:
# Maximum concurrent backfill requests
maxConcurrentRequests: 5
# Default batch size
defaultBatchSize: 1000
# Maximum retention lookback (days)
maxRetentionDays: 90
# Service definitions
services:
orchestrator-web:
image: registry.stella-ops.org/stellaops/orchestrator-web:2025.10.0-edge
replicas: 2
service:
port: 8080
configMounts:
- name: orchestrator-config
configMap: orchestrator-config
mountPath: /app/etc/orchestrator.yaml
subPath: orchestrator.yaml
envFrom:
- secretRef:
name: orchestrator-secrets
env:
ASPNETCORE_ENVIRONMENT: Production
ORCHESTRATOR__CONFIG: /app/etc/orchestrator.yaml
ports:
- containerPort: 8080
resources:
requests:
memory: "256Mi"
cpu: "250m"
limits:
memory: "1Gi"
cpu: "1000m"
readinessProbe:
httpGet:
path: /readyz
port: 8080
initialDelaySeconds: 5
periodSeconds: 10
timeoutSeconds: 5
failureThreshold: 3
livenessProbe:
httpGet:
path: /livez
port: 8080
initialDelaySeconds: 10
periodSeconds: 20
timeoutSeconds: 5
failureThreshold: 3
startupProbe:
httpGet:
path: /startupz
port: 8080
initialDelaySeconds: 3
periodSeconds: 5
timeoutSeconds: 3
failureThreshold: 30
orchestrator-worker:
image: registry.stella-ops.org/stellaops/orchestrator-worker:2025.10.0-edge
replicas: 1
configMounts:
- name: orchestrator-config
configMap: orchestrator-config
mountPath: /app/etc/orchestrator.yaml
subPath: orchestrator.yaml
envFrom:
- secretRef:
name: orchestrator-secrets
env:
DOTNET_ENVIRONMENT: Production
ORCHESTRATOR__CONFIG: /app/etc/orchestrator.yaml
resources:
requests:
memory: "128Mi"
cpu: "100m"
limits:
memory: "512Mi"
cpu: "500m"
orchestrator-postgres:
class: infrastructure
image: docker.io/library/postgres:16-alpine
service:
port: 5432
envFrom:
- secretRef:
name: orchestrator-postgres-secrets
env:
POSTGRES_DB: stellaops_orchestrator
POSTGRES_USER: orchestrator
volumeMounts:
- name: postgres-data
mountPath: /var/lib/postgresql/data
volumeClaims:
- name: postgres-data
claimName: orchestrator-postgres-data
readinessProbe:
exec:
command:
- pg_isready
- -U
- orchestrator
- -d
- stellaops_orchestrator
initialDelaySeconds: 5
periodSeconds: 10
livenessProbe:
exec:
command:
- pg_isready
- -U
- orchestrator
- -d
- stellaops_orchestrator
initialDelaySeconds: 15
periodSeconds: 30

View File

@@ -0,0 +1,339 @@
global:
profile: prod
release:
version: "2025.09.2"
channel: stable
manifestSha256: "dc3c8fe1ab83941c838ccc5a8a5862f7ddfa38c2078e580b5649db26554565b7"
image:
pullPolicy: IfNotPresent
labels:
stellaops.io/channel: stable
stellaops.io/profile: prod
# Migration jobs for controlled rollouts (disabled by default)
migrations:
enabled: false
jobs: []
networkPolicy:
enabled: true
ingressPort: 8443
egressPort: 443
ingressNamespaces:
kubernetes.io/metadata.name: stellaops
egressNamespaces:
kubernetes.io/metadata.name: stellaops
ingress:
enabled: true
className: nginx
annotations:
nginx.ingress.kubernetes.io/proxy-body-size: "50m"
nginx.ingress.kubernetes.io/ssl-redirect: "true"
cert-manager.io/cluster-issuer: "letsencrypt-prod"
hosts:
- host: gateway.prod.stella-ops.org
path: /
servicePort: 80
tls:
- secretName: stellaops-prod-tls
hosts:
- gateway.prod.stella-ops.org
externalSecrets:
enabled: true
secrets:
- name: core-secrets
storeRef:
name: stellaops-secret-store
kind: ClusterSecretStore
target:
name: stellaops-prod-core
data:
- key: STELLAOPS_AUTHORITY__JWT__SIGNINGKEY
remoteKey: prod/authority/jwt-signing-key
- key: STELLAOPS_SECRETS_ENCRYPTION_KEY
remoteKey: prod/core/secrets-encryption-key
prometheus:
enabled: true
path: /metrics
port: 8080
scheme: http
hpa:
enabled: true
minReplicas: 2
maxReplicas: 6
cpu:
targetPercentage: 70
memory:
targetPercentage: 75
configMaps:
notify-config:
data:
notify.yaml: |
storage:
driver: mongo
connectionString: "mongodb://stellaops-mongo:27017"
database: "stellaops_notify_prod"
commandTimeoutSeconds: 45
authority:
enabled: true
issuer: "https://authority.prod.stella-ops.org"
metadataAddress: "https://authority.prod.stella-ops.org/.well-known/openid-configuration"
requireHttpsMetadata: true
allowAnonymousFallback: false
backchannelTimeoutSeconds: 30
tokenClockSkewSeconds: 60
audiences:
- notify
readScope: notify.read
adminScope: notify.admin
api:
basePath: "/api/v1/notify"
internalBasePath: "/internal/notify"
tenantHeader: "X-StellaOps-Tenant"
plugins:
baseDirectory: "/opt/stellaops"
directory: "plugins/notify"
searchPatterns:
- "StellaOps.Notify.Connectors.*.dll"
orderedPlugins:
- StellaOps.Notify.Connectors.Slack
- StellaOps.Notify.Connectors.Teams
- StellaOps.Notify.Connectors.Email
- StellaOps.Notify.Connectors.Webhook
telemetry:
enableRequestLogging: true
minimumLogLevel: Information
policy-engine-activation:
data:
STELLAOPS_POLICY_ENGINE__ACTIVATION__FORCETWOPERSONAPPROVAL: "true"
STELLAOPS_POLICY_ENGINE__ACTIVATION__DEFAULTREQUIRESTWOPERSONAPPROVAL: "true"
STELLAOPS_POLICY_ENGINE__ACTIVATION__EMITAUDITLOGS: "true"
services:
authority:
image: registry.stella-ops.org/stellaops/authority@sha256:b0348bad1d0b401cc3c71cb40ba034c8043b6c8874546f90d4783c9dbfcc0bf5
service:
port: 8440
env:
STELLAOPS_AUTHORITY__ISSUER: "https://authority.prod.stella-ops.org"
STELLAOPS_AUTHORITY__PLUGINDIRECTORIES__0: "/app/plugins"
STELLAOPS_AUTHORITY__PLUGINS__CONFIGURATIONDIRECTORY: "/app/etc/authority.plugins"
envFrom:
- secretRef:
name: stellaops-prod-core
signer:
image: registry.stella-ops.org/stellaops/signer@sha256:8ad574e61f3a9e9bda8a58eb2700ae46813284e35a150b1137bc7c2b92ac0f2e
service:
port: 8441
env:
SIGNER__AUTHORITY__BASEURL: "https://stellaops-authority:8440"
SIGNER__POE__INTROSPECTURL: "https://licensing.prod.stella-ops.org/introspect"
envFrom:
- secretRef:
name: stellaops-prod-core
attestor:
image: registry.stella-ops.org/stellaops/attestor@sha256:0534985f978b0b5d220d73c96fddd962cd9135f616811cbe3bff4666c5af568f
service:
port: 8442
env:
ATTESTOR__SIGNER__BASEURL: "https://stellaops-signer:8441"
envFrom:
- secretRef:
name: stellaops-prod-core
concelier:
image: registry.stella-ops.org/stellaops/concelier@sha256:c58cdcaee1d266d68d498e41110a589dd204b487d37381096bd61ab345a867c5
service:
port: 8445
env:
CONCELIER__STORAGE__S3__ENDPOINT: "http://stellaops-minio:9000"
CONCELIER__AUTHORITY__BASEURL: "https://stellaops-authority:8440"
envFrom:
- secretRef:
name: stellaops-prod-core
volumeMounts:
- name: concelier-jobs
mountPath: /var/lib/concelier/jobs
volumeClaims:
- name: concelier-jobs
claimName: stellaops-concelier-jobs
scanner-web:
image: registry.stella-ops.org/stellaops/scanner-web@sha256:14b23448c3f9586a9156370b3e8c1991b61907efa666ca37dd3aaed1e79fe3b7
service:
port: 8444
env:
SCANNER__ARTIFACTSTORE__DRIVER: "rustfs"
SCANNER__ARTIFACTSTORE__ENDPOINT: "http://stellaops-rustfs:8080/api/v1"
SCANNER__ARTIFACTSTORE__BUCKET: "scanner-artifacts"
SCANNER__ARTIFACTSTORE__TIMEOUTSECONDS: "30"
SCANNER__QUEUE__BROKER: "nats://stellaops-nats:4222"
SCANNER__EVENTS__ENABLED: "true"
SCANNER__EVENTS__DRIVER: "redis"
SCANNER__EVENTS__DSN: ""
SCANNER__EVENTS__STREAM: "stella.events"
SCANNER__EVENTS__PUBLISHTIMEOUTSECONDS: "5"
SCANNER__EVENTS__MAXSTREAMLENGTH: "10000"
SCANNER__OFFLINEKIT__ENABLED: "false"
SCANNER__OFFLINEKIT__REQUIREDSSE: "true"
SCANNER__OFFLINEKIT__REKOROFFLINEMODE: "true"
SCANNER__OFFLINEKIT__TRUSTROOTDIRECTORY: "/etc/stellaops/trust-roots"
SCANNER__OFFLINEKIT__REKORSNAPSHOTDIRECTORY: "/var/lib/stellaops/rekor-snapshot"
SCANNER_SURFACE_FS_ENDPOINT: "http://stellaops-rustfs:8080/api/v1"
SCANNER_SURFACE_CACHE_ROOT: "/var/lib/stellaops/surface"
SCANNER_SURFACE_SECRETS_PROVIDER: "kubernetes"
SCANNER_SURFACE_SECRETS_ROOT: "stellaops/scanner"
envFrom:
- secretRef:
name: stellaops-prod-core
scanner-worker:
image: registry.stella-ops.org/stellaops/scanner-worker@sha256:32e25e76386eb9ea8bee0a1ad546775db9a2df989fab61ac877e351881960dab
replicas: 3
env:
SCANNER__ARTIFACTSTORE__DRIVER: "rustfs"
SCANNER__ARTIFACTSTORE__ENDPOINT: "http://stellaops-rustfs:8080/api/v1"
SCANNER__ARTIFACTSTORE__BUCKET: "scanner-artifacts"
SCANNER__ARTIFACTSTORE__TIMEOUTSECONDS: "30"
SCANNER__QUEUE__BROKER: "nats://stellaops-nats:4222"
SCANNER__EVENTS__ENABLED: "true"
SCANNER__EVENTS__DRIVER: "redis"
SCANNER__EVENTS__DSN: ""
SCANNER__EVENTS__STREAM: "stella.events"
SCANNER__EVENTS__PUBLISHTIMEOUTSECONDS: "5"
SCANNER__EVENTS__MAXSTREAMLENGTH: "10000"
SCANNER_SURFACE_FS_ENDPOINT: "http://stellaops-rustfs:8080/api/v1"
SCANNER_SURFACE_CACHE_ROOT: "/var/lib/stellaops/surface"
SCANNER_SURFACE_SECRETS_PROVIDER: "kubernetes"
SCANNER_SURFACE_SECRETS_ROOT: "stellaops/scanner"
envFrom:
- secretRef:
name: stellaops-prod-core
notify-web:
image: registry.stella-ops.org/stellaops/notify-web:2025.09.2
service:
port: 8446
env:
DOTNET_ENVIRONMENT: Production
envFrom:
- secretRef:
name: stellaops-prod-notify
configMounts:
- name: notify-config
mountPath: /app/etc/notify.yaml
subPath: notify.yaml
configMap: notify-config
excititor:
image: registry.stella-ops.org/stellaops/excititor@sha256:59022e2016aebcef5c856d163ae705755d3f81949d41195256e935ef40a627fa
env:
EXCITITOR__CONCELIER__BASEURL: "https://stellaops-concelier:8445"
envFrom:
- secretRef:
name: stellaops-prod-core
advisory-ai-web:
image: registry.stella-ops.org/stellaops/advisory-ai-web:2025.09.2
service:
port: 8448
env:
ADVISORYAI__AdvisoryAI__SbomBaseAddress: https://stellaops-scanner-web:8444
ADVISORYAI__AdvisoryAI__Queue__DirectoryPath: /var/lib/advisory-ai/queue
ADVISORYAI__AdvisoryAI__Storage__PlanCacheDirectory: /var/lib/advisory-ai/plans
ADVISORYAI__AdvisoryAI__Storage__OutputDirectory: /var/lib/advisory-ai/outputs
ADVISORYAI__AdvisoryAI__Inference__Mode: Local
ADVISORYAI__AdvisoryAI__Inference__Remote__BaseAddress: ""
ADVISORYAI__AdvisoryAI__Inference__Remote__ApiKey: ""
envFrom:
- secretRef:
name: stellaops-prod-core
volumeMounts:
- name: advisory-ai-data
mountPath: /var/lib/advisory-ai
volumeClaims:
- name: advisory-ai-data
claimName: stellaops-advisory-ai-data
advisory-ai-worker:
image: registry.stella-ops.org/stellaops/advisory-ai-worker:2025.09.2
env:
ADVISORYAI__AdvisoryAI__SbomBaseAddress: https://stellaops-scanner-web:8444
ADVISORYAI__AdvisoryAI__Queue__DirectoryPath: /var/lib/advisory-ai/queue
ADVISORYAI__AdvisoryAI__Storage__PlanCacheDirectory: /var/lib/advisory-ai/plans
ADVISORYAI__AdvisoryAI__Storage__OutputDirectory: /var/lib/advisory-ai/outputs
ADVISORYAI__AdvisoryAI__Inference__Mode: Local
ADVISORYAI__AdvisoryAI__Inference__Remote__BaseAddress: ""
ADVISORYAI__AdvisoryAI__Inference__Remote__ApiKey: ""
envFrom:
- secretRef:
name: stellaops-prod-core
volumeMounts:
- name: advisory-ai-data
mountPath: /var/lib/advisory-ai
volumeClaims:
- name: advisory-ai-data
claimName: stellaops-advisory-ai-data
web-ui:
image: registry.stella-ops.org/stellaops/web-ui@sha256:10d924808c48e4353e3a241da62eb7aefe727a1d6dc830eb23a8e181013b3a23
service:
port: 8443
env:
STELLAOPS_UI__BACKEND__BASEURL: "https://stellaops-scanner-web:8444"
mongo:
class: infrastructure
image: docker.io/library/mongo@sha256:c258b26dbb7774f97f52aff52231ca5f228273a84329c5f5e451c3739457db49
service:
port: 27017
command:
- mongod
- --bind_ip_all
envFrom:
- secretRef:
name: stellaops-prod-mongo
volumeMounts:
- name: mongo-data
mountPath: /data/db
volumeClaims:
- name: mongo-data
claimName: stellaops-mongo-data
minio:
class: infrastructure
image: docker.io/minio/minio@sha256:14cea493d9a34af32f524e538b8346cf79f3321eff8e708c1e2960462bd8936e
service:
port: 9000
command:
- server
- /data
- --console-address
- :9001
envFrom:
- secretRef:
name: stellaops-prod-minio
volumeMounts:
- name: minio-data
mountPath: /data
volumeClaims:
- name: minio-data
claimName: stellaops-minio-data
rustfs:
class: infrastructure
image: registry.stella-ops.org/stellaops/rustfs:2025.10.0-edge
service:
port: 8080
command:
- serve
- --listen
- 0.0.0.0:8080
- --root
- /data
env:
RUSTFS__LOG__LEVEL: info
RUSTFS__STORAGE__PATH: /data
volumeMounts:
- name: rustfs-data
mountPath: /data
volumeClaims:
- name: rustfs-data
claimName: stellaops-rustfs-data

View File

@@ -0,0 +1,245 @@
global:
profile: stage
release:
version: "2025.09.2"
channel: stable
manifestSha256: "dc3c8fe1ab83941c838ccc5a8a5862f7ddfa38c2078e580b5649db26554565b7"
image:
pullPolicy: IfNotPresent
labels:
stellaops.io/channel: stable
telemetry:
collector:
enabled: true
defaultTenant: stage
tls:
secretName: stellaops-otel-tls-stage
configMaps:
notify-config:
data:
notify.yaml: |
storage:
driver: mongo
connectionString: "mongodb://notify-mongo.stage.svc.cluster.local:27017"
database: "stellaops_notify_stage"
commandTimeoutSeconds: 45
authority:
enabled: true
issuer: "https://authority.stage.stella-ops.org"
metadataAddress: "https://authority.stage.stella-ops.org/.well-known/openid-configuration"
requireHttpsMetadata: true
allowAnonymousFallback: false
backchannelTimeoutSeconds: 30
tokenClockSkewSeconds: 60
audiences:
- notify
readScope: notify.read
adminScope: notify.admin
api:
basePath: "/api/v1/notify"
internalBasePath: "/internal/notify"
tenantHeader: "X-StellaOps-Tenant"
plugins:
baseDirectory: "/opt/stellaops"
directory: "plugins/notify"
searchPatterns:
- "StellaOps.Notify.Connectors.*.dll"
orderedPlugins:
- StellaOps.Notify.Connectors.Slack
- StellaOps.Notify.Connectors.Teams
- StellaOps.Notify.Connectors.Email
- StellaOps.Notify.Connectors.Webhook
telemetry:
enableRequestLogging: true
minimumLogLevel: Information
policy-engine-activation:
data:
STELLAOPS_POLICY_ENGINE__ACTIVATION__FORCETWOPERSONAPPROVAL: "true"
STELLAOPS_POLICY_ENGINE__ACTIVATION__DEFAULTREQUIRESTWOPERSONAPPROVAL: "true"
STELLAOPS_POLICY_ENGINE__ACTIVATION__EMITAUDITLOGS: "true"
services:
authority:
image: registry.stella-ops.org/stellaops/authority@sha256:b0348bad1d0b401cc3c71cb40ba034c8043b6c8874546f90d4783c9dbfcc0bf5
service:
port: 8440
env:
STELLAOPS_AUTHORITY__ISSUER: "https://stellaops-authority:8440"
STELLAOPS_AUTHORITY__MONGO__CONNECTIONSTRING: "mongodb://stellaops-stage:stellaops-stage@stellaops-mongo:27017"
STELLAOPS_AUTHORITY__PLUGINDIRECTORIES__0: "/app/plugins"
STELLAOPS_AUTHORITY__PLUGINS__CONFIGURATIONDIRECTORY: "/app/etc/authority.plugins"
signer:
image: registry.stella-ops.org/stellaops/signer@sha256:8ad574e61f3a9e9bda8a58eb2700ae46813284e35a150b1137bc7c2b92ac0f2e
service:
port: 8441
env:
SIGNER__AUTHORITY__BASEURL: "https://stellaops-authority:8440"
SIGNER__POE__INTROSPECTURL: "https://licensing.stage.stella-ops.internal/introspect"
SIGNER__STORAGE__MONGO__CONNECTIONSTRING: "mongodb://stellaops-stage:stellaops-stage@stellaops-mongo:27017"
attestor:
image: registry.stella-ops.org/stellaops/attestor@sha256:0534985f978b0b5d220d73c96fddd962cd9135f616811cbe3bff4666c5af568f
service:
port: 8442
env:
ATTESTOR__SIGNER__BASEURL: "https://stellaops-signer:8441"
ATTESTOR__MONGO__CONNECTIONSTRING: "mongodb://stellaops-stage:stellaops-stage@stellaops-mongo:27017"
concelier:
image: registry.stella-ops.org/stellaops/concelier@sha256:c58cdcaee1d266d68d498e41110a589dd204b487d37381096bd61ab345a867c5
service:
port: 8445
env:
CONCELIER__STORAGE__MONGO__CONNECTIONSTRING: "mongodb://stellaops-stage:stellaops-stage@stellaops-mongo:27017"
CONCELIER__STORAGE__S3__ENDPOINT: "http://stellaops-minio:9000"
CONCELIER__STORAGE__S3__ACCESSKEYID: "stellaops-stage"
CONCELIER__STORAGE__S3__SECRETACCESSKEY: "stage-minio-secret"
CONCELIER__AUTHORITY__BASEURL: "https://stellaops-authority:8440"
volumeMounts:
- name: concelier-jobs
mountPath: /var/lib/concelier/jobs
volumeClaims:
- name: concelier-jobs
claimName: stellaops-concelier-jobs
scanner-web:
image: registry.stella-ops.org/stellaops/scanner-web@sha256:14b23448c3f9586a9156370b3e8c1991b61907efa666ca37dd3aaed1e79fe3b7
service:
port: 8444
env:
SCANNER__STORAGE__MONGO__CONNECTIONSTRING: "mongodb://stellaops-stage:stellaops-stage@stellaops-mongo:27017"
SCANNER__ARTIFACTSTORE__DRIVER: "rustfs"
SCANNER__ARTIFACTSTORE__ENDPOINT: "http://stellaops-rustfs:8080/api/v1"
SCANNER__ARTIFACTSTORE__BUCKET: "scanner-artifacts"
SCANNER__ARTIFACTSTORE__TIMEOUTSECONDS: "30"
SCANNER__QUEUE__BROKER: "nats://stellaops-nats:4222"
SCANNER__EVENTS__ENABLED: "false"
SCANNER__EVENTS__DRIVER: "redis"
SCANNER__EVENTS__DSN: ""
SCANNER__EVENTS__STREAM: "stella.events"
SCANNER__EVENTS__PUBLISHTIMEOUTSECONDS: "5"
SCANNER__EVENTS__MAXSTREAMLENGTH: "10000"
SCANNER__OFFLINEKIT__ENABLED: "false"
SCANNER__OFFLINEKIT__REQUIREDSSE: "true"
SCANNER__OFFLINEKIT__REKOROFFLINEMODE: "true"
SCANNER__OFFLINEKIT__TRUSTROOTDIRECTORY: "/etc/stellaops/trust-roots"
SCANNER__OFFLINEKIT__REKORSNAPSHOTDIRECTORY: "/var/lib/stellaops/rekor-snapshot"
SCANNER_SURFACE_FS_ENDPOINT: "http://stellaops-rustfs:8080/api/v1"
SCANNER_SURFACE_CACHE_ROOT: "/var/lib/stellaops/surface"
SCANNER_SURFACE_SECRETS_PROVIDER: "kubernetes"
SCANNER_SURFACE_SECRETS_ROOT: "stellaops/scanner"
scanner-worker:
image: registry.stella-ops.org/stellaops/scanner-worker@sha256:32e25e76386eb9ea8bee0a1ad546775db9a2df989fab61ac877e351881960dab
replicas: 2
env:
SCANNER__STORAGE__MONGO__CONNECTIONSTRING: "mongodb://stellaops-stage:stellaops-stage@stellaops-mongo:27017"
SCANNER__ARTIFACTSTORE__DRIVER: "rustfs"
SCANNER__ARTIFACTSTORE__ENDPOINT: "http://stellaops-rustfs:8080/api/v1"
SCANNER__ARTIFACTSTORE__BUCKET: "scanner-artifacts"
SCANNER__ARTIFACTSTORE__TIMEOUTSECONDS: "30"
SCANNER__QUEUE__BROKER: "nats://stellaops-nats:4222"
SCANNER__EVENTS__ENABLED: "false"
SCANNER__EVENTS__DRIVER: "redis"
SCANNER__EVENTS__DSN: ""
SCANNER__EVENTS__STREAM: "stella.events"
SCANNER__EVENTS__PUBLISHTIMEOUTSECONDS: "5"
SCANNER__EVENTS__MAXSTREAMLENGTH: "10000"
SCANNER_SURFACE_FS_ENDPOINT: "http://stellaops-rustfs:8080/api/v1"
SCANNER_SURFACE_CACHE_ROOT: "/var/lib/stellaops/surface"
SCANNER_SURFACE_SECRETS_PROVIDER: "kubernetes"
SCANNER_SURFACE_SECRETS_ROOT: "stellaops/scanner"
notify-web:
image: registry.stella-ops.org/stellaops/notify-web:2025.09.2
service:
port: 8446
env:
DOTNET_ENVIRONMENT: Production
configMounts:
- name: notify-config
mountPath: /app/etc/notify.yaml
subPath: notify.yaml
configMap: notify-config
excititor:
image: registry.stella-ops.org/stellaops/excititor@sha256:59022e2016aebcef5c856d163ae705755d3f81949d41195256e935ef40a627fa
env:
EXCITITOR__CONCELIER__BASEURL: "https://stellaops-concelier:8445"
EXCITITOR__STORAGE__MONGO__CONNECTIONSTRING: "mongodb://stellaops-stage:stellaops-stage@stellaops-mongo:27017"
web-ui:
image: registry.stella-ops.org/stellaops/web-ui@sha256:10d924808c48e4353e3a241da62eb7aefe727a1d6dc830eb23a8e181013b3a23
service:
port: 8443
env:
STELLAOPS_UI__BACKEND__BASEURL: "https://stellaops-scanner-web:8444"
mongo:
class: infrastructure
image: docker.io/library/mongo@sha256:c258b26dbb7774f97f52aff52231ca5f228273a84329c5f5e451c3739457db49
service:
port: 27017
command:
- mongod
- --bind_ip_all
env:
MONGO_INITDB_ROOT_USERNAME: stellaops-stage
MONGO_INITDB_ROOT_PASSWORD: stellaops-stage
volumeMounts:
- name: mongo-data
mountPath: /data/db
volumeClaims:
- name: mongo-data
claimName: stellaops-mongo-data
minio:
class: infrastructure
image: docker.io/minio/minio@sha256:14cea493d9a34af32f524e538b8346cf79f3321eff8e708c1e2960462bd8936e
service:
port: 9000
command:
- server
- /data
- --console-address
- :9001
env:
MINIO_ROOT_USER: stellaops-stage
MINIO_ROOT_PASSWORD: stage-minio-secret
volumeMounts:
- name: minio-data
mountPath: /data
volumeClaims:
- name: minio-data
claimName: stellaops-minio-data
rustfs:
class: infrastructure
image: registry.stella-ops.org/stellaops/rustfs:2025.10.0-edge
service:
port: 8080
command:
- serve
- --listen
- 0.0.0.0:8080
- --root
- /data
env:
RUSTFS__LOG__LEVEL: info
RUSTFS__STORAGE__PATH: /data
volumeMounts:
- name: rustfs-data
mountPath: /data
volumeClaims:
- name: rustfs-data
claimName: stellaops-rustfs-data
nats:
class: infrastructure
image: docker.io/library/nats@sha256:c82559e4476289481a8a5196e675ebfe67eea81d95e5161e3e78eccfe766608e
service:
port: 4222
command:
- -js
- -sd
- /data
volumeMounts:
- name: nats-data
mountPath: /data
volumeClaims:
- name: nats-data
claimName: stellaops-nats-data

View File

@@ -0,0 +1,284 @@
global:
release:
version: ""
channel: ""
manifestSha256: ""
profile: ""
image:
pullPolicy: IfNotPresent
labels: {}
migrations:
enabled: false
jobs: []
networkPolicy:
enabled: false
ingressPort: 80
egressPort: 443
ingressNamespaces: {}
ingressPods: {}
egressNamespaces: {}
egressPods: {}
ingress:
enabled: false
className: nginx
annotations: {}
hosts: []
tls: []
externalSecrets:
enabled: false
secrets: []
prometheus:
enabled: false
path: /metrics
port: 8080
scheme: http
hpa:
enabled: false
minReplicas: 1
maxReplicas: 3
cpu:
targetPercentage: 75
memory:
targetPercentage: null
# Surface.Env configuration for Scanner/Zastava components
# See docs/modules/scanner/design/surface-env.md for details
surface:
# Surface.FS storage configuration
fs:
# Base URI for Surface.FS / RustFS / S3-compatible store (required)
endpoint: ""
# Bucket/container for manifests and artefacts
bucket: "surface-cache"
# Optional region for S3-compatible stores (AWS/GCS)
region: ""
# Local cache configuration
cache:
# Local directory for warm caches
root: "/var/lib/stellaops/surface"
# Soft limit for on-disk cache usage in MB (64-262144)
quotaMb: 4096
# Enable manifest prefetch threads
prefetchEnabled: false
# Tenant configuration
tenant: "default"
# Comma-separated feature switches
features: ""
# TLS configuration for client authentication
tls:
# Path to PEM/PKCS#12 certificate file
certPath: ""
# Optional private key path when cert/key stored separately
keyPath: ""
# Secret name containing TLS cert/key
secretName: ""
# Secrets provider configuration
secrets:
# Provider ID: kubernetes, file, inline
provider: "kubernetes"
# Kubernetes namespace for secrets provider
namespace: ""
# Path or base for file provider
root: ""
# Optional fallback provider ID
fallbackProvider: ""
# Allow inline secrets (disable in production)
allowInline: false
telemetry:
collector:
enabled: false
replicas: 1
image: otel/opentelemetry-collector:0.105.0
requireClientCert: true
defaultTenant: unknown
logLevel: info
tls:
secretName: ""
certPath: /etc/otel/tls/tls.crt
keyPath: /etc/otel/tls/tls.key
caPath: /etc/otel/tls/ca.crt
items:
- key: tls.crt
path: tls.crt
- key: tls.key
path: tls.key
- key: ca.crt
path: ca.crt
service:
grpcPort: 4317
httpPort: 4318
metricsPort: 9464
resources: {}
configMaps:
# Surface.Env environment variables for Scanner/Zastava components
surface-env:
data:
SCANNER_SURFACE_FS_ENDPOINT: "{{ .Values.surface.fs.endpoint }}"
SCANNER_SURFACE_FS_BUCKET: "{{ .Values.surface.fs.bucket }}"
SCANNER_SURFACE_FS_REGION: "{{ .Values.surface.fs.region }}"
SCANNER_SURFACE_CACHE_ROOT: "{{ .Values.surface.cache.root }}"
SCANNER_SURFACE_CACHE_QUOTA_MB: "{{ .Values.surface.cache.quotaMb }}"
SCANNER_SURFACE_PREFETCH_ENABLED: "{{ .Values.surface.cache.prefetchEnabled }}"
SCANNER_SURFACE_TENANT: "{{ .Values.surface.tenant }}"
SCANNER_SURFACE_FEATURES: "{{ .Values.surface.features }}"
SCANNER_SURFACE_TLS_CERT_PATH: "{{ .Values.surface.tls.certPath }}"
SCANNER_SURFACE_TLS_KEY_PATH: "{{ .Values.surface.tls.keyPath }}"
SCANNER_SURFACE_SECRETS_PROVIDER: "{{ .Values.surface.secrets.provider }}"
SCANNER_SURFACE_SECRETS_NAMESPACE: "{{ .Values.surface.secrets.namespace }}"
SCANNER_SURFACE_SECRETS_ROOT: "{{ .Values.surface.secrets.root }}"
SCANNER_SURFACE_SECRETS_FALLBACK_PROVIDER: "{{ .Values.surface.secrets.fallbackProvider }}"
SCANNER_SURFACE_SECRETS_ALLOW_INLINE: "{{ .Values.surface.secrets.allowInline }}"
# Zastava consumers inherit Scanner defaults but can be overridden via ZASTAVA_* envs
ZASTAVA_SURFACE_FS_ENDPOINT: "{{ .Values.surface.fs.endpoint }}"
ZASTAVA_SURFACE_FS_BUCKET: "{{ .Values.surface.fs.bucket }}"
ZASTAVA_SURFACE_FS_REGION: "{{ .Values.surface.fs.region }}"
ZASTAVA_SURFACE_CACHE_ROOT: "{{ .Values.surface.cache.root }}"
ZASTAVA_SURFACE_CACHE_QUOTA_MB: "{{ .Values.surface.cache.quotaMb }}"
ZASTAVA_SURFACE_PREFETCH_ENABLED: "{{ .Values.surface.cache.prefetchEnabled }}"
ZASTAVA_SURFACE_TENANT: "{{ .Values.surface.tenant }}"
ZASTAVA_SURFACE_FEATURES: "{{ .Values.surface.features }}"
ZASTAVA_SURFACE_TLS_CERT_PATH: "{{ .Values.surface.tls.certPath }}"
ZASTAVA_SURFACE_TLS_KEY_PATH: "{{ .Values.surface.tls.keyPath }}"
ZASTAVA_SURFACE_SECRETS_PROVIDER: "{{ .Values.surface.secrets.provider }}"
ZASTAVA_SURFACE_SECRETS_NAMESPACE: "{{ .Values.surface.secrets.namespace }}"
ZASTAVA_SURFACE_SECRETS_ROOT: "{{ .Values.surface.secrets.root }}"
ZASTAVA_SURFACE_SECRETS_FALLBACK_PROVIDER: "{{ .Values.surface.secrets.fallbackProvider }}"
ZASTAVA_SURFACE_SECRETS_ALLOW_INLINE: "{{ .Values.surface.secrets.allowInline }}"
issuer-directory-config:
data:
issuer-directory.yaml: |
IssuerDirectory:
telemetry:
minimumLogLevel: Information
authority:
enabled: true
issuer: https://authority.svc.cluster.local/realms/stellaops
requireHttpsMetadata: true
audiences:
- stellaops-platform
readScope: issuer-directory:read
writeScope: issuer-directory:write
adminScope: issuer-directory:admin
tenantHeader: X-StellaOps-Tenant
seedCsafPublishers: true
csafSeedPath: data/csaf-publishers.json
Mongo:
connectionString: mongodb://mongo:27017
database: issuer-directory
issuersCollection: issuers
issuerKeysCollection: issuer_keys
issuerTrustCollection: issuer_trust_overrides
auditCollection: issuer_audit
policy-engine-activation:
data:
STELLAOPS_POLICY_ENGINE__ACTIVATION__FORCETWOPERSONAPPROVAL: "false"
STELLAOPS_POLICY_ENGINE__ACTIVATION__DEFAULTREQUIRESTWOPERSONAPPROVAL: "false"
STELLAOPS_POLICY_ENGINE__ACTIVATION__EMITAUDITLOGS: "true"
services:
issuer-directory:
image: registry.stella-ops.org/stellaops/issuer-directory-web:2025.10.0-edge
replicas: 1
configMounts:
- name: issuer-directory-config
configMap: issuer-directory-config
mountPath: /etc/issuer-directory.yaml
subPath: issuer-directory.yaml
envFrom:
- secretRef:
name: issuer-directory-secrets
env:
ISSUERDIRECTORY__CONFIG: /etc/issuer-directory.yaml
ISSUERDIRECTORY__AUTHORITY__BASEURL: https://authority:8440
ISSUERDIRECTORY__SEEDCSAFPUBLISHERS: "true"
ports:
- containerPort: 8080
service:
port: 8080
readinessProbe:
httpGet:
path: /health/live
port: 8080
initialDelaySeconds: 5
periodSeconds: 10
livenessProbe:
httpGet:
path: /health/live
port: 8080
initialDelaySeconds: 10
periodSeconds: 20
scheduler-worker:
image: registry.stella-ops.org/stellaops/scheduler-worker:2025.10.0-edge
replicas: 1
command:
- dotnet
- StellaOps.Scheduler.Worker.Host.dll
env:
SCHEDULER__QUEUE__KIND: Nats
SCHEDULER__QUEUE__NATS__URL: nats://nats:4222
SCHEDULER__STORAGE__CONNECTIONSTRING: mongodb://scheduler-mongo:27017
SCHEDULER__STORAGE__DATABASE: stellaops_scheduler
SCHEDULER__WORKER__RUNNER__SCANNER__BASEADDRESS: http://scanner-web:8444
advisory-ai-web:
image: registry.stella-ops.org/stellaops/advisory-ai-web:2025.10.0-edge
service:
port: 8448
env:
ADVISORYAI__AdvisoryAI__SbomBaseAddress: http://scanner-web:8444
ADVISORYAI__AdvisoryAI__Queue__DirectoryPath: /var/lib/advisory-ai/queue
ADVISORYAI__AdvisoryAI__Storage__PlanCacheDirectory: /var/lib/advisory-ai/plans
ADVISORYAI__AdvisoryAI__Storage__OutputDirectory: /var/lib/advisory-ai/outputs
ADVISORYAI__AdvisoryAI__Inference__Mode: Local
ADVISORYAI__AdvisoryAI__Inference__Remote__BaseAddress: ""
ADVISORYAI__AdvisoryAI__Inference__Remote__ApiKey: ""
volumeMounts:
- name: advisory-ai-data
mountPath: /var/lib/advisory-ai
volumeClaims:
- name: advisory-ai-data
claimName: stellaops-advisory-ai-data
advisory-ai-worker:
image: registry.stella-ops.org/stellaops/advisory-ai-worker:2025.10.0-edge
env:
ADVISORYAI__AdvisoryAI__SbomBaseAddress: http://scanner-web:8444
ADVISORYAI__AdvisoryAI__Queue__DirectoryPath: /var/lib/advisory-ai/queue
ADVISORYAI__AdvisoryAI__Storage__PlanCacheDirectory: /var/lib/advisory-ai/plans
ADVISORYAI__AdvisoryAI__Storage__OutputDirectory: /var/lib/advisory-ai/outputs
ADVISORYAI__AdvisoryAI__Inference__Mode: Local
ADVISORYAI__AdvisoryAI__Inference__Remote__BaseAddress: ""
ADVISORYAI__AdvisoryAI__Inference__Remote__ApiKey: ""
volumeMounts:
- name: advisory-ai-data
mountPath: /var/lib/advisory-ai
volumeClaims:
- name: advisory-ai-data
claimName: stellaops-advisory-ai-data
mock:
enabled: false
orchestrator:
image: registry.stella-ops.org/stellaops/orchestrator@sha256:97f12856ce870bafd3328bda86833bcccbf56d255941d804966b5557f6610119
policyRegistry:
image: registry.stella-ops.org/stellaops/policy-registry@sha256:c6cad8055e9827ebcbebb6ad4d6866dce4b83a0a49b0a8a6500b736a5cb26fa7
packsRegistry:
image: registry.stella-ops.org/stellaops/packs-registry@sha256:1f5e9416c4dc608594ad6fad87c24d72134427f899c192b494e22b268499c791
taskRunner:
image: registry.stella-ops.org/stellaops/task-runner@sha256:eb5ad992b49a41554f41516be1a6afcfa6522faf2111c08ff2b3664ad2fc954b
vexLens:
image: registry.stella-ops.org/stellaops/vex-lens@sha256:b44e63ecfeebc345a70c073c1ce5ace709c58be0ffaad0e2862758aeee3092fb
issuerDirectory:
image: registry.stella-ops.org/stellaops/issuer-directory@sha256:67e8ef02c97d3156741e857756994888f30c373ace8e84886762edba9dc51914
findingsLedger:
image: registry.stella-ops.org/stellaops/findings-ledger@sha256:71d4c361ba8b2f8b69d652597bc3f2efc8a64f93fab854ce25272a88506df49c
vulnExplorerApi:
image: registry.stella-ops.org/stellaops/vuln-explorer-api@sha256:7fc7e43a05cbeb0106ce7d4d634612e83de6fdc119aaab754a71c1d60b82841d