CD/CD consolidation
This commit is contained in:
@@ -1,74 +0,0 @@
|
||||
# Deployment Profiles
|
||||
|
||||
This directory contains deterministic deployment bundles for the core Stella Ops stack. All manifests reference immutable image digests and map 1:1 to the release manifests stored under `deploy/releases/`.
|
||||
|
||||
## Structure
|
||||
|
||||
- `releases/` – canonical release manifests (edge, stable, airgap) used to source image digests.
|
||||
- `compose/` – Docker Compose bundles for dev/stage/airgap targets plus `.env` seed files.
|
||||
- `compose/docker-compose.mirror.yaml` – managed mirror bundle for `*.stella-ops.org` with gateway cache and multi-tenant auth.
|
||||
- `compose/docker-compose.telemetry.yaml` – optional OpenTelemetry collector overlay (mutual TLS, OTLP pipelines).
|
||||
- `compose/docker-compose.telemetry-storage.yaml` – optional Prometheus/Tempo/Loki stack for observability backends.
|
||||
- `helm/stellaops/` – multi-profile Helm chart with values files for dev/stage/airgap.
|
||||
- `helm/stellaops/INSTALL.md` – install/runbook for prod and airgap profiles with digest pins.
|
||||
- `telemetry/` – shared OpenTelemetry collector configuration and certificate artefacts (generated via tooling).
|
||||
- `tools/validate-profiles.sh` – helper that runs `docker compose config` and `helm lint/template` for every profile.
|
||||
|
||||
## Workflow
|
||||
|
||||
1. Update or add a release manifest under `releases/` with the new digests.
|
||||
2. Mirror the digests into the Compose and Helm profiles that correspond to that channel.
|
||||
3. Run `deploy/tools/validate-profiles.sh` (requires Docker CLI and Helm) to ensure the bundles lint and template cleanly.
|
||||
4. If telemetry ingest is required for the release, generate development certificates using
|
||||
`./ops/devops/telemetry/generate_dev_tls.sh` and run the collector smoke test with
|
||||
`python ./ops/devops/telemetry/smoke_otel_collector.py` to verify the OTLP endpoints.
|
||||
5. Commit the change alongside any documentation updates (e.g. install guide cross-links).
|
||||
|
||||
Maintaining the digest linkage keeps offline/air-gapped installs reproducible and avoids tag drift between environments.
|
||||
|
||||
### Surface.Env rollout warnings
|
||||
|
||||
- Compose (`deploy/compose/env/*.env.example`) and Helm (`deploy/helm/stellaops/values-*.yaml`) now seed `SCANNER_SURFACE_*` _and_ `ZASTAVA_SURFACE_*` variables so Scanner Worker/WebService and Zastava Observer/Webhook resolve cache roots, Surface.FS endpoints, and secrets providers through `StellaOps.Scanner.Surface.Env`.
|
||||
- During rollout, watch for structured log messages (and readiness output) prefixed with `surface.env.`—for example, `surface.env.cache_root_missing`, `surface.env.endpoint_unreachable`, or `surface.env.secrets_provider_invalid`.
|
||||
- Treat these warnings as deployment blockers: update the endpoint/cache/secrets values or permissions before promoting the environment, otherwise workers will fail fast at startup.
|
||||
- Air-gapped bundles default the secrets provider to `file` with `/etc/stellaops/secrets`; connected clusters default to `kubernetes`. Adjust the provider/root pair if your secrets manager differs.
|
||||
- Secret provisioning workflows for Kubernetes/Compose/Offline Kit are documented in `ops/devops/secrets/surface-secrets-provisioning.md`; follow that for `Surface.Secrets` handles and RBAC/permissions.
|
||||
|
||||
### Mongo2Go OpenSSL prerequisites
|
||||
|
||||
- Linux runners that execute Mongo2Go-backed suites (Excititor, Scheduler, Graph, etc.) must expose OpenSSL 1.1 (`libcrypto.so.1.1`, `libssl.so.1.1`). The canonical copies live under `tests/native/openssl-1.1/linux-x64`.
|
||||
- Export `LD_LIBRARY_PATH="$(git rev-parse --show-toplevel)/tests/native/openssl-1.1/linux-x64:${LD_LIBRARY_PATH:-}"` before invoking `dotnet test`. Example:\
|
||||
`LD_LIBRARY_PATH="$(pwd)/tests/native/openssl-1.1/linux-x64" dotnet test src/Excititor/__Tests/StellaOps.Excititor.WebService.Tests/StellaOps.Excititor.WebService.Tests.csproj --nologo`.
|
||||
- CI agents or Dockerfiles that host these tests should either mount the directory into the container or copy the two `.so` files into a directory that is already on the runtime library path.
|
||||
|
||||
### Additional tooling
|
||||
|
||||
- `deploy/tools/check-channel-alignment.py` – verifies that Helm/Compose profiles reference the exact images listed in a release manifest. Run it for each channel before promoting a release.
|
||||
- `ops/devops/telemetry/generate_dev_tls.sh` – produces local CA/server/client certificates for Compose-based collector testing.
|
||||
- `ops/devops/telemetry/smoke_otel_collector.py` – sends OTLP traffic and asserts the collector accepted traces, metrics, and logs.
|
||||
- `ops/devops/telemetry/package_offline_bundle.py` – packages telemetry assets (config/Helm/Compose) into a signed tarball for air-gapped installs.
|
||||
- `docs/modules/devops/runbooks/deployment-upgrade.md` – end-to-end instructions for upgrade, rollback, and channel promotion workflows (Helm + Compose).
|
||||
|
||||
### Tenancy observability & chaos (DEVOPS-TEN-49-001)
|
||||
|
||||
- Import `ops/devops/tenant/recording-rules.yaml` and `ops/devops/tenant/alerts.yaml` into your Prometheus rule groups.
|
||||
- Add Grafana dashboard `ops/devops/tenant/dashboards/tenant-audit.json` (folder `StellaOps / Tenancy`) to watch latency/error/auth cache ratios per tenant/service.
|
||||
- Run the multi-tenant k6 harness `ops/devops/tenant/k6-tenant-load.js` to hit 5k concurrent tenant-labelled requests (defaults to read/write 90/10, header `X-StellaOps-Tenant`).
|
||||
- Execute JWKS outage chaos via `ops/devops/tenant/jwks-chaos.sh` on an isolated agent with sudo/iptables; watch alerts `jwks_cache_miss_spike` and `tenant_auth_failures_spike` while load is active.
|
||||
|
||||
## CI smoke checks
|
||||
|
||||
The `.gitea/workflows/build-test-deploy.yml` pipeline includes a `notify-smoke` stage that validates scanner event propagation after staging deployments. Configure the following repository secrets (or environment-level secrets) so the job can connect to Redis and the Notify API:
|
||||
|
||||
- `NOTIFY_SMOKE_REDIS_DSN` – Redis connection string (`redis://user:pass@host:port/db`).
|
||||
- `NOTIFY_SMOKE_NOTIFY_BASEURL` – Base URL for the staging Notify WebService (e.g. `https://notify.stage.stella-ops.internal`).
|
||||
- `NOTIFY_SMOKE_NOTIFY_TOKEN` – OAuth bearer token (service account) with permission to read deliveries.
|
||||
- `NOTIFY_SMOKE_NOTIFY_TENANT` – Tenant identifier used for the smoke validation requests.
|
||||
- *(Optional)* `NOTIFY_SMOKE_NOTIFY_TENANT_HEADER` – Override for the tenant header name (defaults to `X-StellaOps-Tenant`).
|
||||
|
||||
Define the following repository variables (or secrets) to drive the assertions performed by the smoke check:
|
||||
|
||||
- `NOTIFY_SMOKE_EXPECT_KINDS` – Comma-separated event kinds the checker must observe (for example `scanner.report.ready,scanner.scan.completed`).
|
||||
- `NOTIFY_SMOKE_LOOKBACK_MINUTES` – Time window (in minutes) used when scanning the Redis stream for recent events (for example `30`).
|
||||
|
||||
All of the above values are required—the workflow fails fast with a descriptive error if any are missing or empty. Provide the variables at the organisation or repository scope before enabling the smoke stage.
|
||||
@@ -1,181 +0,0 @@
|
||||
# Zastava Agent Ansible Deployment
|
||||
|
||||
Ansible playbook for deploying StellaOps Zastava Agent on VM/bare-metal hosts.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- Ansible 2.10 or later
|
||||
- Target hosts must have:
|
||||
- Docker installed and running
|
||||
- SSH access with sudo privileges
|
||||
- systemd as init system
|
||||
- Internet access (for downloading agent binaries) OR local artifact repository
|
||||
|
||||
## Quick Start
|
||||
|
||||
1. **Create inventory file:**
|
||||
|
||||
```bash
|
||||
cp inventory.yml.sample inventory.yml
|
||||
```
|
||||
|
||||
2. **Edit inventory with your hosts and configuration:**
|
||||
|
||||
```yaml
|
||||
zastava_agents:
|
||||
hosts:
|
||||
your-host:
|
||||
ansible_host: 192.168.1.100
|
||||
ansible_user: ubuntu
|
||||
vars:
|
||||
zastava_tenant: your-tenant
|
||||
scanner_backend_url: https://scanner.internal
|
||||
```
|
||||
|
||||
3. **Run the playbook:**
|
||||
|
||||
```bash
|
||||
ansible-playbook -i inventory.yml zastava-agent.yml
|
||||
```
|
||||
|
||||
## Configuration Variables
|
||||
|
||||
### Required Variables
|
||||
|
||||
| Variable | Description |
|
||||
|----------|-------------|
|
||||
| `zastava_tenant` | Tenant identifier for multi-tenancy isolation |
|
||||
| `scanner_backend_url` | URL of the Scanner backend service |
|
||||
|
||||
### Optional Variables
|
||||
|
||||
| Variable | Default | Description |
|
||||
|----------|---------|-------------|
|
||||
| `zastava_version` | `latest` | Agent version to deploy |
|
||||
| `zastava_node_name` | hostname | Override node name in events |
|
||||
| `zastava_health_port` | `8080` | Health check HTTP port |
|
||||
| `docker_socket` | `/var/run/docker.sock` | Docker socket path |
|
||||
| `zastava_log_level` | `Information` | Serilog log level |
|
||||
| `scanner_backend_insecure` | `false` | Allow HTTP backend (NOT for production) |
|
||||
| `download_base_url` | `https://releases.stellaops.org` | Base URL for agent downloads |
|
||||
|
||||
### Advanced Variables
|
||||
|
||||
| Variable | Description |
|
||||
|----------|-------------|
|
||||
| `zastava_extra_env` | Dictionary of additional environment variables |
|
||||
|
||||
## Directory Structure
|
||||
|
||||
After deployment, the agent is installed with the following structure:
|
||||
|
||||
```
|
||||
/opt/stellaops/zastava-agent/ # Agent binaries
|
||||
/etc/stellaops/zastava-agent.env # Environment configuration
|
||||
/var/lib/zastava-agent/ # Data directory
|
||||
/var/lib/zastava-agent/runtime-events/ # Event buffer (disk-backed)
|
||||
/etc/systemd/system/zastava-agent.service # systemd unit
|
||||
```
|
||||
|
||||
## Post-Deployment Verification
|
||||
|
||||
### Check Service Status
|
||||
|
||||
```bash
|
||||
systemctl status zastava-agent
|
||||
```
|
||||
|
||||
### View Logs
|
||||
|
||||
```bash
|
||||
journalctl -u zastava-agent -f
|
||||
```
|
||||
|
||||
### Health Endpoints
|
||||
|
||||
| Endpoint | Description |
|
||||
|----------|-------------|
|
||||
| `/healthz` | Liveness probe - agent is running |
|
||||
| `/readyz` | Readiness probe - agent can process events |
|
||||
| `/livez` | Alias for liveness probe |
|
||||
|
||||
```bash
|
||||
curl http://localhost:8080/healthz
|
||||
curl http://localhost:8080/readyz
|
||||
```
|
||||
|
||||
## Air-Gapped Deployment
|
||||
|
||||
For air-gapped environments:
|
||||
|
||||
1. Download agent tarball to a local artifact server
|
||||
2. Set `download_base_url` to your local server:
|
||||
|
||||
```yaml
|
||||
download_base_url: https://artifacts.internal/stellaops
|
||||
```
|
||||
|
||||
3. Ensure the URL structure matches:
|
||||
`{download_base_url}/zastava-agent/{version}/zastava-agent-linux-{arch}.tar.gz`
|
||||
|
||||
## Security Notes
|
||||
|
||||
### Docker Socket Access
|
||||
|
||||
The agent requires read access to the Docker socket to monitor container events.
|
||||
The service runs as the `zastava-agent` user in the `docker` group.
|
||||
|
||||
See `docs/modules/zastava/operations/docker-socket-permissions.md` for security
|
||||
considerations and alternative configurations.
|
||||
|
||||
### systemd Hardening
|
||||
|
||||
The service unit includes security hardening:
|
||||
|
||||
- `NoNewPrivileges=true` - Prevent privilege escalation
|
||||
- `ProtectSystem=strict` - Read-only system directories
|
||||
- `PrivateTmp=true` - Isolated /tmp
|
||||
- `ProtectKernelTunables=true` - No kernel parameter modification
|
||||
- Resource limits on file descriptors and memory
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Agent Won't Start
|
||||
|
||||
1. Check Docker service: `systemctl status docker`
|
||||
2. Verify Docker socket permissions: `ls -la /var/run/docker.sock`
|
||||
3. Check agent logs: `journalctl -u zastava-agent -e`
|
||||
|
||||
### Cannot Connect to Backend
|
||||
|
||||
1. Verify network connectivity: `curl -I ${scanner_backend_url}/healthz`
|
||||
2. Check TLS certificates if using HTTPS
|
||||
3. Ensure firewall allows outbound connections
|
||||
|
||||
### Events Not Being Sent
|
||||
|
||||
1. Check event buffer directory permissions
|
||||
2. Verify health endpoint returns healthy: `curl localhost:8080/readyz`
|
||||
3. Check agent logs for connection errors
|
||||
|
||||
## Uninstallation
|
||||
|
||||
To remove the agent:
|
||||
|
||||
```bash
|
||||
# Stop and disable service
|
||||
sudo systemctl stop zastava-agent
|
||||
sudo systemctl disable zastava-agent
|
||||
|
||||
# Remove files
|
||||
sudo rm -rf /opt/stellaops/zastava-agent
|
||||
sudo rm -f /etc/stellaops/zastava-agent.env
|
||||
sudo rm -f /etc/systemd/system/zastava-agent.service
|
||||
sudo rm -rf /var/lib/zastava-agent
|
||||
|
||||
# Remove user
|
||||
sudo userdel zastava-agent
|
||||
|
||||
# Reload systemd
|
||||
sudo systemctl daemon-reload
|
||||
```
|
||||
@@ -1,58 +0,0 @@
|
||||
[Unit]
|
||||
Description=StellaOps Zastava Agent - Container Runtime Monitor
|
||||
Documentation=https://docs.stellaops.org/zastava/agent/
|
||||
After=network-online.target docker.service containerd.service
|
||||
Wants=network-online.target
|
||||
Requires=docker.service
|
||||
|
||||
[Service]
|
||||
Type=notify
|
||||
ExecStart=/opt/stellaops/zastava-agent/StellaOps.Zastava.Agent
|
||||
WorkingDirectory=/opt/stellaops/zastava-agent
|
||||
Restart=always
|
||||
RestartSec=5
|
||||
|
||||
# Environment configuration
|
||||
EnvironmentFile=-/etc/stellaops/zastava-agent.env
|
||||
Environment=DOTNET_ENVIRONMENT=Production
|
||||
Environment=ASPNETCORE_ENVIRONMENT=Production
|
||||
|
||||
# User and permissions
|
||||
User=zastava-agent
|
||||
Group=docker
|
||||
|
||||
# Security hardening
|
||||
NoNewPrivileges=true
|
||||
ProtectSystem=strict
|
||||
ProtectHome=true
|
||||
PrivateTmp=true
|
||||
PrivateDevices=true
|
||||
ProtectKernelTunables=true
|
||||
ProtectKernelModules=true
|
||||
ProtectControlGroups=true
|
||||
RestrictRealtime=true
|
||||
RestrictSUIDSGID=true
|
||||
|
||||
# Allow read access to Docker socket
|
||||
ReadWritePaths=/var/run/docker.sock
|
||||
ReadWritePaths=/var/lib/zastava-agent
|
||||
|
||||
# Capabilities
|
||||
CapabilityBoundingSet=
|
||||
AmbientCapabilities=
|
||||
|
||||
# Resource limits
|
||||
LimitNOFILE=65536
|
||||
LimitNPROC=4096
|
||||
MemoryMax=512M
|
||||
|
||||
# Logging
|
||||
StandardOutput=journal
|
||||
StandardError=journal
|
||||
SyslogIdentifier=zastava-agent
|
||||
|
||||
# Watchdog (5 minute timeout)
|
||||
WatchdogSec=300
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
@@ -1,46 +0,0 @@
|
||||
---
|
||||
# Sample Ansible Inventory for Zastava Agent Deployment
|
||||
#
|
||||
# Copy this file to inventory.yml and customize for your environment.
|
||||
# Then run: ansible-playbook -i inventory.yml zastava-agent.yml
|
||||
|
||||
all:
|
||||
children:
|
||||
zastava_agents:
|
||||
hosts:
|
||||
# Add your VM/bare-metal hosts here
|
||||
vm-node-1:
|
||||
ansible_host: 192.168.1.101
|
||||
ansible_user: ubuntu
|
||||
vm-node-2:
|
||||
ansible_host: 192.168.1.102
|
||||
ansible_user: ubuntu
|
||||
# Example with SSH key
|
||||
vm-node-3:
|
||||
ansible_host: 192.168.1.103
|
||||
ansible_user: root
|
||||
ansible_ssh_private_key_file: ~/.ssh/stellaops_key
|
||||
|
||||
vars:
|
||||
# Required: Set these for your environment
|
||||
zastava_tenant: my-tenant
|
||||
scanner_backend_url: https://scanner.example.com
|
||||
|
||||
# Optional: Override node name per host
|
||||
# zastava_node_name: custom-node-name
|
||||
|
||||
# Optional: Change health check port
|
||||
# zastava_health_port: 8080
|
||||
|
||||
# Optional: Custom Docker socket path
|
||||
# docker_socket: /var/run/docker.sock
|
||||
|
||||
# Optional: Set log level (Verbose, Debug, Information, Warning, Error)
|
||||
# zastava_log_level: Information
|
||||
|
||||
# Optional: Allow insecure HTTP (NOT for production)
|
||||
# scanner_backend_insecure: false
|
||||
|
||||
# Optional: Additional environment variables
|
||||
# zastava_extra_env:
|
||||
# CUSTOM_VAR: custom_value
|
||||
@@ -1,40 +0,0 @@
|
||||
# StellaOps Zastava Agent Configuration
|
||||
# Managed by Ansible - Do not edit manually
|
||||
# Generated: {{ ansible_date_time.iso8601 }}
|
||||
|
||||
# Tenant identifier for multi-tenancy
|
||||
ZASTAVA_TENANT={{ zastava_tenant }}
|
||||
|
||||
# Scanner backend URL
|
||||
ZASTAVA_AGENT__Backend__BaseAddress={{ scanner_backend_url }}
|
||||
|
||||
{% if zastava_node_name is defined %}
|
||||
# Node name override
|
||||
ZASTAVA_NODE_NAME={{ zastava_node_name }}
|
||||
{% endif %}
|
||||
|
||||
# Docker socket endpoint
|
||||
ZASTAVA_AGENT__DockerEndpoint=unix://{{ docker_socket }}
|
||||
|
||||
# Event buffer path
|
||||
ZASTAVA_AGENT__EventBufferPath={{ zastava_data_dir }}/runtime-events
|
||||
|
||||
# Health check port
|
||||
ZASTAVA_AGENT__HealthCheck__Port={{ zastava_health_port }}
|
||||
|
||||
{% if scanner_backend_insecure | default(false) | bool %}
|
||||
# WARNING: Insecure HTTP backend enabled
|
||||
ZASTAVA_AGENT__Backend__AllowInsecureHttp=true
|
||||
{% endif %}
|
||||
|
||||
{% if zastava_log_level is defined %}
|
||||
# Logging level
|
||||
Serilog__MinimumLevel__Default={{ zastava_log_level }}
|
||||
{% endif %}
|
||||
|
||||
{% if zastava_extra_env is defined %}
|
||||
# Additional environment variables
|
||||
{% for key, value in zastava_extra_env.items() %}
|
||||
{{ key }}={{ value }}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
@@ -1,232 +0,0 @@
|
||||
---
|
||||
# Ansible Playbook for Zastava Agent VM/Bare-Metal Deployment
|
||||
#
|
||||
# Requirements:
|
||||
# - Target hosts must have Docker installed and running
|
||||
# - Ansible 2.10+ with community.docker collection
|
||||
#
|
||||
# Usage:
|
||||
# ansible-playbook -i inventory.yml zastava-agent.yml \
|
||||
# -e zastava_tenant=my-tenant \
|
||||
# -e scanner_backend_url=https://scanner.internal
|
||||
#
|
||||
# Variables (can be set in inventory or via -e):
|
||||
# zastava_tenant: Tenant identifier (required)
|
||||
# scanner_backend_url: Scanner backend URL (required)
|
||||
# zastava_version: Version to deploy (default: latest)
|
||||
# zastava_node_name: Override node name (default: hostname)
|
||||
# zastava_health_port: Health check port (default: 8080)
|
||||
# docker_socket: Docker socket path (default: /var/run/docker.sock)
|
||||
|
||||
- name: Deploy StellaOps Zastava Agent
|
||||
hosts: zastava_agents
|
||||
become: true
|
||||
|
||||
vars:
|
||||
zastava_version: "{{ zastava_version | default('latest') }}"
|
||||
zastava_install_dir: /opt/stellaops/zastava-agent
|
||||
zastava_config_dir: /etc/stellaops
|
||||
zastava_data_dir: /var/lib/zastava-agent
|
||||
zastava_user: zastava-agent
|
||||
zastava_group: docker
|
||||
zastava_health_port: "{{ zastava_health_port | default(8080) }}"
|
||||
docker_socket: "{{ docker_socket | default('/var/run/docker.sock') }}"
|
||||
download_base_url: "{{ download_base_url | default('https://releases.stellaops.org') }}"
|
||||
|
||||
pre_tasks:
|
||||
- name: Validate required variables
|
||||
ansible.builtin.assert:
|
||||
that:
|
||||
- zastava_tenant is defined and zastava_tenant | length > 0
|
||||
- scanner_backend_url is defined and scanner_backend_url | length > 0
|
||||
fail_msg: |
|
||||
Required variables not set.
|
||||
Please provide:
|
||||
- zastava_tenant: Your tenant identifier
|
||||
- scanner_backend_url: Scanner backend URL
|
||||
|
||||
- name: Check Docker service is running
|
||||
ansible.builtin.systemd:
|
||||
name: docker
|
||||
state: started
|
||||
check_mode: true
|
||||
register: docker_status
|
||||
|
||||
- name: Fail if Docker is not available
|
||||
ansible.builtin.fail:
|
||||
msg: "Docker service is not running on {{ inventory_hostname }}"
|
||||
when: docker_status.status.ActiveState != 'active'
|
||||
|
||||
tasks:
|
||||
# =========================================================================
|
||||
# User and Directory Setup
|
||||
# =========================================================================
|
||||
|
||||
- name: Create zastava-agent system user
|
||||
ansible.builtin.user:
|
||||
name: "{{ zastava_user }}"
|
||||
comment: StellaOps Zastava Agent
|
||||
system: true
|
||||
shell: /usr/sbin/nologin
|
||||
groups: "{{ zastava_group }}"
|
||||
create_home: false
|
||||
state: present
|
||||
|
||||
- name: Create installation directory
|
||||
ansible.builtin.file:
|
||||
path: "{{ zastava_install_dir }}"
|
||||
state: directory
|
||||
owner: "{{ zastava_user }}"
|
||||
group: "{{ zastava_group }}"
|
||||
mode: '0755'
|
||||
|
||||
- name: Create configuration directory
|
||||
ansible.builtin.file:
|
||||
path: "{{ zastava_config_dir }}"
|
||||
state: directory
|
||||
owner: root
|
||||
group: root
|
||||
mode: '0755'
|
||||
|
||||
- name: Create data directory
|
||||
ansible.builtin.file:
|
||||
path: "{{ zastava_data_dir }}"
|
||||
state: directory
|
||||
owner: "{{ zastava_user }}"
|
||||
group: "{{ zastava_group }}"
|
||||
mode: '0750'
|
||||
|
||||
- name: Create event buffer directory
|
||||
ansible.builtin.file:
|
||||
path: "{{ zastava_data_dir }}/runtime-events"
|
||||
state: directory
|
||||
owner: "{{ zastava_user }}"
|
||||
group: "{{ zastava_group }}"
|
||||
mode: '0750'
|
||||
|
||||
# =========================================================================
|
||||
# Download and Install Agent
|
||||
# =========================================================================
|
||||
|
||||
- name: Determine architecture
|
||||
ansible.builtin.set_fact:
|
||||
arch_suffix: "{{ 'x64' if ansible_architecture == 'x86_64' else 'arm64' if ansible_architecture == 'aarch64' else ansible_architecture }}"
|
||||
|
||||
- name: Download Zastava Agent binary
|
||||
ansible.builtin.get_url:
|
||||
url: "{{ download_base_url }}/zastava-agent/{{ zastava_version }}/zastava-agent-linux-{{ arch_suffix }}.tar.gz"
|
||||
dest: /tmp/zastava-agent.tar.gz
|
||||
mode: '0644'
|
||||
register: download_result
|
||||
retries: 3
|
||||
delay: 5
|
||||
|
||||
- name: Extract Zastava Agent
|
||||
ansible.builtin.unarchive:
|
||||
src: /tmp/zastava-agent.tar.gz
|
||||
dest: "{{ zastava_install_dir }}"
|
||||
remote_src: true
|
||||
owner: "{{ zastava_user }}"
|
||||
group: "{{ zastava_group }}"
|
||||
extra_opts:
|
||||
- --strip-components=1
|
||||
notify: Restart zastava-agent
|
||||
|
||||
- name: Make agent binary executable
|
||||
ansible.builtin.file:
|
||||
path: "{{ zastava_install_dir }}/StellaOps.Zastava.Agent"
|
||||
mode: '0755'
|
||||
|
||||
- name: Clean up downloaded archive
|
||||
ansible.builtin.file:
|
||||
path: /tmp/zastava-agent.tar.gz
|
||||
state: absent
|
||||
|
||||
# =========================================================================
|
||||
# Configuration
|
||||
# =========================================================================
|
||||
|
||||
- name: Deploy environment configuration
|
||||
ansible.builtin.template:
|
||||
src: zastava-agent.env.j2
|
||||
dest: "{{ zastava_config_dir }}/zastava-agent.env"
|
||||
owner: root
|
||||
group: "{{ zastava_group }}"
|
||||
mode: '0640'
|
||||
notify: Restart zastava-agent
|
||||
|
||||
# =========================================================================
|
||||
# systemd Service
|
||||
# =========================================================================
|
||||
|
||||
- name: Install systemd service unit
|
||||
ansible.builtin.copy:
|
||||
src: zastava-agent.service
|
||||
dest: /etc/systemd/system/zastava-agent.service
|
||||
owner: root
|
||||
group: root
|
||||
mode: '0644'
|
||||
notify:
|
||||
- Reload systemd
|
||||
- Restart zastava-agent
|
||||
|
||||
- name: Enable and start zastava-agent service
|
||||
ansible.builtin.systemd:
|
||||
name: zastava-agent
|
||||
state: started
|
||||
enabled: true
|
||||
daemon_reload: true
|
||||
|
||||
# =========================================================================
|
||||
# Health Verification
|
||||
# =========================================================================
|
||||
|
||||
- name: Wait for agent health endpoint
|
||||
ansible.builtin.uri:
|
||||
url: "http://localhost:{{ zastava_health_port }}/healthz"
|
||||
method: GET
|
||||
status_code: 200
|
||||
register: health_result
|
||||
retries: 30
|
||||
delay: 2
|
||||
until: health_result.status == 200
|
||||
|
||||
- name: Display agent status
|
||||
ansible.builtin.debug:
|
||||
msg: "Zastava Agent deployed successfully on {{ inventory_hostname }}"
|
||||
|
||||
handlers:
|
||||
- name: Reload systemd
|
||||
ansible.builtin.systemd:
|
||||
daemon_reload: true
|
||||
|
||||
- name: Restart zastava-agent
|
||||
ansible.builtin.systemd:
|
||||
name: zastava-agent
|
||||
state: restarted
|
||||
|
||||
# =============================================================================
|
||||
# Post-deployment verification play
|
||||
# =============================================================================
|
||||
- name: Verify Zastava Agent Deployment
|
||||
hosts: zastava_agents
|
||||
become: false
|
||||
gather_facts: false
|
||||
|
||||
tasks:
|
||||
- name: Check agent readiness
|
||||
ansible.builtin.uri:
|
||||
url: "http://localhost:{{ zastava_health_port | default(8080) }}/readyz"
|
||||
method: GET
|
||||
return_content: true
|
||||
register: ready_check
|
||||
|
||||
- name: Display deployment summary
|
||||
ansible.builtin.debug:
|
||||
msg: |
|
||||
Zastava Agent Deployment Summary:
|
||||
- Host: {{ inventory_hostname }}
|
||||
- Status: {{ 'Ready' if ready_check.status == 200 else 'Not Ready' }}
|
||||
- Health Endpoint: http://localhost:{{ zastava_health_port | default(8080) }}/healthz
|
||||
- Tenant: {{ zastava_tenant }}
|
||||
- Backend: {{ scanner_backend_url }}
|
||||
@@ -1,136 +0,0 @@
|
||||
# Stella Ops Compose Profiles
|
||||
|
||||
These Compose bundles ship the minimum services required to exercise the scanner pipeline plus control-plane dependencies. Every profile is pinned to immutable image digests sourced from `deploy/releases/*.yaml` and is linted via `docker compose config` in CI.
|
||||
|
||||
## Layout
|
||||
|
||||
| Path | Purpose |
|
||||
| ---- | ------- |
|
||||
| `docker-compose.dev.yaml` | Edge/nightly stack tuned for laptops and iterative work. |
|
||||
| `docker-compose.stage.yaml` | Stable channel stack mirroring pre-production clusters. |
|
||||
| `docker-compose.prod.yaml` | Production cutover stack with front-door network hand-off and Notify events enabled. |
|
||||
| `docker-compose.airgap.yaml` | Stable stack with air-gapped defaults (no outbound hostnames). |
|
||||
| `docker-compose.mirror.yaml` | Managed mirror topology for `*.stella-ops.org` distribution (Concelier + Excititor + CDN gateway). |
|
||||
| `docker-compose.telemetry.yaml` | Optional OpenTelemetry collector overlay (mutual TLS, OTLP ingest endpoints). |
|
||||
| `docker-compose.telemetry-storage.yaml` | Prometheus/Tempo/Loki storage overlay with multi-tenant defaults. |
|
||||
| `docker-compose.gpu.yaml` | Optional GPU overlay enabling NVIDIA devices for Advisory AI web/worker. Apply with `-f docker-compose.<env>.yaml -f docker-compose.gpu.yaml`. |
|
||||
| `env/*.env.example` | Seed `.env` files that document required secrets and ports per profile. |
|
||||
| `scripts/backup.sh` | Pauses workers and creates tar.gz of Mongo/MinIO/Redis volumes (deterministic snapshot). |
|
||||
| `scripts/reset.sh` | Stops the stack and removes Mongo/MinIO/Redis volumes after explicit confirmation. |
|
||||
| `scripts/quickstart.sh` | Helper to validate config and start dev stack; set `USE_MOCK=1` to include `docker-compose.mock.yaml` overlay. |
|
||||
| `docker-compose.mock.yaml` | Dev-only overlay with placeholder digests for missing services (orchestrator, policy-registry, packs, task-runner, VEX/Vuln stack). Use only with mock release manifest `deploy/releases/2025.09-mock-dev.yaml`. |
|
||||
|
||||
## Usage
|
||||
|
||||
```bash
|
||||
cp env/dev.env.example dev.env
|
||||
docker compose --env-file dev.env -f docker-compose.dev.yaml config
|
||||
docker compose --env-file dev.env -f docker-compose.dev.yaml up -d
|
||||
```
|
||||
|
||||
The stage and airgap variants behave the same way—swap the file names accordingly. All profiles expose 443/8443 for the UI and REST APIs, and they share a `stellaops` Docker network scoped to the compose project.
|
||||
|
||||
> **Surface.Secrets:** set `SCANNER_SURFACE_SECRETS_PROVIDER`/`SCANNER_SURFACE_SECRETS_ROOT` in your `.env` and point `SURFACE_SECRETS_HOST_PATH` to the decrypted bundle path (default `./offline/surface-secrets`). The stack mounts that path read-only into Scanner Web/Worker so `secret://` references resolve without embedding plaintext.
|
||||
|
||||
> **Graph Explorer reminder:** If you enable Cartographer or Graph API containers alongside these profiles, update `etc/authority.yaml` so the `cartographer-service` client is marked with `properties.serviceIdentity: "cartographer"` and carries a tenant hint. The Authority host now refuses `graph:write` tokens without that marker, so apply the configuration change before rolling out the updated images.
|
||||
|
||||
### Telemetry collector overlay
|
||||
|
||||
The OpenTelemetry collector overlay is optional and can be layered on top of any profile:
|
||||
|
||||
```bash
|
||||
./ops/devops/telemetry/generate_dev_tls.sh
|
||||
docker compose -f docker-compose.telemetry.yaml up -d
|
||||
python ../../ops/devops/telemetry/smoke_otel_collector.py --host localhost
|
||||
docker compose -f docker-compose.telemetry-storage.yaml up -d
|
||||
```
|
||||
|
||||
The generator script creates a development CA plus server/client certificates under
|
||||
`deploy/telemetry/certs/`. The smoke test sends OTLP/HTTP payloads using the generated
|
||||
client certificate and asserts the collector reports accepted traces, metrics, and logs.
|
||||
The storage overlay starts Prometheus, Tempo, and Loki with multitenancy enabled so you
|
||||
can validate the end-to-end pipeline before promoting changes to staging. Adjust the
|
||||
configs in `deploy/telemetry/storage/` before running in production.
|
||||
Mount the same certificates when running workloads so the collector can enforce mutual TLS.
|
||||
|
||||
For production cutovers copy `env/prod.env.example` to `prod.env`, update the secret placeholders, and create the external network expected by the profile:
|
||||
|
||||
```bash
|
||||
docker network create stellaops_frontdoor
|
||||
docker compose --env-file prod.env -f docker-compose.prod.yaml config
|
||||
```
|
||||
|
||||
### Scanner event stream settings
|
||||
|
||||
Scanner WebService can emit signed `scanner.report.*` events to Redis Streams when `SCANNER__EVENTS__ENABLED=true`. Each profile ships environment placeholders you can override in the `.env` file:
|
||||
|
||||
- `SCANNER_EVENTS_ENABLED` – toggle emission on/off (defaults to `false`).
|
||||
- `SCANNER_EVENTS_DRIVER` – currently only `redis` is supported.
|
||||
- `SCANNER_EVENTS_DSN` – Redis endpoint; leave blank to reuse the queue DSN when it uses `redis://`.
|
||||
- `SCANNER_EVENTS_STREAM` – stream name (`stella.events` by default).
|
||||
- `SCANNER_EVENTS_PUBLISH_TIMEOUT_SECONDS` – per-publish timeout window (defaults to `5`).
|
||||
- `SCANNER_EVENTS_MAX_STREAM_LENGTH` – max stream length before Redis trims entries (defaults to `10000`).
|
||||
|
||||
Helm values mirror the same knobs under each service’s `env` map (see `deploy/helm/stellaops/values-*.yaml`).
|
||||
|
||||
### Scheduler worker configuration
|
||||
|
||||
Every Compose profile now provisions the `scheduler-worker` container (backed by the
|
||||
`StellaOps.Scheduler.Worker.Host` entrypoint). The environment placeholders exposed
|
||||
in the `.env` samples match the options bound by `AddSchedulerWorker`:
|
||||
|
||||
- `SCHEDULER_QUEUE_KIND` – queue transport (`Nats` or `Redis`).
|
||||
- `SCHEDULER_QUEUE_NATS_URL` – NATS connection string used by planner/runner consumers.
|
||||
- `SCHEDULER_STORAGE_DATABASE` – PostgreSQL database name for scheduler state.
|
||||
- `SCHEDULER_SCANNER_BASEADDRESS` – base URL the runner uses when invoking Scanner’s
|
||||
`/api/v1/reports` (defaults to the in-cluster `http://scanner-web:8444`).
|
||||
|
||||
Helm deployments inherit the same defaults from `services.scheduler-worker.env` in
|
||||
`values.yaml`; override them per environment as needed.
|
||||
|
||||
### Advisory AI configuration
|
||||
|
||||
`advisory-ai-web` hosts the API/plan cache while `advisory-ai-worker` executes queued tasks. Both containers mount the shared volumes (`advisory-ai-queue`, `advisory-ai-plans`, `advisory-ai-outputs`) so they always read/write the same deterministic state. New environment knobs:
|
||||
|
||||
- `ADVISORY_AI_SBOM_BASEADDRESS` – endpoint the SBOM context client hits (defaults to the in-cluster Scanner URL).
|
||||
- `ADVISORY_AI_INFERENCE_MODE` – `Local` (default) keeps inference on-prem; `Remote` posts sanitized prompts to the URL supplied via `ADVISORY_AI_REMOTE_BASEADDRESS`. Optional `ADVISORY_AI_REMOTE_APIKEY` carries the bearer token when remote inference is enabled.
|
||||
- `ADVISORY_AI_WEB_PORT` – host port for `advisory-ai-web`.
|
||||
|
||||
The Helm chart mirrors these settings under `services.advisory-ai-web` / `advisory-ai-worker` and expects a PVC named `stellaops-advisory-ai-data` so both deployments can mount the same RWX volume.
|
||||
|
||||
### Front-door network hand-off
|
||||
|
||||
`docker-compose.prod.yaml` adds a `frontdoor` network so operators can attach Traefik, Envoy, or an on-prem load balancer that terminates TLS. Override `FRONTDOOR_NETWORK` in `prod.env` if your reverse proxy uses a different bridge name. Attach only the externally reachable services (Authority, Signer, Attestor, Concelier, Scanner Web, Notify Web, UI) to that network—internal infrastructure (Mongo, MinIO, RustFS, NATS) stays on the private `stellaops` network.
|
||||
|
||||
### Updating to a new release
|
||||
|
||||
1. Import the new manifest into `deploy/releases/` (see `deploy/README.md`).
|
||||
2. Update image digests in the relevant Compose file(s).
|
||||
3. Re-run `docker compose config` to confirm the bundle is deterministic.
|
||||
|
||||
### Mock overlay for missing digests (dev only)
|
||||
|
||||
Until official digests land, you can exercise Compose packaging with mock placeholders:
|
||||
|
||||
```bash
|
||||
# assumes docker-compose.dev.yaml as the base profile
|
||||
USE_MOCK=1 ./scripts/quickstart.sh env/dev.env.example
|
||||
```
|
||||
|
||||
The overlay pins the missing services (orchestrator, policy-registry, packs-registry, task-runner, VEX/Vuln stack) to mock digests from `deploy/releases/2025.09-mock-dev.yaml` and starts their real entrypoints so integration flows can be exercised end-to-end. Replace the mock pins with production digests once releases publish; keep the mock overlay dev-only.
|
||||
|
||||
Keep digests synchronized between Compose, Helm, and the release manifest to preserve reproducibility guarantees. `deploy/tools/validate-profiles.sh` performs a quick audit.
|
||||
|
||||
### GPU toggle for Advisory AI
|
||||
|
||||
GPU is disabled by default. To run inference on NVIDIA GPUs:
|
||||
|
||||
```bash
|
||||
docker compose \
|
||||
--env-file prod.env \
|
||||
-f docker-compose.prod.yaml \
|
||||
-f docker-compose.gpu.yaml \
|
||||
up -d
|
||||
```
|
||||
|
||||
The GPU overlay requests one GPU for `advisory-ai-worker` and `advisory-ai-web` and sets `ADVISORY_AI_INFERENCE_GPU=true`. Ensure the host has the NVIDIA container runtime and that the base compose file still sets the correct digests.
|
||||
@@ -1,383 +0,0 @@
|
||||
x-release-labels: &release-labels
|
||||
com.stellaops.release.version: "2025.09.2-airgap"
|
||||
com.stellaops.release.channel: "airgap"
|
||||
com.stellaops.profile: "airgap"
|
||||
|
||||
networks:
|
||||
stellaops:
|
||||
driver: bridge
|
||||
|
||||
volumes:
|
||||
valkey-data:
|
||||
rustfs-data:
|
||||
concelier-jobs:
|
||||
nats-data:
|
||||
scanner-surface-cache:
|
||||
postgres-data:
|
||||
advisory-ai-queue:
|
||||
advisory-ai-plans:
|
||||
advisory-ai-outputs:
|
||||
|
||||
services:
|
||||
postgres:
|
||||
image: docker.io/library/postgres:17
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
POSTGRES_USER: "${POSTGRES_USER:-stellaops}"
|
||||
POSTGRES_PASSWORD: "${POSTGRES_PASSWORD:-stellaops}"
|
||||
POSTGRES_DB: "${POSTGRES_DB:-stellaops}"
|
||||
PGDATA: /var/lib/postgresql/data/pgdata
|
||||
volumes:
|
||||
- postgres-data:/var/lib/postgresql/data
|
||||
- ./postgres-init:/docker-entrypoint-initdb.d:ro
|
||||
command:
|
||||
- "postgres"
|
||||
- "-c"
|
||||
- "shared_preload_libraries=pg_stat_statements"
|
||||
- "-c"
|
||||
- "pg_stat_statements.track=all"
|
||||
ports:
|
||||
- "${POSTGRES_PORT:-25432}:5432"
|
||||
healthcheck:
|
||||
test: ["CMD-SHELL", "pg_isready -U $$POSTGRES_USER -d $$POSTGRES_DB"]
|
||||
interval: 10s
|
||||
timeout: 5s
|
||||
retries: 5
|
||||
networks:
|
||||
- stellaops
|
||||
labels: *release-labels
|
||||
|
||||
valkey:
|
||||
image: docker.io/valkey/valkey:8.0
|
||||
restart: unless-stopped
|
||||
command: ["valkey-server", "--appendonly", "yes"]
|
||||
volumes:
|
||||
- valkey-data:/data
|
||||
ports:
|
||||
- "${VALKEY_PORT:-26379}:6379"
|
||||
networks:
|
||||
- stellaops
|
||||
labels: *release-labels
|
||||
|
||||
rustfs:
|
||||
image: registry.stella-ops.org/stellaops/rustfs:2025.10.0-edge
|
||||
command: ["serve", "--listen", "0.0.0.0:8080", "--root", "/data"]
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
RUSTFS__LOG__LEVEL: info
|
||||
RUSTFS__STORAGE__PATH: /data
|
||||
volumes:
|
||||
- rustfs-data:/data
|
||||
ports:
|
||||
- "${RUSTFS_HTTP_PORT:-8080}:8080"
|
||||
networks:
|
||||
- stellaops
|
||||
labels: *release-labels
|
||||
|
||||
nats:
|
||||
image: docker.io/library/nats@sha256:c82559e4476289481a8a5196e675ebfe67eea81d95e5161e3e78eccfe766608e
|
||||
command:
|
||||
- "-js"
|
||||
- "-sd"
|
||||
- /data
|
||||
restart: unless-stopped
|
||||
ports:
|
||||
- "${NATS_CLIENT_PORT:-24222}:4222"
|
||||
volumes:
|
||||
- nats-data:/data
|
||||
networks:
|
||||
- stellaops
|
||||
labels: *release-labels
|
||||
|
||||
authority:
|
||||
image: registry.stella-ops.org/stellaops/authority@sha256:5551a3269b7008cd5aceecf45df018c67459ed519557ccbe48b093b926a39bcc
|
||||
restart: unless-stopped
|
||||
depends_on:
|
||||
- postgres
|
||||
- valkey
|
||||
environment:
|
||||
STELLAOPS_AUTHORITY__ISSUER: "${AUTHORITY_ISSUER}"
|
||||
STELLAOPS_AUTHORITY__STORAGE__DRIVER: "postgres"
|
||||
STELLAOPS_AUTHORITY__STORAGE__POSTGRES__CONNECTIONSTRING: "Host=postgres;Port=5432;Database=${POSTGRES_DB:-stellaops_platform};Username=${POSTGRES_USER:-stellaops};Password=${POSTGRES_PASSWORD:-stellaops}"
|
||||
STELLAOPS_AUTHORITY__CACHE__REDIS__CONNECTIONSTRING: "valkey:6379"
|
||||
STELLAOPS_AUTHORITY__PLUGINDIRECTORIES__0: "/app/plugins"
|
||||
STELLAOPS_AUTHORITY__PLUGINS__CONFIGURATIONDIRECTORY: "/app/etc/authority.plugins"
|
||||
volumes:
|
||||
- ../../etc/authority.yaml:/etc/authority.yaml:ro
|
||||
- ../../etc/authority.plugins:/app/etc/authority.plugins:ro
|
||||
ports:
|
||||
- "${AUTHORITY_PORT:-8440}:8440"
|
||||
networks:
|
||||
- stellaops
|
||||
labels: *release-labels
|
||||
|
||||
signer:
|
||||
image: registry.stella-ops.org/stellaops/signer@sha256:ddbbd664a42846cea6b40fca6465bc679b30f72851158f300d01a8571c5478fc
|
||||
restart: unless-stopped
|
||||
depends_on:
|
||||
- postgres
|
||||
- authority
|
||||
environment:
|
||||
SIGNER__AUTHORITY__BASEURL: "https://authority:8440"
|
||||
SIGNER__POE__INTROSPECTURL: "${SIGNER_POE_INTROSPECT_URL}"
|
||||
SIGNER__STORAGE__DRIVER: "postgres"
|
||||
SIGNER__STORAGE__POSTGRES__CONNECTIONSTRING: "Host=postgres;Port=5432;Database=${POSTGRES_DB:-stellaops_platform};Username=${POSTGRES_USER:-stellaops};Password=${POSTGRES_PASSWORD:-stellaops}"
|
||||
ports:
|
||||
- "${SIGNER_PORT:-8441}:8441"
|
||||
networks:
|
||||
- stellaops
|
||||
labels: *release-labels
|
||||
|
||||
attestor:
|
||||
image: registry.stella-ops.org/stellaops/attestor@sha256:1ff0a3124d66d3a2702d8e421df40fbd98cc75cb605d95510598ebbae1433c50
|
||||
restart: unless-stopped
|
||||
depends_on:
|
||||
- signer
|
||||
- postgres
|
||||
environment:
|
||||
ATTESTOR__SIGNER__BASEURL: "https://signer:8441"
|
||||
ATTESTOR__STORAGE__DRIVER: "postgres"
|
||||
ATTESTOR__STORAGE__POSTGRES__CONNECTIONSTRING: "Host=postgres;Port=5432;Database=${POSTGRES_DB:-stellaops_platform};Username=${POSTGRES_USER:-stellaops};Password=${POSTGRES_PASSWORD:-stellaops}"
|
||||
ports:
|
||||
- "${ATTESTOR_PORT:-8442}:8442"
|
||||
networks:
|
||||
- stellaops
|
||||
labels: *release-labels
|
||||
|
||||
issuer-directory:
|
||||
image: registry.stella-ops.org/stellaops/issuer-directory-web:2025.10.0-edge
|
||||
restart: unless-stopped
|
||||
depends_on:
|
||||
- postgres
|
||||
- authority
|
||||
environment:
|
||||
ISSUERDIRECTORY__CONFIG: "/etc/issuer-directory.yaml"
|
||||
ISSUERDIRECTORY__AUTHORITY__ISSUER: "${AUTHORITY_ISSUER}"
|
||||
ISSUERDIRECTORY__AUTHORITY__BASEURL: "https://authority:8440"
|
||||
ISSUERDIRECTORY__STORAGE__DRIVER: "postgres"
|
||||
ISSUERDIRECTORY__STORAGE__POSTGRES__CONNECTIONSTRING: "Host=postgres;Port=5432;Database=${POSTGRES_DB:-stellaops_platform};Username=${POSTGRES_USER:-stellaops};Password=${POSTGRES_PASSWORD:-stellaops}"
|
||||
ISSUERDIRECTORY__SEEDCSAFPUBLISHERS: "${ISSUER_DIRECTORY_SEED_CSAF:-true}"
|
||||
volumes:
|
||||
- ../../etc/issuer-directory.yaml:/etc/issuer-directory.yaml:ro
|
||||
ports:
|
||||
- "${ISSUER_DIRECTORY_PORT:-8447}:8080"
|
||||
networks:
|
||||
- stellaops
|
||||
labels: *release-labels
|
||||
|
||||
concelier:
|
||||
image: registry.stella-ops.org/stellaops/concelier@sha256:29e2e1a0972707e092cbd3d370701341f9fec2aa9316fb5d8100480f2a1c76b5
|
||||
restart: unless-stopped
|
||||
depends_on:
|
||||
- postgres
|
||||
- valkey
|
||||
environment:
|
||||
CONCELIER__STORAGE__DRIVER: "postgres"
|
||||
CONCELIER__STORAGE__POSTGRES__CONNECTIONSTRING: "Host=postgres;Port=5432;Database=${POSTGRES_DB:-stellaops_platform};Username=${POSTGRES_USER:-stellaops};Password=${POSTGRES_PASSWORD:-stellaops}"
|
||||
CONCELIER__STORAGE__S3__ENDPOINT: "http://rustfs:8080"
|
||||
CONCELIER__AUTHORITY__BASEURL: "https://authority:8440"
|
||||
CONCELIER__AUTHORITY__RESILIENCE__ALLOWOFFLINECACHEFALLBACK: "true"
|
||||
CONCELIER__AUTHORITY__RESILIENCE__OFFLINECACHETOLERANCE: "${AUTHORITY_OFFLINE_CACHE_TOLERANCE:-00:30:00}"
|
||||
volumes:
|
||||
- concelier-jobs:/var/lib/concelier/jobs
|
||||
ports:
|
||||
- "${CONCELIER_PORT:-8445}:8445"
|
||||
networks:
|
||||
- stellaops
|
||||
labels: *release-labels
|
||||
|
||||
scanner-web:
|
||||
image: registry.stella-ops.org/stellaops/scanner-web@sha256:3df8ca21878126758203c1a0444e39fd97f77ddacf04a69685cda9f1e5e94718
|
||||
restart: unless-stopped
|
||||
depends_on:
|
||||
- postgres
|
||||
- valkey
|
||||
- concelier
|
||||
- rustfs
|
||||
environment:
|
||||
SCANNER__STORAGE__DRIVER: "postgres"
|
||||
SCANNER__STORAGE__POSTGRES__CONNECTIONSTRING: "Host=postgres;Port=5432;Database=${POSTGRES_DB:-stellaops_platform};Username=${POSTGRES_USER:-stellaops};Password=${POSTGRES_PASSWORD:-stellaops}"
|
||||
SCANNER__CACHE__REDIS__CONNECTIONSTRING: "valkey:6379"
|
||||
SCANNER__ARTIFACTSTORE__DRIVER: "rustfs"
|
||||
SCANNER__ARTIFACTSTORE__ENDPOINT: "http://rustfs:8080/api/v1"
|
||||
SCANNER__ARTIFACTSTORE__BUCKET: "scanner-artifacts"
|
||||
SCANNER__ARTIFACTSTORE__TIMEOUTSECONDS: "30"
|
||||
SCANNER__QUEUE__BROKER: "${SCANNER_QUEUE_BROKER:-valkey://valkey:6379}"
|
||||
SCANNER__EVENTS__ENABLED: "${SCANNER_EVENTS_ENABLED:-false}"
|
||||
SCANNER__EVENTS__DRIVER: "${SCANNER_EVENTS_DRIVER:-valkey}"
|
||||
SCANNER__EVENTS__DSN: "${SCANNER_EVENTS_DSN:-}"
|
||||
SCANNER__EVENTS__STREAM: "${SCANNER_EVENTS_STREAM:-stella.events}"
|
||||
SCANNER__EVENTS__PUBLISHTIMEOUTSECONDS: "${SCANNER_EVENTS_PUBLISH_TIMEOUT_SECONDS:-5}"
|
||||
SCANNER__EVENTS__MAXSTREAMLENGTH: "${SCANNER_EVENTS_MAX_STREAM_LENGTH:-10000}"
|
||||
SCANNER__OFFLINEKIT__ENABLED: "${SCANNER_OFFLINEKIT_ENABLED:-false}"
|
||||
SCANNER__OFFLINEKIT__REQUIREDSSE: "${SCANNER_OFFLINEKIT_REQUIREDSSE:-true}"
|
||||
SCANNER__OFFLINEKIT__REKOROFFLINEMODE: "${SCANNER_OFFLINEKIT_REKOROFFLINEMODE:-true}"
|
||||
SCANNER__OFFLINEKIT__TRUSTROOTDIRECTORY: "${SCANNER_OFFLINEKIT_TRUSTROOTDIRECTORY:-/etc/stellaops/trust-roots}"
|
||||
SCANNER__OFFLINEKIT__REKORSNAPSHOTDIRECTORY: "${SCANNER_OFFLINEKIT_REKORSNAPSHOTDIRECTORY:-/var/lib/stellaops/rekor-snapshot}"
|
||||
# Surface.Env configuration (see docs/modules/scanner/design/surface-env.md)
|
||||
SCANNER_SURFACE_FS_ENDPOINT: "${SCANNER_SURFACE_FS_ENDPOINT:-http://rustfs:8080}"
|
||||
SCANNER_SURFACE_FS_BUCKET: "${SCANNER_SURFACE_FS_BUCKET:-surface-cache}"
|
||||
SCANNER_SURFACE_CACHE_ROOT: "${SCANNER_SURFACE_CACHE_ROOT:-/var/lib/stellaops/surface}"
|
||||
SCANNER_SURFACE_CACHE_QUOTA_MB: "${SCANNER_SURFACE_CACHE_QUOTA_MB:-4096}"
|
||||
SCANNER_SURFACE_PREFETCH_ENABLED: "${SCANNER_SURFACE_PREFETCH_ENABLED:-false}"
|
||||
SCANNER_SURFACE_TENANT: "${SCANNER_SURFACE_TENANT:-default}"
|
||||
SCANNER_SURFACE_FEATURES: "${SCANNER_SURFACE_FEATURES:-}"
|
||||
SCANNER_SURFACE_SECRETS_PROVIDER: "${SCANNER_SURFACE_SECRETS_PROVIDER:-file}"
|
||||
SCANNER_SURFACE_SECRETS_NAMESPACE: "${SCANNER_SURFACE_SECRETS_NAMESPACE:-}"
|
||||
SCANNER_SURFACE_SECRETS_ROOT: "${SCANNER_SURFACE_SECRETS_ROOT:-/etc/stellaops/secrets}"
|
||||
SCANNER_SURFACE_SECRETS_FALLBACK_PROVIDER: "${SCANNER_SURFACE_SECRETS_FALLBACK_PROVIDER:-}"
|
||||
SCANNER_SURFACE_SECRETS_ALLOW_INLINE: "${SCANNER_SURFACE_SECRETS_ALLOW_INLINE:-false}"
|
||||
volumes:
|
||||
- scanner-surface-cache:/var/lib/stellaops/surface
|
||||
- ${SURFACE_SECRETS_HOST_PATH:-./offline/surface-secrets}:${SCANNER_SURFACE_SECRETS_ROOT:-/etc/stellaops/secrets}:ro
|
||||
- ${SCANNER_OFFLINEKIT_TRUSTROOTS_HOST_PATH:-./offline/trust-roots}:${SCANNER_OFFLINEKIT_TRUSTROOTDIRECTORY:-/etc/stellaops/trust-roots}:ro
|
||||
- ${SCANNER_OFFLINEKIT_REKOR_SNAPSHOT_HOST_PATH:-./offline/rekor-snapshot}:${SCANNER_OFFLINEKIT_REKORSNAPSHOTDIRECTORY:-/var/lib/stellaops/rekor-snapshot}:ro
|
||||
ports:
|
||||
- "${SCANNER_WEB_PORT:-8444}:8444"
|
||||
networks:
|
||||
- stellaops
|
||||
labels: *release-labels
|
||||
|
||||
scanner-worker:
|
||||
image: registry.stella-ops.org/stellaops/scanner-worker@sha256:eea5d6cfe7835950c5ec7a735a651f2f0d727d3e470cf9027a4a402ea89c4fb5
|
||||
restart: unless-stopped
|
||||
depends_on:
|
||||
- postgres
|
||||
- valkey
|
||||
- scanner-web
|
||||
- rustfs
|
||||
environment:
|
||||
SCANNER__STORAGE__DRIVER: "postgres"
|
||||
SCANNER__STORAGE__POSTGRES__CONNECTIONSTRING: "Host=postgres;Port=5432;Database=${POSTGRES_DB:-stellaops_platform};Username=${POSTGRES_USER:-stellaops};Password=${POSTGRES_PASSWORD:-stellaops}"
|
||||
SCANNER__CACHE__REDIS__CONNECTIONSTRING: "valkey:6379"
|
||||
SCANNER__ARTIFACTSTORE__DRIVER: "rustfs"
|
||||
SCANNER__ARTIFACTSTORE__ENDPOINT: "http://rustfs:8080/api/v1"
|
||||
SCANNER__ARTIFACTSTORE__BUCKET: "scanner-artifacts"
|
||||
SCANNER__ARTIFACTSTORE__TIMEOUTSECONDS: "30"
|
||||
SCANNER__QUEUE__BROKER: "${SCANNER_QUEUE_BROKER:-valkey://valkey:6379}"
|
||||
# Surface.Env configuration (see docs/modules/scanner/design/surface-env.md)
|
||||
SCANNER_SURFACE_FS_ENDPOINT: "${SCANNER_SURFACE_FS_ENDPOINT:-http://rustfs:8080}"
|
||||
SCANNER_SURFACE_FS_BUCKET: "${SCANNER_SURFACE_FS_BUCKET:-surface-cache}"
|
||||
SCANNER_SURFACE_CACHE_ROOT: "${SCANNER_SURFACE_CACHE_ROOT:-/var/lib/stellaops/surface}"
|
||||
SCANNER_SURFACE_CACHE_QUOTA_MB: "${SCANNER_SURFACE_CACHE_QUOTA_MB:-4096}"
|
||||
SCANNER_SURFACE_PREFETCH_ENABLED: "${SCANNER_SURFACE_PREFETCH_ENABLED:-false}"
|
||||
SCANNER_SURFACE_TENANT: "${SCANNER_SURFACE_TENANT:-default}"
|
||||
SCANNER_SURFACE_FEATURES: "${SCANNER_SURFACE_FEATURES:-}"
|
||||
SCANNER_SURFACE_SECRETS_PROVIDER: "${SCANNER_SURFACE_SECRETS_PROVIDER:-file}"
|
||||
SCANNER_SURFACE_SECRETS_NAMESPACE: "${SCANNER_SURFACE_SECRETS_NAMESPACE:-}"
|
||||
SCANNER_SURFACE_SECRETS_ROOT: "${SCANNER_SURFACE_SECRETS_ROOT:-/etc/stellaops/secrets}"
|
||||
SCANNER_SURFACE_SECRETS_FALLBACK_PROVIDER: "${SCANNER_SURFACE_SECRETS_FALLBACK_PROVIDER:-}"
|
||||
SCANNER_SURFACE_SECRETS_ALLOW_INLINE: "${SCANNER_SURFACE_SECRETS_ALLOW_INLINE:-false}"
|
||||
volumes:
|
||||
- scanner-surface-cache:/var/lib/stellaops/surface
|
||||
- ${SURFACE_SECRETS_HOST_PATH:-./offline/surface-secrets}:${SCANNER_SURFACE_SECRETS_ROOT:-/etc/stellaops/secrets}:ro
|
||||
networks:
|
||||
- stellaops
|
||||
labels: *release-labels
|
||||
|
||||
scheduler-worker:
|
||||
image: registry.stella-ops.org/stellaops/scheduler-worker:2025.10.0-edge
|
||||
restart: unless-stopped
|
||||
depends_on:
|
||||
- postgres
|
||||
- valkey
|
||||
- scanner-web
|
||||
command:
|
||||
- "dotnet"
|
||||
- "StellaOps.Scheduler.Worker.Host.dll"
|
||||
environment:
|
||||
SCHEDULER__STORAGE__DRIVER: "postgres"
|
||||
SCHEDULER__STORAGE__POSTGRES__CONNECTIONSTRING: "Host=postgres;Port=5432;Database=${POSTGRES_DB:-stellaops_platform};Username=${POSTGRES_USER:-stellaops};Password=${POSTGRES_PASSWORD:-stellaops}"
|
||||
SCHEDULER__QUEUE__KIND: "${SCHEDULER_QUEUE_KIND:-Valkey}"
|
||||
SCHEDULER__QUEUE__VALKEY__URL: "${SCHEDULER_QUEUE_VALKEY_URL:-valkey:6379}"
|
||||
SCHEDULER__WORKER__RUNNER__SCANNER__BASEADDRESS: "${SCHEDULER_SCANNER_BASEADDRESS:-http://scanner-web:8444}"
|
||||
networks:
|
||||
- stellaops
|
||||
labels: *release-labels
|
||||
|
||||
notify-web:
|
||||
image: ${NOTIFY_WEB_IMAGE:-registry.stella-ops.org/stellaops/notify-web:2025.09.2}
|
||||
restart: unless-stopped
|
||||
depends_on:
|
||||
- postgres
|
||||
- authority
|
||||
environment:
|
||||
DOTNET_ENVIRONMENT: Production
|
||||
volumes:
|
||||
- ../../etc/notify.airgap.yaml:/app/etc/notify.yaml:ro
|
||||
ports:
|
||||
- "${NOTIFY_WEB_PORT:-9446}:8446"
|
||||
networks:
|
||||
- stellaops
|
||||
labels: *release-labels
|
||||
|
||||
excititor:
|
||||
image: registry.stella-ops.org/stellaops/excititor@sha256:65c0ee13f773efe920d7181512349a09d363ab3f3e177d276136bd2742325a68
|
||||
restart: unless-stopped
|
||||
depends_on:
|
||||
- postgres
|
||||
- concelier
|
||||
environment:
|
||||
EXCITITOR__CONCELIER__BASEURL: "https://concelier:8445"
|
||||
EXCITITOR__STORAGE__DRIVER: "postgres"
|
||||
EXCITITOR__STORAGE__POSTGRES__CONNECTIONSTRING: "Host=postgres;Port=5432;Database=${POSTGRES_DB:-stellaops_platform};Username=${POSTGRES_USER:-stellaops};Password=${POSTGRES_PASSWORD:-stellaops}"
|
||||
networks:
|
||||
- stellaops
|
||||
labels: *release-labels
|
||||
|
||||
advisory-ai-web:
|
||||
image: registry.stella-ops.org/stellaops/advisory-ai-web:2025.09.2-airgap
|
||||
restart: unless-stopped
|
||||
depends_on:
|
||||
- scanner-web
|
||||
environment:
|
||||
ADVISORYAI__AdvisoryAI__SbomBaseAddress: "${ADVISORY_AI_SBOM_BASEADDRESS:-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: "${ADVISORY_AI_INFERENCE_MODE:-Local}"
|
||||
ADVISORYAI__AdvisoryAI__Inference__Remote__BaseAddress: "${ADVISORY_AI_REMOTE_BASEADDRESS:-}"
|
||||
ADVISORYAI__AdvisoryAI__Inference__Remote__ApiKey: "${ADVISORY_AI_REMOTE_APIKEY:-}"
|
||||
ports:
|
||||
- "${ADVISORY_AI_WEB_PORT:-8448}:8448"
|
||||
volumes:
|
||||
- advisory-ai-queue:/var/lib/advisory-ai/queue
|
||||
- advisory-ai-plans:/var/lib/advisory-ai/plans
|
||||
- advisory-ai-outputs:/var/lib/advisory-ai/outputs
|
||||
networks:
|
||||
- stellaops
|
||||
labels: *release-labels
|
||||
|
||||
advisory-ai-worker:
|
||||
image: registry.stella-ops.org/stellaops/advisory-ai-worker:2025.09.2-airgap
|
||||
restart: unless-stopped
|
||||
depends_on:
|
||||
- advisory-ai-web
|
||||
environment:
|
||||
ADVISORYAI__AdvisoryAI__SbomBaseAddress: "${ADVISORY_AI_SBOM_BASEADDRESS:-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: "${ADVISORY_AI_INFERENCE_MODE:-Local}"
|
||||
ADVISORYAI__AdvisoryAI__Inference__Remote__BaseAddress: "${ADVISORY_AI_REMOTE_BASEADDRESS:-}"
|
||||
ADVISORYAI__AdvisoryAI__Inference__Remote__ApiKey: "${ADVISORY_AI_REMOTE_APIKEY:-}"
|
||||
volumes:
|
||||
- advisory-ai-queue:/var/lib/advisory-ai/queue
|
||||
- advisory-ai-plans:/var/lib/advisory-ai/plans
|
||||
- advisory-ai-outputs:/var/lib/advisory-ai/outputs
|
||||
networks:
|
||||
- stellaops
|
||||
labels: *release-labels
|
||||
|
||||
web-ui:
|
||||
image: registry.stella-ops.org/stellaops/web-ui@sha256:bee9668011ff414572131dc777faab4da24473fe12c230893f161cabee092a1d
|
||||
restart: unless-stopped
|
||||
depends_on:
|
||||
- scanner-web
|
||||
environment:
|
||||
STELLAOPS_UI__BACKEND__BASEURL: "https://scanner-web:8444"
|
||||
ports:
|
||||
- "${UI_PORT:-9443}:8443"
|
||||
networks:
|
||||
- stellaops
|
||||
labels: *release-labels
|
||||
@@ -1,191 +0,0 @@
|
||||
# Content Addressable Storage (CAS) Infrastructure
|
||||
# Uses RustFS for S3-compatible immutable object storage
|
||||
# Aligned with best-in-class vulnerability scanner retention policies
|
||||
#
|
||||
# Usage:
|
||||
# docker compose -f docker-compose.cas.yaml up -d
|
||||
# docker compose -f docker-compose.cas.yaml -f docker-compose.dev.yaml up -d
|
||||
|
||||
x-release-labels: &release-labels
|
||||
com.stellaops.release.version: "2025.10.0-edge"
|
||||
com.stellaops.release.channel: "edge"
|
||||
com.stellaops.profile: "cas"
|
||||
|
||||
x-cas-config: &cas-config
|
||||
# Retention policies (aligned with Trivy/Grype/Anchore Enterprise)
|
||||
# - vulnerability-db: 7 days (matches Trivy default)
|
||||
# - sbom-artifacts: 365 days (audit compliance)
|
||||
# - scan-results: 90 days (SOC2/ISO27001 typical)
|
||||
# - evidence-bundles: indefinite (immutable, content-addressed)
|
||||
# - attestations: indefinite (in-toto/DSSE signed)
|
||||
CAS__RETENTION__VULNERABILITY_DB_DAYS: "7"
|
||||
CAS__RETENTION__SBOM_ARTIFACTS_DAYS: "365"
|
||||
CAS__RETENTION__SCAN_RESULTS_DAYS: "90"
|
||||
CAS__RETENTION__EVIDENCE_BUNDLES_DAYS: "0" # 0 = indefinite
|
||||
CAS__RETENTION__ATTESTATIONS_DAYS: "0" # 0 = indefinite
|
||||
CAS__RETENTION__TEMP_ARTIFACTS_DAYS: "1"
|
||||
|
||||
networks:
|
||||
cas:
|
||||
driver: bridge
|
||||
|
||||
volumes:
|
||||
rustfs-cas-data:
|
||||
driver: local
|
||||
driver_opts:
|
||||
type: none
|
||||
o: bind
|
||||
device: ${CAS_DATA_PATH:-/var/lib/stellaops/cas}
|
||||
rustfs-evidence-data:
|
||||
driver: local
|
||||
driver_opts:
|
||||
type: none
|
||||
o: bind
|
||||
device: ${CAS_EVIDENCE_PATH:-/var/lib/stellaops/evidence}
|
||||
rustfs-attestation-data:
|
||||
driver: local
|
||||
driver_opts:
|
||||
type: none
|
||||
o: bind
|
||||
device: ${CAS_ATTESTATION_PATH:-/var/lib/stellaops/attestations}
|
||||
|
||||
services:
|
||||
# Primary CAS storage - runtime facts, signals, replay artifacts
|
||||
rustfs-cas:
|
||||
image: registry.stella-ops.org/stellaops/rustfs:2025.10.0-edge
|
||||
command: ["serve", "--listen", "0.0.0.0:8080", "--root", "/data"]
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
RUSTFS__LOG__LEVEL: "${RUSTFS_LOG_LEVEL:-info}"
|
||||
RUSTFS__STORAGE__PATH: /data
|
||||
RUSTFS__STORAGE__DEDUP: "true"
|
||||
RUSTFS__STORAGE__COMPRESSION: "${RUSTFS_COMPRESSION:-zstd}"
|
||||
RUSTFS__STORAGE__COMPRESSION_LEVEL: "${RUSTFS_COMPRESSION_LEVEL:-3}"
|
||||
# Bucket lifecycle (retention enforcement)
|
||||
RUSTFS__LIFECYCLE__ENABLED: "true"
|
||||
RUSTFS__LIFECYCLE__SCAN_INTERVAL_HOURS: "24"
|
||||
RUSTFS__LIFECYCLE__DEFAULT_RETENTION_DAYS: "90"
|
||||
# Access control
|
||||
RUSTFS__AUTH__ENABLED: "${RUSTFS_AUTH_ENABLED:-true}"
|
||||
RUSTFS__AUTH__API_KEY: "${RUSTFS_CAS_API_KEY:-cas-api-key-change-me}"
|
||||
RUSTFS__AUTH__READONLY_KEY: "${RUSTFS_CAS_READONLY_KEY:-cas-readonly-key-change-me}"
|
||||
# Service account configuration
|
||||
RUSTFS__ACCOUNTS__SCANNER__KEY: "${RUSTFS_SCANNER_KEY:-scanner-svc-key}"
|
||||
RUSTFS__ACCOUNTS__SCANNER__BUCKETS: "scanner-artifacts,surface-cache,runtime-facts"
|
||||
RUSTFS__ACCOUNTS__SCANNER__PERMISSIONS: "read,write"
|
||||
RUSTFS__ACCOUNTS__SIGNALS__KEY: "${RUSTFS_SIGNALS_KEY:-signals-svc-key}"
|
||||
RUSTFS__ACCOUNTS__SIGNALS__BUCKETS: "runtime-facts,signals-data,provenance-feed"
|
||||
RUSTFS__ACCOUNTS__SIGNALS__PERMISSIONS: "read,write"
|
||||
RUSTFS__ACCOUNTS__REPLAY__KEY: "${RUSTFS_REPLAY_KEY:-replay-svc-key}"
|
||||
RUSTFS__ACCOUNTS__REPLAY__BUCKETS: "replay-bundles,inputs-lock"
|
||||
RUSTFS__ACCOUNTS__REPLAY__PERMISSIONS: "read,write"
|
||||
RUSTFS__ACCOUNTS__READONLY__KEY: "${RUSTFS_READONLY_KEY:-readonly-svc-key}"
|
||||
RUSTFS__ACCOUNTS__READONLY__BUCKETS: "*"
|
||||
RUSTFS__ACCOUNTS__READONLY__PERMISSIONS: "read"
|
||||
<<: *cas-config
|
||||
volumes:
|
||||
- rustfs-cas-data:/data
|
||||
ports:
|
||||
- "${RUSTFS_CAS_PORT:-8180}:8080"
|
||||
networks:
|
||||
- cas
|
||||
labels: *release-labels
|
||||
healthcheck:
|
||||
test: ["CMD", "curl", "-f", "http://localhost:8080/health"]
|
||||
interval: 30s
|
||||
timeout: 10s
|
||||
retries: 3
|
||||
start_period: 10s
|
||||
|
||||
# Evidence storage - Merkle roots, hash chains, evidence bundles (immutable)
|
||||
rustfs-evidence:
|
||||
image: registry.stella-ops.org/stellaops/rustfs:2025.10.0-edge
|
||||
command: ["serve", "--listen", "0.0.0.0:8080", "--root", "/data", "--immutable"]
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
RUSTFS__LOG__LEVEL: "${RUSTFS_LOG_LEVEL:-info}"
|
||||
RUSTFS__STORAGE__PATH: /data
|
||||
RUSTFS__STORAGE__DEDUP: "true"
|
||||
RUSTFS__STORAGE__COMPRESSION: "${RUSTFS_COMPRESSION:-zstd}"
|
||||
RUSTFS__STORAGE__IMMUTABLE: "true" # Write-once, never delete
|
||||
# Access control
|
||||
RUSTFS__AUTH__ENABLED: "true"
|
||||
RUSTFS__AUTH__API_KEY: "${RUSTFS_EVIDENCE_API_KEY:-evidence-api-key-change-me}"
|
||||
RUSTFS__AUTH__READONLY_KEY: "${RUSTFS_EVIDENCE_READONLY_KEY:-evidence-readonly-key-change-me}"
|
||||
# Service accounts
|
||||
RUSTFS__ACCOUNTS__LEDGER__KEY: "${RUSTFS_LEDGER_KEY:-ledger-svc-key}"
|
||||
RUSTFS__ACCOUNTS__LEDGER__BUCKETS: "evidence-bundles,merkle-roots,hash-chains"
|
||||
RUSTFS__ACCOUNTS__LEDGER__PERMISSIONS: "read,write"
|
||||
RUSTFS__ACCOUNTS__EXPORTER__KEY: "${RUSTFS_EXPORTER_KEY:-exporter-svc-key}"
|
||||
RUSTFS__ACCOUNTS__EXPORTER__BUCKETS: "evidence-bundles"
|
||||
RUSTFS__ACCOUNTS__EXPORTER__PERMISSIONS: "read"
|
||||
volumes:
|
||||
- rustfs-evidence-data:/data
|
||||
ports:
|
||||
- "${RUSTFS_EVIDENCE_PORT:-8181}:8080"
|
||||
networks:
|
||||
- cas
|
||||
labels: *release-labels
|
||||
healthcheck:
|
||||
test: ["CMD", "curl", "-f", "http://localhost:8080/health"]
|
||||
interval: 30s
|
||||
timeout: 10s
|
||||
retries: 3
|
||||
start_period: 10s
|
||||
|
||||
# Attestation storage - DSSE envelopes, in-toto attestations (immutable)
|
||||
rustfs-attestation:
|
||||
image: registry.stella-ops.org/stellaops/rustfs:2025.10.0-edge
|
||||
command: ["serve", "--listen", "0.0.0.0:8080", "--root", "/data", "--immutable"]
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
RUSTFS__LOG__LEVEL: "${RUSTFS_LOG_LEVEL:-info}"
|
||||
RUSTFS__STORAGE__PATH: /data
|
||||
RUSTFS__STORAGE__DEDUP: "true"
|
||||
RUSTFS__STORAGE__COMPRESSION: "${RUSTFS_COMPRESSION:-zstd}"
|
||||
RUSTFS__STORAGE__IMMUTABLE: "true" # Write-once, never delete
|
||||
# Access control
|
||||
RUSTFS__AUTH__ENABLED: "true"
|
||||
RUSTFS__AUTH__API_KEY: "${RUSTFS_ATTESTATION_API_KEY:-attestation-api-key-change-me}"
|
||||
RUSTFS__AUTH__READONLY_KEY: "${RUSTFS_ATTESTATION_READONLY_KEY:-attestation-readonly-key-change-me}"
|
||||
# Service accounts
|
||||
RUSTFS__ACCOUNTS__ATTESTOR__KEY: "${RUSTFS_ATTESTOR_KEY:-attestor-svc-key}"
|
||||
RUSTFS__ACCOUNTS__ATTESTOR__BUCKETS: "attestations,dsse-envelopes,rekor-receipts"
|
||||
RUSTFS__ACCOUNTS__ATTESTOR__PERMISSIONS: "read,write"
|
||||
RUSTFS__ACCOUNTS__VERIFIER__KEY: "${RUSTFS_VERIFIER_KEY:-verifier-svc-key}"
|
||||
RUSTFS__ACCOUNTS__VERIFIER__BUCKETS: "attestations,dsse-envelopes,rekor-receipts"
|
||||
RUSTFS__ACCOUNTS__VERIFIER__PERMISSIONS: "read"
|
||||
volumes:
|
||||
- rustfs-attestation-data:/data
|
||||
ports:
|
||||
- "${RUSTFS_ATTESTATION_PORT:-8182}:8080"
|
||||
networks:
|
||||
- cas
|
||||
labels: *release-labels
|
||||
healthcheck:
|
||||
test: ["CMD", "curl", "-f", "http://localhost:8080/health"]
|
||||
interval: 30s
|
||||
timeout: 10s
|
||||
retries: 3
|
||||
start_period: 10s
|
||||
|
||||
# Lifecycle manager - enforces retention policies
|
||||
cas-lifecycle:
|
||||
image: registry.stella-ops.org/stellaops/cas-lifecycle:2025.10.0-edge
|
||||
restart: unless-stopped
|
||||
depends_on:
|
||||
rustfs-cas:
|
||||
condition: service_healthy
|
||||
environment:
|
||||
LIFECYCLE__CAS__ENDPOINT: "http://rustfs-cas:8080"
|
||||
LIFECYCLE__CAS__API_KEY: "${RUSTFS_CAS_API_KEY:-cas-api-key-change-me}"
|
||||
LIFECYCLE__SCHEDULE__CRON: "${LIFECYCLE_CRON:-0 3 * * *}" # 3 AM daily
|
||||
LIFECYCLE__POLICIES__VULNERABILITY_DB: "7d"
|
||||
LIFECYCLE__POLICIES__SBOM_ARTIFACTS: "365d"
|
||||
LIFECYCLE__POLICIES__SCAN_RESULTS: "90d"
|
||||
LIFECYCLE__POLICIES__TEMP_ARTIFACTS: "1d"
|
||||
LIFECYCLE__TELEMETRY__ENABLED: "${LIFECYCLE_TELEMETRY:-true}"
|
||||
LIFECYCLE__TELEMETRY__OTLP_ENDPOINT: "${OTLP_ENDPOINT:-}"
|
||||
networks:
|
||||
- cas
|
||||
labels: *release-labels
|
||||
@@ -1,301 +0,0 @@
|
||||
# StellaOps Docker Compose - International Profile
|
||||
# Cryptography: SM2, SM3, SM4 (ShangMi / Commercial Cipher - temporarily using NIST)
|
||||
# Provider: offline-verification
|
||||
# Jurisdiction: china, world
|
||||
|
||||
x-release-labels: &release-labels
|
||||
com.stellaops.release.version: "2025.10.0-edge"
|
||||
com.stellaops.release.channel: "edge"
|
||||
com.stellaops.profile: "china"
|
||||
com.stellaops.crypto.profile: "china"
|
||||
com.stellaops.crypto.provider: "offline-verification"
|
||||
|
||||
x-crypto-env: &crypto-env
|
||||
# Crypto configuration
|
||||
STELLAOPS_CRYPTO_PROFILE: "china"
|
||||
STELLAOPS_CRYPTO_CONFIG_PATH: "/app/etc/appsettings.crypto.yaml"
|
||||
STELLAOPS_CRYPTO_MANIFEST_PATH: "/app/etc/crypto-plugins-manifest.json"
|
||||
|
||||
networks:
|
||||
stellaops:
|
||||
driver: bridge
|
||||
|
||||
volumes:
|
||||
rustfs-data:
|
||||
concelier-jobs:
|
||||
nats-data:
|
||||
valkey-data:
|
||||
advisory-ai-queue:
|
||||
advisory-ai-plans:
|
||||
advisory-ai-outputs:
|
||||
postgres-data:
|
||||
|
||||
services:
|
||||
postgres:
|
||||
image: docker.io/library/postgres:16
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
POSTGRES_USER: "${POSTGRES_USER:-stellaops}"
|
||||
POSTGRES_PASSWORD: "${POSTGRES_PASSWORD:-stellaops}"
|
||||
POSTGRES_DB: "${POSTGRES_DB:-stellaops_platform}"
|
||||
PGDATA: /var/lib/postgresql/data/pgdata
|
||||
volumes:
|
||||
- postgres-data:/var/lib/postgresql/data
|
||||
- ../postgres-partitioning:/docker-entrypoint-initdb.d:ro
|
||||
ports:
|
||||
- "${POSTGRES_PORT:-5432}:5432"
|
||||
networks:
|
||||
- stellaops
|
||||
labels: *release-labels
|
||||
|
||||
valkey:
|
||||
image: docker.io/valkey/valkey:8.0
|
||||
restart: unless-stopped
|
||||
command: ["valkey-server", "--appendonly", "yes"]
|
||||
volumes:
|
||||
- valkey-data:/data
|
||||
ports:
|
||||
- "${VALKEY_PORT:-6379}:6379"
|
||||
networks:
|
||||
- stellaops
|
||||
labels: *release-labels
|
||||
|
||||
rustfs:
|
||||
image: registry.stella-ops.org/stellaops/rustfs:2025.10.0-edge
|
||||
command: ["serve", "--listen", "0.0.0.0:8080", "--root", "/data"]
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
RUSTFS__LOG__LEVEL: info
|
||||
RUSTFS__STORAGE__PATH: /data
|
||||
volumes:
|
||||
- rustfs-data:/data
|
||||
ports:
|
||||
- "${RUSTFS_HTTP_PORT:-8080}:8080"
|
||||
networks:
|
||||
- stellaops
|
||||
labels: *release-labels
|
||||
|
||||
nats:
|
||||
image: docker.io/library/nats@sha256:c82559e4476289481a8a5196e675ebfe67eea81d95e5161e3e78eccfe766608e
|
||||
command:
|
||||
- "-js"
|
||||
- "-sd"
|
||||
- /data
|
||||
restart: unless-stopped
|
||||
ports:
|
||||
- "${NATS_CLIENT_PORT:-4222}:4222"
|
||||
volumes:
|
||||
- nats-data:/data
|
||||
networks:
|
||||
- stellaops
|
||||
labels: *release-labels
|
||||
|
||||
authority:
|
||||
image: registry.stella-ops.org/stellaops/authority:china
|
||||
restart: unless-stopped
|
||||
depends_on:
|
||||
- postgres
|
||||
environment:
|
||||
<<: *crypto-env
|
||||
STELLAOPS_AUTHORITY__ISSUER: "${AUTHORITY_ISSUER}"
|
||||
STELLAOPS_AUTHORITY__STORAGE__DRIVER: "postgres"
|
||||
STELLAOPS_AUTHORITY__STORAGE__POSTGRES__CONNECTIONSTRING: "Host=postgres;Port=5432;Database=${POSTGRES_DB:-stellaops_platform};Username=${POSTGRES_USER:-stellaops};Password=${POSTGRES_PASSWORD:-stellaops}"
|
||||
STELLAOPS_AUTHORITY__PLUGINDIRECTORIES__0: "/app/plugins"
|
||||
STELLAOPS_AUTHORITY__PLUGINS__CONFIGURATIONDIRECTORY: "/app/etc/authority.plugins"
|
||||
volumes:
|
||||
- ../../etc/authority.yaml:/etc/authority.yaml:ro
|
||||
- ../../etc/authority.plugins:/app/etc/authority.plugins:ro
|
||||
- ../../etc/appsettings.crypto.china.yaml:/app/etc/appsettings.crypto.yaml:ro
|
||||
- ../../etc/crypto-plugins-manifest.json:/app/etc/crypto-plugins-manifest.json:ro
|
||||
ports:
|
||||
- "${AUTHORITY_PORT:-8440}:8440"
|
||||
networks:
|
||||
- stellaops
|
||||
labels: *release-labels
|
||||
|
||||
signer:
|
||||
image: registry.stella-ops.org/stellaops/signer:china
|
||||
restart: unless-stopped
|
||||
depends_on:
|
||||
- postgres
|
||||
environment:
|
||||
<<: *crypto-env
|
||||
STELLAOPS_SIGNER__STORAGE__DRIVER: "postgres"
|
||||
STELLAOPS_SIGNER__STORAGE__POSTGRES__CONNECTIONSTRING: "Host=postgres;Port=5432;Database=${POSTGRES_DB:-stellaops_platform};Username=${POSTGRES_USER:-stellaops};Password=${POSTGRES_PASSWORD:-stellaops}"
|
||||
volumes:
|
||||
- ../../etc/appsettings.crypto.china.yaml:/app/etc/appsettings.crypto.yaml:ro
|
||||
- ../../etc/crypto-plugins-manifest.json:/app/etc/crypto-plugins-manifest.json:ro
|
||||
ports:
|
||||
- "${SIGNER_PORT:-8441}:8441"
|
||||
networks:
|
||||
- stellaops
|
||||
labels: *release-labels
|
||||
|
||||
attestor:
|
||||
image: registry.stella-ops.org/stellaops/attestor:china
|
||||
restart: unless-stopped
|
||||
depends_on:
|
||||
- signer
|
||||
environment:
|
||||
<<: *crypto-env
|
||||
STELLAOPS_ATTESTOR__SIGNER__BASEURL: "http://signer:8441"
|
||||
volumes:
|
||||
- ../../etc/appsettings.crypto.china.yaml:/app/etc/appsettings.crypto.yaml:ro
|
||||
- ../../etc/crypto-plugins-manifest.json:/app/etc/crypto-plugins-manifest.json:ro
|
||||
ports:
|
||||
- "${ATTESTOR_PORT:-8442}:8442"
|
||||
networks:
|
||||
- stellaops
|
||||
labels: *release-labels
|
||||
|
||||
concelier:
|
||||
image: registry.stella-ops.org/stellaops/concelier:china
|
||||
restart: unless-stopped
|
||||
depends_on:
|
||||
- postgres
|
||||
- rustfs
|
||||
environment:
|
||||
<<: *crypto-env
|
||||
STELLAOPS_CONCELIER__STORAGE__DRIVER: "postgres"
|
||||
STELLAOPS_CONCELIER__STORAGE__POSTGRES__CONNECTIONSTRING: "Host=postgres;Port=5432;Database=${POSTGRES_DB:-stellaops_platform};Username=${POSTGRES_USER:-stellaops};Password=${POSTGRES_PASSWORD:-stellaops}"
|
||||
STELLAOPS_CONCELIER__STORAGE__RUSTFS__BASEURL: "http://rustfs:8080"
|
||||
volumes:
|
||||
- ../../etc/appsettings.crypto.china.yaml:/app/etc/appsettings.crypto.yaml:ro
|
||||
- ../../etc/crypto-plugins-manifest.json:/app/etc/crypto-plugins-manifest.json:ro
|
||||
- concelier-jobs:/app/jobs
|
||||
ports:
|
||||
- "${CONCELIER_PORT:-8443}:8443"
|
||||
networks:
|
||||
- stellaops
|
||||
labels: *release-labels
|
||||
|
||||
scanner:
|
||||
image: registry.stella-ops.org/stellaops/scanner:china
|
||||
restart: unless-stopped
|
||||
depends_on:
|
||||
- postgres
|
||||
environment:
|
||||
<<: *crypto-env
|
||||
STELLAOPS_SCANNER__STORAGE__DRIVER: "postgres"
|
||||
STELLAOPS_SCANNER__STORAGE__POSTGRES__CONNECTIONSTRING: "Host=postgres;Port=5432;Database=${POSTGRES_DB:-stellaops_platform};Username=${POSTGRES_USER:-stellaops};Password=${POSTGRES_PASSWORD:-stellaops}"
|
||||
volumes:
|
||||
- ../../etc/appsettings.crypto.china.yaml:/app/etc/appsettings.crypto.yaml:ro
|
||||
- ../../etc/crypto-plugins-manifest.json:/app/etc/crypto-plugins-manifest.json:ro
|
||||
ports:
|
||||
- "${SCANNER_PORT:-8444}:8444"
|
||||
networks:
|
||||
- stellaops
|
||||
labels: *release-labels
|
||||
|
||||
excititor:
|
||||
image: registry.stella-ops.org/stellaops/excititor:china
|
||||
restart: unless-stopped
|
||||
depends_on:
|
||||
- postgres
|
||||
environment:
|
||||
<<: *crypto-env
|
||||
STELLAOPS_EXCITITOR__STORAGE__DRIVER: "postgres"
|
||||
STELLAOPS_EXCITITOR__STORAGE__POSTGRES__CONNECTIONSTRING: "Host=postgres;Port=5432;Database=${POSTGRES_DB:-stellaops_platform};Username=${POSTGRES_USER:-stellaops};Password=${POSTGRES_PASSWORD:-stellaops}"
|
||||
volumes:
|
||||
- ../../etc/appsettings.crypto.china.yaml:/app/etc/appsettings.crypto.yaml:ro
|
||||
- ../../etc/crypto-plugins-manifest.json:/app/etc/crypto-plugins-manifest.json:ro
|
||||
ports:
|
||||
- "${EXCITITOR_PORT:-8445}:8445"
|
||||
networks:
|
||||
- stellaops
|
||||
labels: *release-labels
|
||||
|
||||
policy:
|
||||
image: registry.stella-ops.org/stellaops/policy:china
|
||||
restart: unless-stopped
|
||||
depends_on:
|
||||
- postgres
|
||||
environment:
|
||||
<<: *crypto-env
|
||||
STELLAOPS_POLICY__STORAGE__DRIVER: "postgres"
|
||||
STELLAOPS_POLICY__STORAGE__POSTGRES__CONNECTIONSTRING: "Host=postgres;Port=5432;Database=${POSTGRES_DB:-stellaops_platform};Username=${POSTGRES_USER:-stellaops};Password=${POSTGRES_PASSWORD:-stellaops}"
|
||||
volumes:
|
||||
- ../../etc/appsettings.crypto.china.yaml:/app/etc/appsettings.crypto.yaml:ro
|
||||
- ../../etc/crypto-plugins-manifest.json:/app/etc/crypto-plugins-manifest.json:ro
|
||||
ports:
|
||||
- "${POLICY_PORT:-8446}:8446"
|
||||
networks:
|
||||
- stellaops
|
||||
labels: *release-labels
|
||||
|
||||
scheduler:
|
||||
image: registry.stella-ops.org/stellaops/scheduler:china
|
||||
restart: unless-stopped
|
||||
depends_on:
|
||||
- postgres
|
||||
- nats
|
||||
environment:
|
||||
<<: *crypto-env
|
||||
STELLAOPS_SCHEDULER__STORAGE__DRIVER: "postgres"
|
||||
STELLAOPS_SCHEDULER__STORAGE__POSTGRES__CONNECTIONSTRING: "Host=postgres;Port=5432;Database=${POSTGRES_DB:-stellaops_platform};Username=${POSTGRES_USER:-stellaops};Password=${POSTGRES_PASSWORD:-stellaops}"
|
||||
STELLAOPS_SCHEDULER__MESSAGING__NATS__URL: "nats://nats:4222"
|
||||
volumes:
|
||||
- ../../etc/appsettings.crypto.china.yaml:/app/etc/appsettings.crypto.yaml:ro
|
||||
- ../../etc/crypto-plugins-manifest.json:/app/etc/crypto-plugins-manifest.json:ro
|
||||
ports:
|
||||
- "${SCHEDULER_PORT:-8447}:8447"
|
||||
networks:
|
||||
- stellaops
|
||||
labels: *release-labels
|
||||
|
||||
notify:
|
||||
image: registry.stella-ops.org/stellaops/notify:china
|
||||
restart: unless-stopped
|
||||
depends_on:
|
||||
- postgres
|
||||
environment:
|
||||
<<: *crypto-env
|
||||
STELLAOPS_NOTIFY__STORAGE__DRIVER: "postgres"
|
||||
STELLAOPS_NOTIFY__STORAGE__POSTGRES__CONNECTIONSTRING: "Host=postgres;Port=5432;Database=${POSTGRES_DB:-stellaops_platform};Username=${POSTGRES_USER:-stellaops};Password=${POSTGRES_PASSWORD:-stellaops}"
|
||||
volumes:
|
||||
- ../../etc/appsettings.crypto.china.yaml:/app/etc/appsettings.crypto.yaml:ro
|
||||
- ../../etc/crypto-plugins-manifest.json:/app/etc/crypto-plugins-manifest.json:ro
|
||||
ports:
|
||||
- "${NOTIFY_PORT:-8448}:8448"
|
||||
networks:
|
||||
- stellaops
|
||||
labels: *release-labels
|
||||
|
||||
zastava:
|
||||
image: registry.stella-ops.org/stellaops/zastava:china
|
||||
restart: unless-stopped
|
||||
depends_on:
|
||||
- postgres
|
||||
environment:
|
||||
<<: *crypto-env
|
||||
STELLAOPS_ZASTAVA__STORAGE__DRIVER: "postgres"
|
||||
STELLAOPS_ZASTAVA__STORAGE__POSTGRES__CONNECTIONSTRING: "Host=postgres;Port=5432;Database=${POSTGRES_DB:-stellaops_platform};Username=${POSTGRES_USER:-stellaops};Password=${POSTGRES_PASSWORD:-stellaops}"
|
||||
volumes:
|
||||
- ../../etc/appsettings.crypto.china.yaml:/app/etc/appsettings.crypto.yaml:ro
|
||||
- ../../etc/crypto-plugins-manifest.json:/app/etc/crypto-plugins-manifest.json:ro
|
||||
ports:
|
||||
- "${ZASTAVA_PORT:-8449}:8449"
|
||||
networks:
|
||||
- stellaops
|
||||
labels: *release-labels
|
||||
|
||||
gateway:
|
||||
image: registry.stella-ops.org/stellaops/gateway:china
|
||||
restart: unless-stopped
|
||||
depends_on:
|
||||
- authority
|
||||
- concelier
|
||||
- scanner
|
||||
environment:
|
||||
<<: *crypto-env
|
||||
STELLAOPS_GATEWAY__AUTHORITY__BASEURL: "http://authority:8440"
|
||||
STELLAOPS_GATEWAY__CONCELIER__BASEURL: "http://concelier:8443"
|
||||
STELLAOPS_GATEWAY__SCANNER__BASEURL: "http://scanner:8444"
|
||||
volumes:
|
||||
- ../../etc/appsettings.crypto.china.yaml:/app/etc/appsettings.crypto.yaml:ro
|
||||
- ../../etc/crypto-plugins-manifest.json:/app/etc/crypto-plugins-manifest.json:ro
|
||||
ports:
|
||||
- "${GATEWAY_PORT:-8080}:8080"
|
||||
networks:
|
||||
- stellaops
|
||||
labels: *release-labels
|
||||
@@ -1,353 +0,0 @@
|
||||
x-release-labels: &release-labels
|
||||
com.stellaops.release.version: "2025.10.0-edge"
|
||||
com.stellaops.release.channel: "edge"
|
||||
com.stellaops.profile: "dev"
|
||||
|
||||
networks:
|
||||
stellaops:
|
||||
driver: bridge
|
||||
|
||||
volumes:
|
||||
rustfs-data:
|
||||
concelier-jobs:
|
||||
nats-data:
|
||||
valkey-data:
|
||||
advisory-ai-queue:
|
||||
advisory-ai-plans:
|
||||
advisory-ai-outputs:
|
||||
postgres-data:
|
||||
|
||||
services:
|
||||
postgres:
|
||||
image: docker.io/library/postgres:16
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
POSTGRES_USER: "${POSTGRES_USER:-stellaops}"
|
||||
POSTGRES_PASSWORD: "${POSTGRES_PASSWORD:-stellaops}"
|
||||
POSTGRES_DB: "${POSTGRES_DB:-stellaops_platform}"
|
||||
PGDATA: /var/lib/postgresql/data/pgdata
|
||||
volumes:
|
||||
- postgres-data:/var/lib/postgresql/data
|
||||
ports:
|
||||
- "${POSTGRES_PORT:-5432}:5432"
|
||||
networks:
|
||||
- stellaops
|
||||
labels: *release-labels
|
||||
|
||||
valkey:
|
||||
image: docker.io/valkey/valkey:8.0
|
||||
restart: unless-stopped
|
||||
command: ["valkey-server", "--appendonly", "yes"]
|
||||
volumes:
|
||||
- valkey-data:/data
|
||||
ports:
|
||||
- "${VALKEY_PORT:-6379}:6379"
|
||||
networks:
|
||||
- stellaops
|
||||
labels: *release-labels
|
||||
|
||||
rustfs:
|
||||
image: registry.stella-ops.org/stellaops/rustfs:2025.10.0-edge
|
||||
command: ["serve", "--listen", "0.0.0.0:8080", "--root", "/data"]
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
RUSTFS__LOG__LEVEL: info
|
||||
RUSTFS__STORAGE__PATH: /data
|
||||
volumes:
|
||||
- rustfs-data:/data
|
||||
ports:
|
||||
- "${RUSTFS_HTTP_PORT:-8080}:8080"
|
||||
networks:
|
||||
- stellaops
|
||||
labels: *release-labels
|
||||
|
||||
nats:
|
||||
image: docker.io/library/nats@sha256:c82559e4476289481a8a5196e675ebfe67eea81d95e5161e3e78eccfe766608e
|
||||
command:
|
||||
- "-js"
|
||||
- "-sd"
|
||||
- /data
|
||||
restart: unless-stopped
|
||||
ports:
|
||||
- "${NATS_CLIENT_PORT:-4222}:4222"
|
||||
volumes:
|
||||
- nats-data:/data
|
||||
networks:
|
||||
- stellaops
|
||||
labels: *release-labels
|
||||
|
||||
authority:
|
||||
image: registry.stella-ops.org/stellaops/authority@sha256:a8e8faec44a579aa5714e58be835f25575710430b1ad2ccd1282a018cd9ffcdd
|
||||
restart: unless-stopped
|
||||
depends_on:
|
||||
- postgres
|
||||
environment:
|
||||
STELLAOPS_AUTHORITY__ISSUER: "${AUTHORITY_ISSUER}"
|
||||
STELLAOPS_AUTHORITY__STORAGE__DRIVER: "postgres"
|
||||
STELLAOPS_AUTHORITY__STORAGE__POSTGRES__CONNECTIONSTRING: "Host=postgres;Port=5432;Database=${POSTGRES_DB:-stellaops_platform};Username=${POSTGRES_USER:-stellaops};Password=${POSTGRES_PASSWORD:-stellaops}"
|
||||
STELLAOPS_AUTHORITY__PLUGINDIRECTORIES__0: "/app/plugins"
|
||||
STELLAOPS_AUTHORITY__PLUGINS__CONFIGURATIONDIRECTORY: "/app/etc/authority.plugins"
|
||||
volumes:
|
||||
- ../../etc/authority.yaml:/etc/authority.yaml:ro
|
||||
- ../../etc/authority.plugins:/app/etc/authority.plugins:ro
|
||||
ports:
|
||||
- "${AUTHORITY_PORT:-8440}:8440"
|
||||
networks:
|
||||
- stellaops
|
||||
labels: *release-labels
|
||||
|
||||
signer:
|
||||
image: registry.stella-ops.org/stellaops/signer@sha256:8bfef9a75783883d49fc18e3566553934e970b00ee090abee9cb110d2d5c3298
|
||||
restart: unless-stopped
|
||||
depends_on:
|
||||
- authority
|
||||
- valkey
|
||||
environment:
|
||||
SIGNER__AUTHORITY__BASEURL: "https://authority:8440"
|
||||
SIGNER__POE__INTROSPECTURL: "${SIGNER_POE_INTROSPECT_URL}"
|
||||
SIGNER__CACHE__REDIS__CONNECTIONSTRING: "valkey:6379"
|
||||
ports:
|
||||
- "${SIGNER_PORT:-8441}:8441"
|
||||
networks:
|
||||
- stellaops
|
||||
labels: *release-labels
|
||||
|
||||
attestor:
|
||||
image: registry.stella-ops.org/stellaops/attestor@sha256:5cc417948c029da01dccf36e4645d961a3f6d8de7e62fe98d845f07cd2282114
|
||||
restart: unless-stopped
|
||||
depends_on:
|
||||
- signer
|
||||
- valkey
|
||||
environment:
|
||||
ATTESTOR__SIGNER__BASEURL: "https://signer:8441"
|
||||
ATTESTOR__CACHE__REDIS__CONNECTIONSTRING: "valkey:6379"
|
||||
ports:
|
||||
- "${ATTESTOR_PORT:-8442}:8442"
|
||||
networks:
|
||||
- stellaops
|
||||
labels: *release-labels
|
||||
|
||||
issuer-directory:
|
||||
image: registry.stella-ops.org/stellaops/issuer-directory-web:2025.10.0-edge
|
||||
restart: unless-stopped
|
||||
depends_on:
|
||||
- postgres
|
||||
- authority
|
||||
environment:
|
||||
ISSUERDIRECTORY__CONFIG: "/etc/issuer-directory.yaml"
|
||||
ISSUERDIRECTORY__AUTHORITY__ISSUER: "${AUTHORITY_ISSUER}"
|
||||
ISSUERDIRECTORY__AUTHORITY__BASEURL: "https://authority:8440"
|
||||
ISSUERDIRECTORY__STORAGE__DRIVER: "postgres"
|
||||
ISSUERDIRECTORY__STORAGE__POSTGRES__CONNECTIONSTRING: "Host=postgres;Port=5432;Database=${POSTGRES_DB:-stellaops_platform};Username=${POSTGRES_USER:-stellaops};Password=${POSTGRES_PASSWORD:-stellaops}"
|
||||
ISSUERDIRECTORY__SEEDCSAFPUBLISHERS: "${ISSUER_DIRECTORY_SEED_CSAF:-true}"
|
||||
volumes:
|
||||
- ../../etc/issuer-directory.yaml:/etc/issuer-directory.yaml:ro
|
||||
ports:
|
||||
- "${ISSUER_DIRECTORY_PORT:-8447}:8080"
|
||||
networks:
|
||||
- stellaops
|
||||
labels: *release-labels
|
||||
|
||||
concelier:
|
||||
image: registry.stella-ops.org/stellaops/concelier@sha256:dafef3954eb4b837e2c424dd2d23e1e4d60fa83794840fac9cd3dea1d43bd085
|
||||
restart: unless-stopped
|
||||
depends_on:
|
||||
- postgres
|
||||
environment:
|
||||
CONCELIER__STORAGE__DRIVER: "postgres"
|
||||
CONCELIER__STORAGE__POSTGRES__CONNECTIONSTRING: "Host=postgres;Port=5432;Database=${POSTGRES_DB:-stellaops_platform};Username=${POSTGRES_USER:-stellaops};Password=${POSTGRES_PASSWORD:-stellaops}"
|
||||
CONCELIER__AUTHORITY__BASEURL: "https://authority:8440"
|
||||
volumes:
|
||||
- concelier-jobs:/var/lib/concelier/jobs
|
||||
ports:
|
||||
- "${CONCELIER_PORT:-8445}:8445"
|
||||
networks:
|
||||
- stellaops
|
||||
labels: *release-labels
|
||||
|
||||
scanner-web:
|
||||
image: registry.stella-ops.org/stellaops/scanner-web@sha256:e0dfdb087e330585a5953029fb4757f5abdf7610820a085bd61b457dbead9a11
|
||||
restart: unless-stopped
|
||||
depends_on:
|
||||
- postgres
|
||||
- concelier
|
||||
- rustfs
|
||||
- nats
|
||||
- valkey
|
||||
environment:
|
||||
SCANNER__STORAGE__DRIVER: "postgres"
|
||||
SCANNER__STORAGE__POSTGRES__CONNECTIONSTRING: "Host=postgres;Port=5432;Database=${POSTGRES_DB:-stellaops_platform};Username=${POSTGRES_USER:-stellaops};Password=${POSTGRES_PASSWORD:-stellaops}"
|
||||
SCANNER__ARTIFACTSTORE__DRIVER: "rustfs"
|
||||
SCANNER__ARTIFACTSTORE__ENDPOINT: "http://rustfs:8080/api/v1"
|
||||
SCANNER__ARTIFACTSTORE__BUCKET: "scanner-artifacts"
|
||||
SCANNER__ARTIFACTSTORE__TIMEOUTSECONDS: "30"
|
||||
SCANNER__QUEUE__BROKER: "nats://nats:4222"
|
||||
SCANNER__CACHE__REDIS__CONNECTIONSTRING: "valkey:6379"
|
||||
SCANNER__EVENTS__ENABLED: "${SCANNER_EVENTS_ENABLED:-false}"
|
||||
SCANNER__EVENTS__DRIVER: "${SCANNER_EVENTS_DRIVER:-valkey}"
|
||||
SCANNER__EVENTS__DSN: "${SCANNER_EVENTS_DSN:-valkey:6379}"
|
||||
SCANNER__EVENTS__STREAM: "${SCANNER_EVENTS_STREAM:-stella.events}"
|
||||
SCANNER__EVENTS__PUBLISHTIMEOUTSECONDS: "${SCANNER_EVENTS_PUBLISH_TIMEOUT_SECONDS:-5}"
|
||||
SCANNER__EVENTS__MAXSTREAMLENGTH: "${SCANNER_EVENTS_MAX_STREAM_LENGTH:-10000}"
|
||||
SCANNER__OFFLINEKIT__ENABLED: "${SCANNER_OFFLINEKIT_ENABLED:-false}"
|
||||
SCANNER__OFFLINEKIT__REQUIREDSSE: "${SCANNER_OFFLINEKIT_REQUIREDSSE:-true}"
|
||||
SCANNER__OFFLINEKIT__REKOROFFLINEMODE: "${SCANNER_OFFLINEKIT_REKOROFFLINEMODE:-true}"
|
||||
SCANNER__OFFLINEKIT__TRUSTROOTDIRECTORY: "${SCANNER_OFFLINEKIT_TRUSTROOTDIRECTORY:-/etc/stellaops/trust-roots}"
|
||||
SCANNER__OFFLINEKIT__REKORSNAPSHOTDIRECTORY: "${SCANNER_OFFLINEKIT_REKORSNAPSHOTDIRECTORY:-/var/lib/stellaops/rekor-snapshot}"
|
||||
volumes:
|
||||
- ${SCANNER_OFFLINEKIT_TRUSTROOTS_HOST_PATH:-./offline/trust-roots}:${SCANNER_OFFLINEKIT_TRUSTROOTDIRECTORY:-/etc/stellaops/trust-roots}:ro
|
||||
- ${SCANNER_OFFLINEKIT_REKOR_SNAPSHOT_HOST_PATH:-./offline/rekor-snapshot}:${SCANNER_OFFLINEKIT_REKORSNAPSHOTDIRECTORY:-/var/lib/stellaops/rekor-snapshot}:ro
|
||||
ports:
|
||||
- "${SCANNER_WEB_PORT:-8444}:8444"
|
||||
networks:
|
||||
- stellaops
|
||||
labels: *release-labels
|
||||
|
||||
scanner-worker:
|
||||
image: registry.stella-ops.org/stellaops/scanner-worker@sha256:92dda42f6f64b2d9522104a5c9ffb61d37b34dd193132b68457a259748008f37
|
||||
restart: unless-stopped
|
||||
depends_on:
|
||||
- scanner-web
|
||||
- rustfs
|
||||
- nats
|
||||
environment:
|
||||
SCANNER__STORAGE__DRIVER: "postgres"
|
||||
SCANNER__STORAGE__POSTGRES__CONNECTIONSTRING: "Host=postgres;Port=5432;Database=${POSTGRES_DB:-stellaops_platform};Username=${POSTGRES_USER:-stellaops};Password=${POSTGRES_PASSWORD:-stellaops}"
|
||||
SCANNER__ARTIFACTSTORE__DRIVER: "rustfs"
|
||||
SCANNER__ARTIFACTSTORE__ENDPOINT: "http://rustfs:8080/api/v1"
|
||||
SCANNER__ARTIFACTSTORE__BUCKET: "scanner-artifacts"
|
||||
SCANNER__ARTIFACTSTORE__TIMEOUTSECONDS: "30"
|
||||
SCANNER__QUEUE__BROKER: "nats://nats:4222"
|
||||
networks:
|
||||
- stellaops
|
||||
labels: *release-labels
|
||||
|
||||
scheduler-worker:
|
||||
image: registry.stella-ops.org/stellaops/scheduler-worker:2025.10.0-edge
|
||||
restart: unless-stopped
|
||||
depends_on:
|
||||
- postgres
|
||||
- nats
|
||||
- scanner-web
|
||||
command:
|
||||
- "dotnet"
|
||||
- "StellaOps.Scheduler.Worker.Host.dll"
|
||||
environment:
|
||||
SCHEDULER__QUEUE__KIND: "Nats"
|
||||
SCHEDULER__QUEUE__NATS__URL: "nats://nats:4222"
|
||||
SCHEDULER__STORAGE__DRIVER: "postgres"
|
||||
SCHEDULER__STORAGE__POSTGRES__CONNECTIONSTRING: "Host=postgres;Port=5432;Database=${POSTGRES_DB:-stellaops_platform};Username=${POSTGRES_USER:-stellaops};Password=${POSTGRES_PASSWORD:-stellaops}"
|
||||
SCHEDULER__WORKER__RUNNER__SCANNER__BASEADDRESS: "${SCHEDULER_SCANNER_BASEADDRESS:-http://scanner-web:8444}"
|
||||
networks:
|
||||
- stellaops
|
||||
labels: *release-labels
|
||||
|
||||
notify-web:
|
||||
image: ${NOTIFY_WEB_IMAGE:-registry.stella-ops.org/stellaops/notify-web:2025.10.0-edge}
|
||||
restart: unless-stopped
|
||||
depends_on:
|
||||
- postgres
|
||||
- authority
|
||||
- valkey
|
||||
environment:
|
||||
DOTNET_ENVIRONMENT: Development
|
||||
NOTIFY__STORAGE__DRIVER: "postgres"
|
||||
NOTIFY__STORAGE__POSTGRES__CONNECTIONSTRING: "Host=postgres;Port=5432;Database=${POSTGRES_DB:-stellaops_platform};Username=${POSTGRES_USER:-stellaops};Password=${POSTGRES_PASSWORD:-stellaops}"
|
||||
NOTIFY__QUEUE__DRIVER: "nats"
|
||||
NOTIFY__QUEUE__NATS__URL: "nats://nats:4222"
|
||||
volumes:
|
||||
- ../../etc/notify.dev.yaml:/app/etc/notify.yaml:ro
|
||||
ports:
|
||||
- "${NOTIFY_WEB_PORT:-8446}:8446"
|
||||
networks:
|
||||
- stellaops
|
||||
labels: *release-labels
|
||||
|
||||
excititor:
|
||||
image: registry.stella-ops.org/stellaops/excititor@sha256:d9bd5cadf1eab427447ce3df7302c30ded837239771cc6433b9befb895054285
|
||||
restart: unless-stopped
|
||||
depends_on:
|
||||
- postgres
|
||||
- concelier
|
||||
environment:
|
||||
EXCITITOR__CONCELIER__BASEURL: "https://concelier:8445"
|
||||
EXCITITOR__STORAGE__DRIVER: "postgres"
|
||||
EXCITITOR__STORAGE__POSTGRES__CONNECTIONSTRING: "Host=postgres;Port=5432;Database=${POSTGRES_DB:-stellaops_platform};Username=${POSTGRES_USER:-stellaops};Password=${POSTGRES_PASSWORD:-stellaops}"
|
||||
networks:
|
||||
- stellaops
|
||||
labels: *release-labels
|
||||
|
||||
advisory-ai-web:
|
||||
image: registry.stella-ops.org/stellaops/advisory-ai-web:2025.10.0-edge
|
||||
restart: unless-stopped
|
||||
depends_on:
|
||||
- scanner-web
|
||||
environment:
|
||||
ADVISORYAI__AdvisoryAI__SbomBaseAddress: "${ADVISORY_AI_SBOM_BASEADDRESS:-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: "${ADVISORY_AI_INFERENCE_MODE:-Local}"
|
||||
ADVISORYAI__AdvisoryAI__Inference__Remote__BaseAddress: "${ADVISORY_AI_REMOTE_BASEADDRESS:-}"
|
||||
ADVISORYAI__AdvisoryAI__Inference__Remote__ApiKey: "${ADVISORY_AI_REMOTE_APIKEY:-}"
|
||||
ports:
|
||||
- "${ADVISORY_AI_WEB_PORT:-8448}:8448"
|
||||
volumes:
|
||||
- advisory-ai-queue:/var/lib/advisory-ai/queue
|
||||
- advisory-ai-plans:/var/lib/advisory-ai/plans
|
||||
- advisory-ai-outputs:/var/lib/advisory-ai/outputs
|
||||
networks:
|
||||
- stellaops
|
||||
labels: *release-labels
|
||||
|
||||
advisory-ai-worker:
|
||||
image: registry.stella-ops.org/stellaops/advisory-ai-worker:2025.10.0-edge
|
||||
restart: unless-stopped
|
||||
depends_on:
|
||||
- advisory-ai-web
|
||||
environment:
|
||||
ADVISORYAI__AdvisoryAI__SbomBaseAddress: "${ADVISORY_AI_SBOM_BASEADDRESS:-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: "${ADVISORY_AI_INFERENCE_MODE:-Local}"
|
||||
ADVISORYAI__AdvisoryAI__Inference__Remote__BaseAddress: "${ADVISORY_AI_REMOTE_BASEADDRESS:-}"
|
||||
ADVISORYAI__AdvisoryAI__Inference__Remote__ApiKey: "${ADVISORY_AI_REMOTE_APIKEY:-}"
|
||||
volumes:
|
||||
- advisory-ai-queue:/var/lib/advisory-ai/queue
|
||||
- advisory-ai-plans:/var/lib/advisory-ai/plans
|
||||
- advisory-ai-outputs:/var/lib/advisory-ai/outputs
|
||||
networks:
|
||||
- stellaops
|
||||
labels: *release-labels
|
||||
|
||||
web-ui:
|
||||
image: registry.stella-ops.org/stellaops/web-ui@sha256:38b225fa7767a5b94ebae4dae8696044126aac429415e93de514d5dd95748dcf
|
||||
restart: unless-stopped
|
||||
depends_on:
|
||||
- scanner-web
|
||||
environment:
|
||||
STELLAOPS_UI__BACKEND__BASEURL: "https://scanner-web:8444"
|
||||
ports:
|
||||
- "${UI_PORT:-8443}:8443"
|
||||
networks:
|
||||
- stellaops
|
||||
labels: *release-labels
|
||||
|
||||
cryptopro-csp:
|
||||
build:
|
||||
context: ../..
|
||||
dockerfile: ops/cryptopro/linux-csp-service/Dockerfile
|
||||
args:
|
||||
CRYPTOPRO_ACCEPT_EULA: "${CRYPTOPRO_ACCEPT_EULA:-0}"
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
ASPNETCORE_URLS: "http://0.0.0.0:8080"
|
||||
CRYPTOPRO_ACCEPT_EULA: "${CRYPTOPRO_ACCEPT_EULA:-0}"
|
||||
volumes:
|
||||
- ../../opt/cryptopro/downloads:/opt/cryptopro/downloads:ro
|
||||
ports:
|
||||
- "${CRYPTOPRO_PORT:-18080}:8080"
|
||||
networks:
|
||||
- stellaops
|
||||
labels: *release-labels
|
||||
@@ -1,301 +0,0 @@
|
||||
# StellaOps Docker Compose - International Profile
|
||||
# Cryptography: eIDAS-compliant qualified trust services (temporarily using NIST)
|
||||
# Provider: offline-verification
|
||||
# Jurisdiction: eu, world
|
||||
|
||||
x-release-labels: &release-labels
|
||||
com.stellaops.release.version: "2025.10.0-edge"
|
||||
com.stellaops.release.channel: "edge"
|
||||
com.stellaops.profile: "eu"
|
||||
com.stellaops.crypto.profile: "eu"
|
||||
com.stellaops.crypto.provider: "offline-verification"
|
||||
|
||||
x-crypto-env: &crypto-env
|
||||
# Crypto configuration
|
||||
STELLAOPS_CRYPTO_PROFILE: "eu"
|
||||
STELLAOPS_CRYPTO_CONFIG_PATH: "/app/etc/appsettings.crypto.yaml"
|
||||
STELLAOPS_CRYPTO_MANIFEST_PATH: "/app/etc/crypto-plugins-manifest.json"
|
||||
|
||||
networks:
|
||||
stellaops:
|
||||
driver: bridge
|
||||
|
||||
volumes:
|
||||
rustfs-data:
|
||||
concelier-jobs:
|
||||
nats-data:
|
||||
valkey-data:
|
||||
advisory-ai-queue:
|
||||
advisory-ai-plans:
|
||||
advisory-ai-outputs:
|
||||
postgres-data:
|
||||
|
||||
services:
|
||||
postgres:
|
||||
image: docker.io/library/postgres:16
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
POSTGRES_USER: "${POSTGRES_USER:-stellaops}"
|
||||
POSTGRES_PASSWORD: "${POSTGRES_PASSWORD:-stellaops}"
|
||||
POSTGRES_DB: "${POSTGRES_DB:-stellaops_platform}"
|
||||
PGDATA: /var/lib/postgresql/data/pgdata
|
||||
volumes:
|
||||
- postgres-data:/var/lib/postgresql/data
|
||||
- ../postgres-partitioning:/docker-entrypoint-initdb.d:ro
|
||||
ports:
|
||||
- "${POSTGRES_PORT:-5432}:5432"
|
||||
networks:
|
||||
- stellaops
|
||||
labels: *release-labels
|
||||
|
||||
valkey:
|
||||
image: docker.io/valkey/valkey:8.0
|
||||
restart: unless-stopped
|
||||
command: ["valkey-server", "--appendonly", "yes"]
|
||||
volumes:
|
||||
- valkey-data:/data
|
||||
ports:
|
||||
- "${VALKEY_PORT:-6379}:6379"
|
||||
networks:
|
||||
- stellaops
|
||||
labels: *release-labels
|
||||
|
||||
rustfs:
|
||||
image: registry.stella-ops.org/stellaops/rustfs:2025.10.0-edge
|
||||
command: ["serve", "--listen", "0.0.0.0:8080", "--root", "/data"]
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
RUSTFS__LOG__LEVEL: info
|
||||
RUSTFS__STORAGE__PATH: /data
|
||||
volumes:
|
||||
- rustfs-data:/data
|
||||
ports:
|
||||
- "${RUSTFS_HTTP_PORT:-8080}:8080"
|
||||
networks:
|
||||
- stellaops
|
||||
labels: *release-labels
|
||||
|
||||
nats:
|
||||
image: docker.io/library/nats@sha256:c82559e4476289481a8a5196e675ebfe67eea81d95e5161e3e78eccfe766608e
|
||||
command:
|
||||
- "-js"
|
||||
- "-sd"
|
||||
- /data
|
||||
restart: unless-stopped
|
||||
ports:
|
||||
- "${NATS_CLIENT_PORT:-4222}:4222"
|
||||
volumes:
|
||||
- nats-data:/data
|
||||
networks:
|
||||
- stellaops
|
||||
labels: *release-labels
|
||||
|
||||
authority:
|
||||
image: registry.stella-ops.org/stellaops/authority:eu
|
||||
restart: unless-stopped
|
||||
depends_on:
|
||||
- postgres
|
||||
environment:
|
||||
<<: *crypto-env
|
||||
STELLAOPS_AUTHORITY__ISSUER: "${AUTHORITY_ISSUER}"
|
||||
STELLAOPS_AUTHORITY__STORAGE__DRIVER: "postgres"
|
||||
STELLAOPS_AUTHORITY__STORAGE__POSTGRES__CONNECTIONSTRING: "Host=postgres;Port=5432;Database=${POSTGRES_DB:-stellaops_platform};Username=${POSTGRES_USER:-stellaops};Password=${POSTGRES_PASSWORD:-stellaops}"
|
||||
STELLAOPS_AUTHORITY__PLUGINDIRECTORIES__0: "/app/plugins"
|
||||
STELLAOPS_AUTHORITY__PLUGINS__CONFIGURATIONDIRECTORY: "/app/etc/authority.plugins"
|
||||
volumes:
|
||||
- ../../etc/authority.yaml:/etc/authority.yaml:ro
|
||||
- ../../etc/authority.plugins:/app/etc/authority.plugins:ro
|
||||
- ../../etc/appsettings.crypto.eu.yaml:/app/etc/appsettings.crypto.yaml:ro
|
||||
- ../../etc/crypto-plugins-manifest.json:/app/etc/crypto-plugins-manifest.json:ro
|
||||
ports:
|
||||
- "${AUTHORITY_PORT:-8440}:8440"
|
||||
networks:
|
||||
- stellaops
|
||||
labels: *release-labels
|
||||
|
||||
signer:
|
||||
image: registry.stella-ops.org/stellaops/signer:eu
|
||||
restart: unless-stopped
|
||||
depends_on:
|
||||
- postgres
|
||||
environment:
|
||||
<<: *crypto-env
|
||||
STELLAOPS_SIGNER__STORAGE__DRIVER: "postgres"
|
||||
STELLAOPS_SIGNER__STORAGE__POSTGRES__CONNECTIONSTRING: "Host=postgres;Port=5432;Database=${POSTGRES_DB:-stellaops_platform};Username=${POSTGRES_USER:-stellaops};Password=${POSTGRES_PASSWORD:-stellaops}"
|
||||
volumes:
|
||||
- ../../etc/appsettings.crypto.eu.yaml:/app/etc/appsettings.crypto.yaml:ro
|
||||
- ../../etc/crypto-plugins-manifest.json:/app/etc/crypto-plugins-manifest.json:ro
|
||||
ports:
|
||||
- "${SIGNER_PORT:-8441}:8441"
|
||||
networks:
|
||||
- stellaops
|
||||
labels: *release-labels
|
||||
|
||||
attestor:
|
||||
image: registry.stella-ops.org/stellaops/attestor:eu
|
||||
restart: unless-stopped
|
||||
depends_on:
|
||||
- signer
|
||||
environment:
|
||||
<<: *crypto-env
|
||||
STELLAOPS_ATTESTOR__SIGNER__BASEURL: "http://signer:8441"
|
||||
volumes:
|
||||
- ../../etc/appsettings.crypto.eu.yaml:/app/etc/appsettings.crypto.yaml:ro
|
||||
- ../../etc/crypto-plugins-manifest.json:/app/etc/crypto-plugins-manifest.json:ro
|
||||
ports:
|
||||
- "${ATTESTOR_PORT:-8442}:8442"
|
||||
networks:
|
||||
- stellaops
|
||||
labels: *release-labels
|
||||
|
||||
concelier:
|
||||
image: registry.stella-ops.org/stellaops/concelier:eu
|
||||
restart: unless-stopped
|
||||
depends_on:
|
||||
- postgres
|
||||
- rustfs
|
||||
environment:
|
||||
<<: *crypto-env
|
||||
STELLAOPS_CONCELIER__STORAGE__DRIVER: "postgres"
|
||||
STELLAOPS_CONCELIER__STORAGE__POSTGRES__CONNECTIONSTRING: "Host=postgres;Port=5432;Database=${POSTGRES_DB:-stellaops_platform};Username=${POSTGRES_USER:-stellaops};Password=${POSTGRES_PASSWORD:-stellaops}"
|
||||
STELLAOPS_CONCELIER__STORAGE__RUSTFS__BASEURL: "http://rustfs:8080"
|
||||
volumes:
|
||||
- ../../etc/appsettings.crypto.eu.yaml:/app/etc/appsettings.crypto.yaml:ro
|
||||
- ../../etc/crypto-plugins-manifest.json:/app/etc/crypto-plugins-manifest.json:ro
|
||||
- concelier-jobs:/app/jobs
|
||||
ports:
|
||||
- "${CONCELIER_PORT:-8443}:8443"
|
||||
networks:
|
||||
- stellaops
|
||||
labels: *release-labels
|
||||
|
||||
scanner:
|
||||
image: registry.stella-ops.org/stellaops/scanner:eu
|
||||
restart: unless-stopped
|
||||
depends_on:
|
||||
- postgres
|
||||
environment:
|
||||
<<: *crypto-env
|
||||
STELLAOPS_SCANNER__STORAGE__DRIVER: "postgres"
|
||||
STELLAOPS_SCANNER__STORAGE__POSTGRES__CONNECTIONSTRING: "Host=postgres;Port=5432;Database=${POSTGRES_DB:-stellaops_platform};Username=${POSTGRES_USER:-stellaops};Password=${POSTGRES_PASSWORD:-stellaops}"
|
||||
volumes:
|
||||
- ../../etc/appsettings.crypto.eu.yaml:/app/etc/appsettings.crypto.yaml:ro
|
||||
- ../../etc/crypto-plugins-manifest.json:/app/etc/crypto-plugins-manifest.json:ro
|
||||
ports:
|
||||
- "${SCANNER_PORT:-8444}:8444"
|
||||
networks:
|
||||
- stellaops
|
||||
labels: *release-labels
|
||||
|
||||
excititor:
|
||||
image: registry.stella-ops.org/stellaops/excititor:eu
|
||||
restart: unless-stopped
|
||||
depends_on:
|
||||
- postgres
|
||||
environment:
|
||||
<<: *crypto-env
|
||||
STELLAOPS_EXCITITOR__STORAGE__DRIVER: "postgres"
|
||||
STELLAOPS_EXCITITOR__STORAGE__POSTGRES__CONNECTIONSTRING: "Host=postgres;Port=5432;Database=${POSTGRES_DB:-stellaops_platform};Username=${POSTGRES_USER:-stellaops};Password=${POSTGRES_PASSWORD:-stellaops}"
|
||||
volumes:
|
||||
- ../../etc/appsettings.crypto.eu.yaml:/app/etc/appsettings.crypto.yaml:ro
|
||||
- ../../etc/crypto-plugins-manifest.json:/app/etc/crypto-plugins-manifest.json:ro
|
||||
ports:
|
||||
- "${EXCITITOR_PORT:-8445}:8445"
|
||||
networks:
|
||||
- stellaops
|
||||
labels: *release-labels
|
||||
|
||||
policy:
|
||||
image: registry.stella-ops.org/stellaops/policy:eu
|
||||
restart: unless-stopped
|
||||
depends_on:
|
||||
- postgres
|
||||
environment:
|
||||
<<: *crypto-env
|
||||
STELLAOPS_POLICY__STORAGE__DRIVER: "postgres"
|
||||
STELLAOPS_POLICY__STORAGE__POSTGRES__CONNECTIONSTRING: "Host=postgres;Port=5432;Database=${POSTGRES_DB:-stellaops_platform};Username=${POSTGRES_USER:-stellaops};Password=${POSTGRES_PASSWORD:-stellaops}"
|
||||
volumes:
|
||||
- ../../etc/appsettings.crypto.eu.yaml:/app/etc/appsettings.crypto.yaml:ro
|
||||
- ../../etc/crypto-plugins-manifest.json:/app/etc/crypto-plugins-manifest.json:ro
|
||||
ports:
|
||||
- "${POLICY_PORT:-8446}:8446"
|
||||
networks:
|
||||
- stellaops
|
||||
labels: *release-labels
|
||||
|
||||
scheduler:
|
||||
image: registry.stella-ops.org/stellaops/scheduler:eu
|
||||
restart: unless-stopped
|
||||
depends_on:
|
||||
- postgres
|
||||
- nats
|
||||
environment:
|
||||
<<: *crypto-env
|
||||
STELLAOPS_SCHEDULER__STORAGE__DRIVER: "postgres"
|
||||
STELLAOPS_SCHEDULER__STORAGE__POSTGRES__CONNECTIONSTRING: "Host=postgres;Port=5432;Database=${POSTGRES_DB:-stellaops_platform};Username=${POSTGRES_USER:-stellaops};Password=${POSTGRES_PASSWORD:-stellaops}"
|
||||
STELLAOPS_SCHEDULER__MESSAGING__NATS__URL: "nats://nats:4222"
|
||||
volumes:
|
||||
- ../../etc/appsettings.crypto.eu.yaml:/app/etc/appsettings.crypto.yaml:ro
|
||||
- ../../etc/crypto-plugins-manifest.json:/app/etc/crypto-plugins-manifest.json:ro
|
||||
ports:
|
||||
- "${SCHEDULER_PORT:-8447}:8447"
|
||||
networks:
|
||||
- stellaops
|
||||
labels: *release-labels
|
||||
|
||||
notify:
|
||||
image: registry.stella-ops.org/stellaops/notify:eu
|
||||
restart: unless-stopped
|
||||
depends_on:
|
||||
- postgres
|
||||
environment:
|
||||
<<: *crypto-env
|
||||
STELLAOPS_NOTIFY__STORAGE__DRIVER: "postgres"
|
||||
STELLAOPS_NOTIFY__STORAGE__POSTGRES__CONNECTIONSTRING: "Host=postgres;Port=5432;Database=${POSTGRES_DB:-stellaops_platform};Username=${POSTGRES_USER:-stellaops};Password=${POSTGRES_PASSWORD:-stellaops}"
|
||||
volumes:
|
||||
- ../../etc/appsettings.crypto.eu.yaml:/app/etc/appsettings.crypto.yaml:ro
|
||||
- ../../etc/crypto-plugins-manifest.json:/app/etc/crypto-plugins-manifest.json:ro
|
||||
ports:
|
||||
- "${NOTIFY_PORT:-8448}:8448"
|
||||
networks:
|
||||
- stellaops
|
||||
labels: *release-labels
|
||||
|
||||
zastava:
|
||||
image: registry.stella-ops.org/stellaops/zastava:eu
|
||||
restart: unless-stopped
|
||||
depends_on:
|
||||
- postgres
|
||||
environment:
|
||||
<<: *crypto-env
|
||||
STELLAOPS_ZASTAVA__STORAGE__DRIVER: "postgres"
|
||||
STELLAOPS_ZASTAVA__STORAGE__POSTGRES__CONNECTIONSTRING: "Host=postgres;Port=5432;Database=${POSTGRES_DB:-stellaops_platform};Username=${POSTGRES_USER:-stellaops};Password=${POSTGRES_PASSWORD:-stellaops}"
|
||||
volumes:
|
||||
- ../../etc/appsettings.crypto.eu.yaml:/app/etc/appsettings.crypto.yaml:ro
|
||||
- ../../etc/crypto-plugins-manifest.json:/app/etc/crypto-plugins-manifest.json:ro
|
||||
ports:
|
||||
- "${ZASTAVA_PORT:-8449}:8449"
|
||||
networks:
|
||||
- stellaops
|
||||
labels: *release-labels
|
||||
|
||||
gateway:
|
||||
image: registry.stella-ops.org/stellaops/gateway:eu
|
||||
restart: unless-stopped
|
||||
depends_on:
|
||||
- authority
|
||||
- concelier
|
||||
- scanner
|
||||
environment:
|
||||
<<: *crypto-env
|
||||
STELLAOPS_GATEWAY__AUTHORITY__BASEURL: "http://authority:8440"
|
||||
STELLAOPS_GATEWAY__CONCELIER__BASEURL: "http://concelier:8443"
|
||||
STELLAOPS_GATEWAY__SCANNER__BASEURL: "http://scanner:8444"
|
||||
volumes:
|
||||
- ../../etc/appsettings.crypto.eu.yaml:/app/etc/appsettings.crypto.yaml:ro
|
||||
- ../../etc/crypto-plugins-manifest.json:/app/etc/crypto-plugins-manifest.json:ro
|
||||
ports:
|
||||
- "${GATEWAY_PORT:-8080}:8080"
|
||||
networks:
|
||||
- stellaops
|
||||
labels: *release-labels
|
||||
@@ -1,26 +0,0 @@
|
||||
version: "3.9"
|
||||
|
||||
services:
|
||||
advisory-ai-worker:
|
||||
deploy:
|
||||
resources:
|
||||
reservations:
|
||||
devices:
|
||||
- capabilities: [gpu]
|
||||
driver: nvidia
|
||||
count: 1
|
||||
environment:
|
||||
ADVISORY_AI_INFERENCE_GPU: "true"
|
||||
runtime: nvidia
|
||||
|
||||
advisory-ai-web:
|
||||
deploy:
|
||||
resources:
|
||||
reservations:
|
||||
devices:
|
||||
- capabilities: [gpu]
|
||||
driver: nvidia
|
||||
count: 1
|
||||
environment:
|
||||
ADVISORY_AI_INFERENCE_GPU: "true"
|
||||
runtime: nvidia
|
||||
@@ -1,301 +0,0 @@
|
||||
# StellaOps Docker Compose - International Profile
|
||||
# Cryptography: Standard NIST algorithms (ECDSA, RSA, SHA-2)
|
||||
# Provider: offline-verification
|
||||
# Jurisdiction: world
|
||||
|
||||
x-release-labels: &release-labels
|
||||
com.stellaops.release.version: "2025.10.0-edge"
|
||||
com.stellaops.release.channel: "edge"
|
||||
com.stellaops.profile: "international"
|
||||
com.stellaops.crypto.profile: "international"
|
||||
com.stellaops.crypto.provider: "offline-verification"
|
||||
|
||||
x-crypto-env: &crypto-env
|
||||
# Crypto configuration
|
||||
STELLAOPS_CRYPTO_PROFILE: "international"
|
||||
STELLAOPS_CRYPTO_CONFIG_PATH: "/app/etc/appsettings.crypto.yaml"
|
||||
STELLAOPS_CRYPTO_MANIFEST_PATH: "/app/etc/crypto-plugins-manifest.json"
|
||||
|
||||
networks:
|
||||
stellaops:
|
||||
driver: bridge
|
||||
|
||||
volumes:
|
||||
rustfs-data:
|
||||
concelier-jobs:
|
||||
nats-data:
|
||||
valkey-data:
|
||||
advisory-ai-queue:
|
||||
advisory-ai-plans:
|
||||
advisory-ai-outputs:
|
||||
postgres-data:
|
||||
|
||||
services:
|
||||
postgres:
|
||||
image: docker.io/library/postgres:16
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
POSTGRES_USER: "${POSTGRES_USER:-stellaops}"
|
||||
POSTGRES_PASSWORD: "${POSTGRES_PASSWORD:-stellaops}"
|
||||
POSTGRES_DB: "${POSTGRES_DB:-stellaops_platform}"
|
||||
PGDATA: /var/lib/postgresql/data/pgdata
|
||||
volumes:
|
||||
- postgres-data:/var/lib/postgresql/data
|
||||
- ../postgres-partitioning:/docker-entrypoint-initdb.d:ro
|
||||
ports:
|
||||
- "${POSTGRES_PORT:-5432}:5432"
|
||||
networks:
|
||||
- stellaops
|
||||
labels: *release-labels
|
||||
|
||||
valkey:
|
||||
image: docker.io/valkey/valkey:8.0
|
||||
restart: unless-stopped
|
||||
command: ["valkey-server", "--appendonly", "yes"]
|
||||
volumes:
|
||||
- valkey-data:/data
|
||||
ports:
|
||||
- "${VALKEY_PORT:-6379}:6379"
|
||||
networks:
|
||||
- stellaops
|
||||
labels: *release-labels
|
||||
|
||||
rustfs:
|
||||
image: registry.stella-ops.org/stellaops/rustfs:2025.10.0-edge
|
||||
command: ["serve", "--listen", "0.0.0.0:8080", "--root", "/data"]
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
RUSTFS__LOG__LEVEL: info
|
||||
RUSTFS__STORAGE__PATH: /data
|
||||
volumes:
|
||||
- rustfs-data:/data
|
||||
ports:
|
||||
- "${RUSTFS_HTTP_PORT:-8080}:8080"
|
||||
networks:
|
||||
- stellaops
|
||||
labels: *release-labels
|
||||
|
||||
nats:
|
||||
image: docker.io/library/nats@sha256:c82559e4476289481a8a5196e675ebfe67eea81d95e5161e3e78eccfe766608e
|
||||
command:
|
||||
- "-js"
|
||||
- "-sd"
|
||||
- /data
|
||||
restart: unless-stopped
|
||||
ports:
|
||||
- "${NATS_CLIENT_PORT:-4222}:4222"
|
||||
volumes:
|
||||
- nats-data:/data
|
||||
networks:
|
||||
- stellaops
|
||||
labels: *release-labels
|
||||
|
||||
authority:
|
||||
image: registry.stella-ops.org/stellaops/authority:international
|
||||
restart: unless-stopped
|
||||
depends_on:
|
||||
- postgres
|
||||
environment:
|
||||
<<: *crypto-env
|
||||
STELLAOPS_AUTHORITY__ISSUER: "${AUTHORITY_ISSUER}"
|
||||
STELLAOPS_AUTHORITY__STORAGE__DRIVER: "postgres"
|
||||
STELLAOPS_AUTHORITY__STORAGE__POSTGRES__CONNECTIONSTRING: "Host=postgres;Port=5432;Database=${POSTGRES_DB:-stellaops_platform};Username=${POSTGRES_USER:-stellaops};Password=${POSTGRES_PASSWORD:-stellaops}"
|
||||
STELLAOPS_AUTHORITY__PLUGINDIRECTORIES__0: "/app/plugins"
|
||||
STELLAOPS_AUTHORITY__PLUGINS__CONFIGURATIONDIRECTORY: "/app/etc/authority.plugins"
|
||||
volumes:
|
||||
- ../../etc/authority.yaml:/etc/authority.yaml:ro
|
||||
- ../../etc/authority.plugins:/app/etc/authority.plugins:ro
|
||||
- ../../etc/appsettings.crypto.international.yaml:/app/etc/appsettings.crypto.yaml:ro
|
||||
- ../../etc/crypto-plugins-manifest.json:/app/etc/crypto-plugins-manifest.json:ro
|
||||
ports:
|
||||
- "${AUTHORITY_PORT:-8440}:8440"
|
||||
networks:
|
||||
- stellaops
|
||||
labels: *release-labels
|
||||
|
||||
signer:
|
||||
image: registry.stella-ops.org/stellaops/signer:international
|
||||
restart: unless-stopped
|
||||
depends_on:
|
||||
- postgres
|
||||
environment:
|
||||
<<: *crypto-env
|
||||
STELLAOPS_SIGNER__STORAGE__DRIVER: "postgres"
|
||||
STELLAOPS_SIGNER__STORAGE__POSTGRES__CONNECTIONSTRING: "Host=postgres;Port=5432;Database=${POSTGRES_DB:-stellaops_platform};Username=${POSTGRES_USER:-stellaops};Password=${POSTGRES_PASSWORD:-stellaops}"
|
||||
volumes:
|
||||
- ../../etc/appsettings.crypto.international.yaml:/app/etc/appsettings.crypto.yaml:ro
|
||||
- ../../etc/crypto-plugins-manifest.json:/app/etc/crypto-plugins-manifest.json:ro
|
||||
ports:
|
||||
- "${SIGNER_PORT:-8441}:8441"
|
||||
networks:
|
||||
- stellaops
|
||||
labels: *release-labels
|
||||
|
||||
attestor:
|
||||
image: registry.stella-ops.org/stellaops/attestor:international
|
||||
restart: unless-stopped
|
||||
depends_on:
|
||||
- signer
|
||||
environment:
|
||||
<<: *crypto-env
|
||||
STELLAOPS_ATTESTOR__SIGNER__BASEURL: "http://signer:8441"
|
||||
volumes:
|
||||
- ../../etc/appsettings.crypto.international.yaml:/app/etc/appsettings.crypto.yaml:ro
|
||||
- ../../etc/crypto-plugins-manifest.json:/app/etc/crypto-plugins-manifest.json:ro
|
||||
ports:
|
||||
- "${ATTESTOR_PORT:-8442}:8442"
|
||||
networks:
|
||||
- stellaops
|
||||
labels: *release-labels
|
||||
|
||||
concelier:
|
||||
image: registry.stella-ops.org/stellaops/concelier:international
|
||||
restart: unless-stopped
|
||||
depends_on:
|
||||
- postgres
|
||||
- rustfs
|
||||
environment:
|
||||
<<: *crypto-env
|
||||
STELLAOPS_CONCELIER__STORAGE__DRIVER: "postgres"
|
||||
STELLAOPS_CONCELIER__STORAGE__POSTGRES__CONNECTIONSTRING: "Host=postgres;Port=5432;Database=${POSTGRES_DB:-stellaops_platform};Username=${POSTGRES_USER:-stellaops};Password=${POSTGRES_PASSWORD:-stellaops}"
|
||||
STELLAOPS_CONCELIER__STORAGE__RUSTFS__BASEURL: "http://rustfs:8080"
|
||||
volumes:
|
||||
- ../../etc/appsettings.crypto.international.yaml:/app/etc/appsettings.crypto.yaml:ro
|
||||
- ../../etc/crypto-plugins-manifest.json:/app/etc/crypto-plugins-manifest.json:ro
|
||||
- concelier-jobs:/app/jobs
|
||||
ports:
|
||||
- "${CONCELIER_PORT:-8443}:8443"
|
||||
networks:
|
||||
- stellaops
|
||||
labels: *release-labels
|
||||
|
||||
scanner:
|
||||
image: registry.stella-ops.org/stellaops/scanner:international
|
||||
restart: unless-stopped
|
||||
depends_on:
|
||||
- postgres
|
||||
environment:
|
||||
<<: *crypto-env
|
||||
STELLAOPS_SCANNER__STORAGE__DRIVER: "postgres"
|
||||
STELLAOPS_SCANNER__STORAGE__POSTGRES__CONNECTIONSTRING: "Host=postgres;Port=5432;Database=${POSTGRES_DB:-stellaops_platform};Username=${POSTGRES_USER:-stellaops};Password=${POSTGRES_PASSWORD:-stellaops}"
|
||||
volumes:
|
||||
- ../../etc/appsettings.crypto.international.yaml:/app/etc/appsettings.crypto.yaml:ro
|
||||
- ../../etc/crypto-plugins-manifest.json:/app/etc/crypto-plugins-manifest.json:ro
|
||||
ports:
|
||||
- "${SCANNER_PORT:-8444}:8444"
|
||||
networks:
|
||||
- stellaops
|
||||
labels: *release-labels
|
||||
|
||||
excititor:
|
||||
image: registry.stella-ops.org/stellaops/excititor:international
|
||||
restart: unless-stopped
|
||||
depends_on:
|
||||
- postgres
|
||||
environment:
|
||||
<<: *crypto-env
|
||||
STELLAOPS_EXCITITOR__STORAGE__DRIVER: "postgres"
|
||||
STELLAOPS_EXCITITOR__STORAGE__POSTGRES__CONNECTIONSTRING: "Host=postgres;Port=5432;Database=${POSTGRES_DB:-stellaops_platform};Username=${POSTGRES_USER:-stellaops};Password=${POSTGRES_PASSWORD:-stellaops}"
|
||||
volumes:
|
||||
- ../../etc/appsettings.crypto.international.yaml:/app/etc/appsettings.crypto.yaml:ro
|
||||
- ../../etc/crypto-plugins-manifest.json:/app/etc/crypto-plugins-manifest.json:ro
|
||||
ports:
|
||||
- "${EXCITITOR_PORT:-8445}:8445"
|
||||
networks:
|
||||
- stellaops
|
||||
labels: *release-labels
|
||||
|
||||
policy:
|
||||
image: registry.stella-ops.org/stellaops/policy:international
|
||||
restart: unless-stopped
|
||||
depends_on:
|
||||
- postgres
|
||||
environment:
|
||||
<<: *crypto-env
|
||||
STELLAOPS_POLICY__STORAGE__DRIVER: "postgres"
|
||||
STELLAOPS_POLICY__STORAGE__POSTGRES__CONNECTIONSTRING: "Host=postgres;Port=5432;Database=${POSTGRES_DB:-stellaops_platform};Username=${POSTGRES_USER:-stellaops};Password=${POSTGRES_PASSWORD:-stellaops}"
|
||||
volumes:
|
||||
- ../../etc/appsettings.crypto.international.yaml:/app/etc/appsettings.crypto.yaml:ro
|
||||
- ../../etc/crypto-plugins-manifest.json:/app/etc/crypto-plugins-manifest.json:ro
|
||||
ports:
|
||||
- "${POLICY_PORT:-8446}:8446"
|
||||
networks:
|
||||
- stellaops
|
||||
labels: *release-labels
|
||||
|
||||
scheduler:
|
||||
image: registry.stella-ops.org/stellaops/scheduler:international
|
||||
restart: unless-stopped
|
||||
depends_on:
|
||||
- postgres
|
||||
- nats
|
||||
environment:
|
||||
<<: *crypto-env
|
||||
STELLAOPS_SCHEDULER__STORAGE__DRIVER: "postgres"
|
||||
STELLAOPS_SCHEDULER__STORAGE__POSTGRES__CONNECTIONSTRING: "Host=postgres;Port=5432;Database=${POSTGRES_DB:-stellaops_platform};Username=${POSTGRES_USER:-stellaops};Password=${POSTGRES_PASSWORD:-stellaops}"
|
||||
STELLAOPS_SCHEDULER__MESSAGING__NATS__URL: "nats://nats:4222"
|
||||
volumes:
|
||||
- ../../etc/appsettings.crypto.international.yaml:/app/etc/appsettings.crypto.yaml:ro
|
||||
- ../../etc/crypto-plugins-manifest.json:/app/etc/crypto-plugins-manifest.json:ro
|
||||
ports:
|
||||
- "${SCHEDULER_PORT:-8447}:8447"
|
||||
networks:
|
||||
- stellaops
|
||||
labels: *release-labels
|
||||
|
||||
notify:
|
||||
image: registry.stella-ops.org/stellaops/notify:international
|
||||
restart: unless-stopped
|
||||
depends_on:
|
||||
- postgres
|
||||
environment:
|
||||
<<: *crypto-env
|
||||
STELLAOPS_NOTIFY__STORAGE__DRIVER: "postgres"
|
||||
STELLAOPS_NOTIFY__STORAGE__POSTGRES__CONNECTIONSTRING: "Host=postgres;Port=5432;Database=${POSTGRES_DB:-stellaops_platform};Username=${POSTGRES_USER:-stellaops};Password=${POSTGRES_PASSWORD:-stellaops}"
|
||||
volumes:
|
||||
- ../../etc/appsettings.crypto.international.yaml:/app/etc/appsettings.crypto.yaml:ro
|
||||
- ../../etc/crypto-plugins-manifest.json:/app/etc/crypto-plugins-manifest.json:ro
|
||||
ports:
|
||||
- "${NOTIFY_PORT:-8448}:8448"
|
||||
networks:
|
||||
- stellaops
|
||||
labels: *release-labels
|
||||
|
||||
zastava:
|
||||
image: registry.stella-ops.org/stellaops/zastava:international
|
||||
restart: unless-stopped
|
||||
depends_on:
|
||||
- postgres
|
||||
environment:
|
||||
<<: *crypto-env
|
||||
STELLAOPS_ZASTAVA__STORAGE__DRIVER: "postgres"
|
||||
STELLAOPS_ZASTAVA__STORAGE__POSTGRES__CONNECTIONSTRING: "Host=postgres;Port=5432;Database=${POSTGRES_DB:-stellaops_platform};Username=${POSTGRES_USER:-stellaops};Password=${POSTGRES_PASSWORD:-stellaops}"
|
||||
volumes:
|
||||
- ../../etc/appsettings.crypto.international.yaml:/app/etc/appsettings.crypto.yaml:ro
|
||||
- ../../etc/crypto-plugins-manifest.json:/app/etc/crypto-plugins-manifest.json:ro
|
||||
ports:
|
||||
- "${ZASTAVA_PORT:-8449}:8449"
|
||||
networks:
|
||||
- stellaops
|
||||
labels: *release-labels
|
||||
|
||||
gateway:
|
||||
image: registry.stella-ops.org/stellaops/gateway:international
|
||||
restart: unless-stopped
|
||||
depends_on:
|
||||
- authority
|
||||
- concelier
|
||||
- scanner
|
||||
environment:
|
||||
<<: *crypto-env
|
||||
STELLAOPS_GATEWAY__AUTHORITY__BASEURL: "http://authority:8440"
|
||||
STELLAOPS_GATEWAY__CONCELIER__BASEURL: "http://concelier:8443"
|
||||
STELLAOPS_GATEWAY__SCANNER__BASEURL: "http://scanner:8444"
|
||||
volumes:
|
||||
- ../../etc/appsettings.crypto.international.yaml:/app/etc/appsettings.crypto.yaml:ro
|
||||
- ../../etc/crypto-plugins-manifest.json:/app/etc/crypto-plugins-manifest.json:ro
|
||||
ports:
|
||||
- "${GATEWAY_PORT:-8080}:8080"
|
||||
networks:
|
||||
- stellaops
|
||||
labels: *release-labels
|
||||
@@ -1,152 +0,0 @@
|
||||
x-release-labels: &release-labels
|
||||
com.stellaops.release.version: "2025.10.0-edge"
|
||||
com.stellaops.release.channel: "edge"
|
||||
com.stellaops.profile: "mirror-managed"
|
||||
|
||||
networks:
|
||||
mirror:
|
||||
driver: bridge
|
||||
|
||||
volumes:
|
||||
mongo-data:
|
||||
minio-data:
|
||||
concelier-jobs:
|
||||
concelier-exports:
|
||||
excititor-exports:
|
||||
nginx-cache:
|
||||
|
||||
services:
|
||||
mongo:
|
||||
image: docker.io/library/mongo@sha256:c258b26dbb7774f97f52aff52231ca5f228273a84329c5f5e451c3739457db49
|
||||
command: ["mongod", "--bind_ip_all"]
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
MONGO_INITDB_ROOT_USERNAME: "${MONGO_INITDB_ROOT_USERNAME:-stellaops_mirror}"
|
||||
MONGO_INITDB_ROOT_PASSWORD: "${MONGO_INITDB_ROOT_PASSWORD:-mirror-password}"
|
||||
volumes:
|
||||
- mongo-data:/data/db
|
||||
networks:
|
||||
- mirror
|
||||
labels: *release-labels
|
||||
|
||||
minio:
|
||||
image: docker.io/minio/minio@sha256:14cea493d9a34af32f524e538b8346cf79f3321eff8e708c1e2960462bd8936e
|
||||
command: ["server", "/data", "--console-address", ":9001"]
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
MINIO_ROOT_USER: "${MINIO_ROOT_USER:-stellaops-mirror}"
|
||||
MINIO_ROOT_PASSWORD: "${MINIO_ROOT_PASSWORD:-mirror-minio-secret}"
|
||||
volumes:
|
||||
- minio-data:/data
|
||||
networks:
|
||||
- mirror
|
||||
labels: *release-labels
|
||||
|
||||
concelier:
|
||||
image: registry.stella-ops.org/stellaops/concelier@sha256:dafef3954eb4b837e2c424dd2d23e1e4d60fa83794840fac9cd3dea1d43bd085
|
||||
restart: unless-stopped
|
||||
depends_on:
|
||||
- mongo
|
||||
- minio
|
||||
environment:
|
||||
ASPNETCORE_URLS: "http://+:8445"
|
||||
CONCELIER__STORAGE__MONGO__CONNECTIONSTRING: "mongodb://${MONGO_INITDB_ROOT_USERNAME:-stellaops_mirror}:${MONGO_INITDB_ROOT_PASSWORD:-mirror-password}@mongo:27017/concelier?authSource=admin"
|
||||
CONCELIER__STORAGE__S3__ENDPOINT: "http://minio:9000"
|
||||
CONCELIER__STORAGE__S3__ACCESSKEYID: "${MINIO_ROOT_USER:-stellaops-mirror}"
|
||||
CONCELIER__STORAGE__S3__SECRETACCESSKEY: "${MINIO_ROOT_PASSWORD:-mirror-minio-secret}"
|
||||
CONCELIER__TELEMETRY__SERVICENAME: "stellaops-concelier-mirror"
|
||||
CONCELIER__MIRROR__ENABLED: "true"
|
||||
CONCELIER__MIRROR__EXPORTROOT: "/exports/json"
|
||||
CONCELIER__MIRROR__LATESTDIRECTORYNAME: "${CONCELIER_MIRROR_LATEST_SEGMENT:-latest}"
|
||||
CONCELIER__MIRROR__MIRRORDIRECTORYNAME: "${CONCELIER_MIRROR_DIRECTORY_SEGMENT:-mirror}"
|
||||
CONCELIER__MIRROR__REQUIREAUTHENTICATION: "${CONCELIER_MIRROR_REQUIRE_AUTH:-true}"
|
||||
CONCELIER__MIRROR__MAXINDEXREQUESTSPERHOUR: "${CONCELIER_MIRROR_INDEX_BUDGET:-600}"
|
||||
CONCELIER__MIRROR__DOMAINS__0__ID: "${CONCELIER_MIRROR_DOMAIN_PRIMARY_ID:-primary}"
|
||||
CONCELIER__MIRROR__DOMAINS__0__DISPLAYNAME: "${CONCELIER_MIRROR_DOMAIN_PRIMARY_NAME:-Primary Mirror}"
|
||||
CONCELIER__MIRROR__DOMAINS__0__REQUIREAUTHENTICATION: "${CONCELIER_MIRROR_DOMAIN_PRIMARY_AUTH:-true}"
|
||||
CONCELIER__MIRROR__DOMAINS__0__MAXDOWNLOADREQUESTSPERHOUR: "${CONCELIER_MIRROR_DOMAIN_PRIMARY_DOWNLOAD_BUDGET:-3600}"
|
||||
CONCELIER__MIRROR__DOMAINS__1__ID: "${CONCELIER_MIRROR_DOMAIN_SECONDARY_ID:-community}"
|
||||
CONCELIER__MIRROR__DOMAINS__1__DISPLAYNAME: "${CONCELIER_MIRROR_DOMAIN_SECONDARY_NAME:-Community Mirror}"
|
||||
CONCELIER__MIRROR__DOMAINS__1__REQUIREAUTHENTICATION: "${CONCELIER_MIRROR_DOMAIN_SECONDARY_AUTH:-false}"
|
||||
CONCELIER__MIRROR__DOMAINS__1__MAXDOWNLOADREQUESTSPERHOUR: "${CONCELIER_MIRROR_DOMAIN_SECONDARY_DOWNLOAD_BUDGET:-1800}"
|
||||
CONCELIER__AUTHORITY__ENABLED: "${CONCELIER_AUTHORITY_ENABLED:-true}"
|
||||
CONCELIER__AUTHORITY__ALLOWANONYMOUSFALLBACK: "${CONCELIER_AUTHORITY_ALLOW_ANON:-false}"
|
||||
CONCELIER__AUTHORITY__ISSUER: "${CONCELIER_AUTHORITY_ISSUER:-https://authority.stella-ops.org}"
|
||||
CONCELIER__AUTHORITY__METADATAADDRESS: "${CONCELIER_AUTHORITY_METADATA:-}"
|
||||
CONCELIER__AUTHORITY__CLIENTID: "${CONCELIER_AUTHORITY_CLIENT_ID:-stellaops-concelier-mirror}"
|
||||
CONCELIER__AUTHORITY__CLIENTSECRETFILE: "/run/secrets/concelier-authority-client"
|
||||
CONCELIER__AUTHORITY__CLIENTSCOPES__0: "${CONCELIER_AUTHORITY_SCOPE:-concelier.mirror.read}"
|
||||
CONCELIER__AUTHORITY__AUDIENCES__0: "${CONCELIER_AUTHORITY_AUDIENCE:-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"
|
||||
volumes:
|
||||
- concelier-jobs:/var/lib/concelier/jobs
|
||||
- concelier-exports:/exports/json
|
||||
- ./mirror-secrets:/run/secrets:ro
|
||||
networks:
|
||||
- mirror
|
||||
labels: *release-labels
|
||||
|
||||
excititor:
|
||||
image: registry.stella-ops.org/stellaops/excititor@sha256:d9bd5cadf1eab427447ce3df7302c30ded837239771cc6433b9befb895054285
|
||||
restart: unless-stopped
|
||||
depends_on:
|
||||
- mongo
|
||||
environment:
|
||||
ASPNETCORE_URLS: "http://+:8448"
|
||||
EXCITITOR__STORAGE__MONGO__CONNECTIONSTRING: "mongodb://${MONGO_INITDB_ROOT_USERNAME:-stellaops_mirror}:${MONGO_INITDB_ROOT_PASSWORD:-mirror-password}@mongo:27017/excititor?authSource=admin"
|
||||
EXCITITOR__STORAGE__MONGO__DATABASENAME: "${EXCITITOR_MONGO_DATABASE:-excititor}"
|
||||
EXCITITOR__ARTIFACTS__FILESYSTEM__ROOT: "/exports"
|
||||
EXCITITOR__ARTIFACTS__FILESYSTEM__OVERWRITEEXISTING: "${EXCITITOR_FILESYSTEM_OVERWRITE:-false}"
|
||||
EXCITITOR__MIRROR__DOMAINS__0__ID: "${EXCITITOR_MIRROR_DOMAIN_PRIMARY_ID:-primary}"
|
||||
EXCITITOR__MIRROR__DOMAINS__0__DISPLAYNAME: "${EXCITITOR_MIRROR_DOMAIN_PRIMARY_NAME:-Primary Mirror}"
|
||||
EXCITITOR__MIRROR__DOMAINS__0__REQUIREAUTHENTICATION: "${EXCITITOR_MIRROR_DOMAIN_PRIMARY_AUTH:-true}"
|
||||
EXCITITOR__MIRROR__DOMAINS__0__MAXINDEXREQUESTSPERHOUR: "${EXCITITOR_MIRROR_DOMAIN_PRIMARY_INDEX_BUDGET:-300}"
|
||||
EXCITITOR__MIRROR__DOMAINS__0__MAXDOWNLOADREQUESTSPERHOUR: "${EXCITITOR_MIRROR_DOMAIN_PRIMARY_DOWNLOAD_BUDGET:-2400}"
|
||||
EXCITITOR__MIRROR__DOMAINS__0__EXPORTS__0__KEY: "${EXCITITOR_MIRROR_PRIMARY_EXPORT_CONSENSUS_KEY:-consensus-json}"
|
||||
EXCITITOR__MIRROR__DOMAINS__0__EXPORTS__0__FORMAT: "${EXCITITOR_MIRROR_PRIMARY_EXPORT_CONSENSUS_FORMAT:-json}"
|
||||
EXCITITOR__MIRROR__DOMAINS__0__EXPORTS__0__VIEW: "${EXCITITOR_MIRROR_PRIMARY_EXPORT_CONSENSUS_VIEW:-consensus}"
|
||||
EXCITITOR__MIRROR__DOMAINS__0__EXPORTS__1__KEY: "${EXCITITOR_MIRROR_PRIMARY_EXPORT_OPENVEX_KEY:-consensus-openvex}"
|
||||
EXCITITOR__MIRROR__DOMAINS__0__EXPORTS__1__FORMAT: "${EXCITITOR_MIRROR_PRIMARY_EXPORT_OPENVEX_FORMAT:-openvex}"
|
||||
EXCITITOR__MIRROR__DOMAINS__0__EXPORTS__1__VIEW: "${EXCITITOR_MIRROR_PRIMARY_EXPORT_OPENVEX_VIEW:-consensus}"
|
||||
EXCITITOR__MIRROR__DOMAINS__1__ID: "${EXCITITOR_MIRROR_DOMAIN_SECONDARY_ID:-community}"
|
||||
EXCITITOR__MIRROR__DOMAINS__1__DISPLAYNAME: "${EXCITITOR_MIRROR_DOMAIN_SECONDARY_NAME:-Community Mirror}"
|
||||
EXCITITOR__MIRROR__DOMAINS__1__REQUIREAUTHENTICATION: "${EXCITITOR_MIRROR_DOMAIN_SECONDARY_AUTH:-false}"
|
||||
EXCITITOR__MIRROR__DOMAINS__1__MAXINDEXREQUESTSPERHOUR: "${EXCITITOR_MIRROR_DOMAIN_SECONDARY_INDEX_BUDGET:-120}"
|
||||
EXCITITOR__MIRROR__DOMAINS__1__MAXDOWNLOADREQUESTSPERHOUR: "${EXCITITOR_MIRROR_DOMAIN_SECONDARY_DOWNLOAD_BUDGET:-600}"
|
||||
EXCITITOR__MIRROR__DOMAINS__1__EXPORTS__0__KEY: "${EXCITITOR_MIRROR_SECONDARY_EXPORT_KEY:-community-consensus}"
|
||||
EXCITITOR__MIRROR__DOMAINS__1__EXPORTS__0__FORMAT: "${EXCITITOR_MIRROR_SECONDARY_EXPORT_FORMAT:-json}"
|
||||
EXCITITOR__MIRROR__DOMAINS__1__EXPORTS__0__VIEW: "${EXCITITOR_MIRROR_SECONDARY_EXPORT_VIEW:-consensus}"
|
||||
volumes:
|
||||
- excititor-exports:/exports
|
||||
- ./mirror-secrets:/run/secrets:ro
|
||||
expose:
|
||||
- "8448"
|
||||
networks:
|
||||
- mirror
|
||||
labels: *release-labels
|
||||
|
||||
mirror-gateway:
|
||||
image: docker.io/library/nginx@sha256:208b70eefac13ee9be00e486f79c695b15cef861c680527171a27d253d834be9
|
||||
restart: unless-stopped
|
||||
depends_on:
|
||||
- concelier
|
||||
- excititor
|
||||
ports:
|
||||
- "${MIRROR_GATEWAY_HTTP_PORT:-8080}:80"
|
||||
- "${MIRROR_GATEWAY_HTTPS_PORT:-9443}:443"
|
||||
volumes:
|
||||
- nginx-cache:/var/cache/nginx
|
||||
- ./mirror-gateway/conf.d:/etc/nginx/conf.d:ro
|
||||
- ./mirror-gateway/tls:/etc/nginx/tls:ro
|
||||
- ./mirror-gateway/secrets:/etc/nginx/secrets:ro
|
||||
networks:
|
||||
- mirror
|
||||
labels: *release-labels
|
||||
@@ -1,90 +0,0 @@
|
||||
x-release-labels: &release-labels
|
||||
com.stellaops.release.version: "2025.09.2-mock"
|
||||
com.stellaops.release.channel: "dev-mock"
|
||||
com.stellaops.profile: "mock-overlay"
|
||||
|
||||
services:
|
||||
orchestrator:
|
||||
image: registry.stella-ops.org/stellaops/orchestrator@sha256:97f12856ce870bafd3328bda86833bcccbf56d255941d804966b5557f6610119
|
||||
command: ["dotnet", "StellaOps.Orchestrator.WebService.dll"]
|
||||
depends_on:
|
||||
- mongo
|
||||
- nats
|
||||
labels: *release-labels
|
||||
networks: [stellaops]
|
||||
|
||||
policy-registry:
|
||||
image: registry.stella-ops.org/stellaops/policy-registry@sha256:c6cad8055e9827ebcbebb6ad4d6866dce4b83a0a49b0a8a6500b736a5cb26fa7
|
||||
command: ["dotnet", "StellaOps.Policy.Engine.dll"]
|
||||
depends_on:
|
||||
- mongo
|
||||
labels: *release-labels
|
||||
networks: [stellaops]
|
||||
|
||||
vex-lens:
|
||||
image: registry.stella-ops.org/stellaops/vex-lens@sha256:b44e63ecfeebc345a70c073c1ce5ace709c58be0ffaad0e2862758aeee3092fb
|
||||
command: ["dotnet", "StellaOps.VexLens.dll"]
|
||||
depends_on:
|
||||
- mongo
|
||||
labels: *release-labels
|
||||
networks: [stellaops]
|
||||
|
||||
issuer-directory:
|
||||
image: registry.stella-ops.org/stellaops/issuer-directory@sha256:67e8ef02c97d3156741e857756994888f30c373ace8e84886762edba9dc51914
|
||||
command: ["dotnet", "StellaOps.IssuerDirectory.Web.dll"]
|
||||
depends_on:
|
||||
- mongo
|
||||
- authority
|
||||
labels: *release-labels
|
||||
networks: [stellaops]
|
||||
|
||||
findings-ledger:
|
||||
image: registry.stella-ops.org/stellaops/findings-ledger@sha256:71d4c361ba8b2f8b69d652597bc3f2efc8a64f93fab854ce25272a88506df49c
|
||||
command: ["dotnet", "StellaOps.Findings.Ledger.WebService.dll"]
|
||||
depends_on:
|
||||
- postgres
|
||||
- authority
|
||||
labels: *release-labels
|
||||
networks: [stellaops]
|
||||
|
||||
vuln-explorer-api:
|
||||
image: registry.stella-ops.org/stellaops/vuln-explorer-api@sha256:7fc7e43a05cbeb0106ce7d4d634612e83de6fdc119aaab754a71c1d60b82841d
|
||||
command: ["dotnet", "StellaOps.VulnExplorer.Api.dll"]
|
||||
depends_on:
|
||||
- findings-ledger
|
||||
- authority
|
||||
labels: *release-labels
|
||||
networks: [stellaops]
|
||||
|
||||
packs-registry:
|
||||
image: registry.stella-ops.org/stellaops/packs-registry@sha256:1f5e9416c4dc608594ad6fad87c24d72134427f899c192b494e22b268499c791
|
||||
command: ["dotnet", "StellaOps.PacksRegistry.dll"]
|
||||
depends_on:
|
||||
- mongo
|
||||
labels: *release-labels
|
||||
networks: [stellaops]
|
||||
|
||||
task-runner:
|
||||
image: registry.stella-ops.org/stellaops/task-runner@sha256:eb5ad992b49a41554f41516be1a6afcfa6522faf2111c08ff2b3664ad2fc954b
|
||||
command: ["dotnet", "StellaOps.TaskRunner.WebService.dll"]
|
||||
depends_on:
|
||||
- packs-registry
|
||||
- postgres
|
||||
labels: *release-labels
|
||||
networks: [stellaops]
|
||||
|
||||
cryptopro-csp:
|
||||
build:
|
||||
context: ../..
|
||||
dockerfile: ops/cryptopro/linux-csp-service/Dockerfile
|
||||
args:
|
||||
CRYPTOPRO_ACCEPT_EULA: "${CRYPTOPRO_ACCEPT_EULA:-0}"
|
||||
environment:
|
||||
ASPNETCORE_URLS: "http://0.0.0.0:8080"
|
||||
CRYPTOPRO_ACCEPT_EULA: "${CRYPTOPRO_ACCEPT_EULA:-0}"
|
||||
volumes:
|
||||
- ../../opt/cryptopro/downloads:/opt/cryptopro/downloads:ro
|
||||
ports:
|
||||
- "${CRYPTOPRO_PORT:-18080}:8080"
|
||||
labels: *release-labels
|
||||
networks: [stellaops]
|
||||
@@ -1,380 +0,0 @@
|
||||
x-release-labels: &release-labels
|
||||
com.stellaops.release.version: "2025.09.2"
|
||||
com.stellaops.release.channel: "stable"
|
||||
com.stellaops.profile: "prod"
|
||||
|
||||
networks:
|
||||
stellaops:
|
||||
driver: bridge
|
||||
frontdoor:
|
||||
external: true
|
||||
name: ${FRONTDOOR_NETWORK:-stellaops_frontdoor}
|
||||
|
||||
volumes:
|
||||
valkey-data:
|
||||
rustfs-data:
|
||||
concelier-jobs:
|
||||
nats-data:
|
||||
scanner-surface-cache:
|
||||
postgres-data:
|
||||
advisory-ai-queue:
|
||||
advisory-ai-plans:
|
||||
advisory-ai-outputs:
|
||||
|
||||
services:
|
||||
valkey:
|
||||
image: docker.io/valkey/valkey:8.0
|
||||
restart: unless-stopped
|
||||
command: ["valkey-server", "--appendonly", "yes"]
|
||||
volumes:
|
||||
- valkey-data:/data
|
||||
ports:
|
||||
- "${VALKEY_PORT:-6379}:6379"
|
||||
networks:
|
||||
- stellaops
|
||||
labels: *release-labels
|
||||
|
||||
rustfs:
|
||||
image: registry.stella-ops.org/stellaops/rustfs:2025.10.0-edge
|
||||
command: ["serve", "--listen", "0.0.0.0:8080", "--root", "/data"]
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
RUSTFS__LOG__LEVEL: info
|
||||
RUSTFS__STORAGE__PATH: /data
|
||||
volumes:
|
||||
- rustfs-data:/data
|
||||
ports:
|
||||
- "${RUSTFS_HTTP_PORT:-8080}:8080"
|
||||
networks:
|
||||
- stellaops
|
||||
labels: *release-labels
|
||||
|
||||
nats:
|
||||
image: docker.io/library/nats@sha256:c82559e4476289481a8a5196e675ebfe67eea81d95e5161e3e78eccfe766608e
|
||||
command:
|
||||
- "-js"
|
||||
- "-sd"
|
||||
- /data
|
||||
restart: unless-stopped
|
||||
ports:
|
||||
- "${NATS_CLIENT_PORT:-4222}:4222"
|
||||
volumes:
|
||||
- nats-data:/data
|
||||
networks:
|
||||
- stellaops
|
||||
labels: *release-labels
|
||||
|
||||
authority:
|
||||
image: registry.stella-ops.org/stellaops/authority@sha256:b0348bad1d0b401cc3c71cb40ba034c8043b6c8874546f90d4783c9dbfcc0bf5
|
||||
restart: unless-stopped
|
||||
depends_on:
|
||||
- postgres
|
||||
- valkey
|
||||
environment:
|
||||
STELLAOPS_AUTHORITY__ISSUER: "${AUTHORITY_ISSUER}"
|
||||
STELLAOPS_AUTHORITY__STORAGE__DRIVER: "postgres"
|
||||
STELLAOPS_AUTHORITY__STORAGE__POSTGRES__CONNECTIONSTRING: "Host=postgres;Port=5432;Database=${POSTGRES_DB:-stellaops_platform};Username=${POSTGRES_USER:-stellaops};Password=${POSTGRES_PASSWORD:-stellaops}"
|
||||
STELLAOPS_AUTHORITY__CACHE__REDIS__CONNECTIONSTRING: "valkey:6379"
|
||||
STELLAOPS_AUTHORITY__PLUGINDIRECTORIES__0: "/app/plugins"
|
||||
STELLAOPS_AUTHORITY__PLUGINS__CONFIGURATIONDIRECTORY: "/app/etc/authority.plugins"
|
||||
volumes:
|
||||
- ../../etc/authority.yaml:/etc/authority.yaml:ro
|
||||
- ../../etc/authority.plugins:/app/etc/authority.plugins:ro
|
||||
ports:
|
||||
- "${AUTHORITY_PORT:-8440}:8440"
|
||||
networks:
|
||||
- stellaops
|
||||
- frontdoor
|
||||
labels: *release-labels
|
||||
|
||||
signer:
|
||||
image: registry.stella-ops.org/stellaops/signer@sha256:8ad574e61f3a9e9bda8a58eb2700ae46813284e35a150b1137bc7c2b92ac0f2e
|
||||
restart: unless-stopped
|
||||
depends_on:
|
||||
- postgres
|
||||
- authority
|
||||
environment:
|
||||
SIGNER__AUTHORITY__BASEURL: "https://authority:8440"
|
||||
SIGNER__POE__INTROSPECTURL: "${SIGNER_POE_INTROSPECT_URL}"
|
||||
SIGNER__STORAGE__DRIVER: "postgres"
|
||||
SIGNER__STORAGE__POSTGRES__CONNECTIONSTRING: "Host=postgres;Port=5432;Database=${POSTGRES_DB:-stellaops_platform};Username=${POSTGRES_USER:-stellaops};Password=${POSTGRES_PASSWORD:-stellaops}"
|
||||
ports:
|
||||
- "${SIGNER_PORT:-8441}:8441"
|
||||
networks:
|
||||
- stellaops
|
||||
- frontdoor
|
||||
labels: *release-labels
|
||||
|
||||
attestor:
|
||||
image: registry.stella-ops.org/stellaops/attestor@sha256:0534985f978b0b5d220d73c96fddd962cd9135f616811cbe3bff4666c5af568f
|
||||
restart: unless-stopped
|
||||
depends_on:
|
||||
- signer
|
||||
- postgres
|
||||
environment:
|
||||
ATTESTOR__SIGNER__BASEURL: "https://signer:8441"
|
||||
ATTESTOR__STORAGE__DRIVER: "postgres"
|
||||
ATTESTOR__STORAGE__POSTGRES__CONNECTIONSTRING: "Host=postgres;Port=5432;Database=${POSTGRES_DB:-stellaops_platform};Username=${POSTGRES_USER:-stellaops};Password=${POSTGRES_PASSWORD:-stellaops}"
|
||||
ports:
|
||||
- "${ATTESTOR_PORT:-8442}:8442"
|
||||
networks:
|
||||
- stellaops
|
||||
- frontdoor
|
||||
labels: *release-labels
|
||||
|
||||
postgres:
|
||||
image: docker.io/library/postgres:16
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
POSTGRES_USER: "${POSTGRES_USER:-stellaops}"
|
||||
POSTGRES_PASSWORD: "${POSTGRES_PASSWORD:-stellaops}"
|
||||
POSTGRES_DB: "${POSTGRES_DB:-stellaops_platform}"
|
||||
PGDATA: /var/lib/postgresql/data/pgdata
|
||||
volumes:
|
||||
- postgres-data:/var/lib/postgresql/data
|
||||
ports:
|
||||
- "${POSTGRES_PORT:-5432}:5432"
|
||||
networks:
|
||||
- stellaops
|
||||
labels: *release-labels
|
||||
|
||||
issuer-directory:
|
||||
image: registry.stella-ops.org/stellaops/issuer-directory-web:2025.10.0-edge
|
||||
restart: unless-stopped
|
||||
depends_on:
|
||||
- postgres
|
||||
- authority
|
||||
environment:
|
||||
ISSUERDIRECTORY__CONFIG: "/etc/issuer-directory.yaml"
|
||||
ISSUERDIRECTORY__AUTHORITY__ISSUER: "${AUTHORITY_ISSUER}"
|
||||
ISSUERDIRECTORY__AUTHORITY__BASEURL: "https://authority:8440"
|
||||
ISSUERDIRECTORY__STORAGE__DRIVER: "postgres"
|
||||
ISSUERDIRECTORY__STORAGE__POSTGRES__CONNECTIONSTRING: "Host=postgres;Port=5432;Database=${POSTGRES_DB:-stellaops_platform};Username=${POSTGRES_USER:-stellaops};Password=${POSTGRES_PASSWORD:-stellaops}"
|
||||
ISSUERDIRECTORY__SEEDCSAFPUBLISHERS: "${ISSUER_DIRECTORY_SEED_CSAF:-true}"
|
||||
volumes:
|
||||
- ../../etc/issuer-directory.yaml:/etc/issuer-directory.yaml:ro
|
||||
ports:
|
||||
- "${ISSUER_DIRECTORY_PORT:-8447}:8080"
|
||||
networks:
|
||||
- stellaops
|
||||
labels: *release-labels
|
||||
|
||||
concelier:
|
||||
image: registry.stella-ops.org/stellaops/concelier@sha256:c58cdcaee1d266d68d498e41110a589dd204b487d37381096bd61ab345a867c5
|
||||
restart: unless-stopped
|
||||
depends_on:
|
||||
- postgres
|
||||
- valkey
|
||||
environment:
|
||||
CONCELIER__STORAGE__DRIVER: "postgres"
|
||||
CONCELIER__STORAGE__POSTGRES__CONNECTIONSTRING: "Host=postgres;Port=5432;Database=${POSTGRES_DB:-stellaops_platform};Username=${POSTGRES_USER:-stellaops};Password=${POSTGRES_PASSWORD:-stellaops}"
|
||||
CONCELIER__STORAGE__S3__ENDPOINT: "http://rustfs:8080"
|
||||
CONCELIER__AUTHORITY__BASEURL: "https://authority:8440"
|
||||
CONCELIER__AUTHORITY__RESILIENCE__ALLOWOFFLINECACHEFALLBACK: "true"
|
||||
CONCELIER__AUTHORITY__RESILIENCE__OFFLINECACHETOLERANCE: "${AUTHORITY_OFFLINE_CACHE_TOLERANCE:-00:30:00}"
|
||||
volumes:
|
||||
- concelier-jobs:/var/lib/concelier/jobs
|
||||
ports:
|
||||
- "${CONCELIER_PORT:-8445}:8445"
|
||||
networks:
|
||||
- stellaops
|
||||
- frontdoor
|
||||
labels: *release-labels
|
||||
|
||||
scanner-web:
|
||||
image: registry.stella-ops.org/stellaops/scanner-web@sha256:14b23448c3f9586a9156370b3e8c1991b61907efa666ca37dd3aaed1e79fe3b7
|
||||
restart: unless-stopped
|
||||
depends_on:
|
||||
- postgres
|
||||
- valkey
|
||||
- concelier
|
||||
- rustfs
|
||||
environment:
|
||||
SCANNER__STORAGE__DRIVER: "postgres"
|
||||
SCANNER__STORAGE__POSTGRES__CONNECTIONSTRING: "Host=postgres;Port=5432;Database=${POSTGRES_DB:-stellaops_platform};Username=${POSTGRES_USER:-stellaops};Password=${POSTGRES_PASSWORD:-stellaops}"
|
||||
SCANNER__CACHE__REDIS__CONNECTIONSTRING: "valkey:6379"
|
||||
SCANNER__ARTIFACTSTORE__DRIVER: "rustfs"
|
||||
SCANNER__ARTIFACTSTORE__ENDPOINT: "http://rustfs:8080/api/v1"
|
||||
SCANNER__ARTIFACTSTORE__BUCKET: "scanner-artifacts"
|
||||
SCANNER__ARTIFACTSTORE__TIMEOUTSECONDS: "30"
|
||||
SCANNER__QUEUE__BROKER: "${SCANNER_QUEUE_BROKER:-valkey://valkey:6379}"
|
||||
SCANNER__EVENTS__ENABLED: "${SCANNER_EVENTS_ENABLED:-false}"
|
||||
SCANNER__EVENTS__DRIVER: "${SCANNER_EVENTS_DRIVER:-valkey}"
|
||||
SCANNER__EVENTS__DSN: "${SCANNER_EVENTS_DSN:-}"
|
||||
SCANNER__EVENTS__STREAM: "${SCANNER_EVENTS_STREAM:-stella.events}"
|
||||
SCANNER__EVENTS__PUBLISHTIMEOUTSECONDS: "${SCANNER_EVENTS_PUBLISH_TIMEOUT_SECONDS:-5}"
|
||||
SCANNER__EVENTS__MAXSTREAMLENGTH: "${SCANNER_EVENTS_MAX_STREAM_LENGTH:-10000}"
|
||||
SCANNER__OFFLINEKIT__ENABLED: "${SCANNER_OFFLINEKIT_ENABLED:-false}"
|
||||
SCANNER__OFFLINEKIT__REQUIREDSSE: "${SCANNER_OFFLINEKIT_REQUIREDSSE:-true}"
|
||||
SCANNER__OFFLINEKIT__REKOROFFLINEMODE: "${SCANNER_OFFLINEKIT_REKOROFFLINEMODE:-true}"
|
||||
SCANNER__OFFLINEKIT__TRUSTROOTDIRECTORY: "${SCANNER_OFFLINEKIT_TRUSTROOTDIRECTORY:-/etc/stellaops/trust-roots}"
|
||||
SCANNER__OFFLINEKIT__REKORSNAPSHOTDIRECTORY: "${SCANNER_OFFLINEKIT_REKORSNAPSHOTDIRECTORY:-/var/lib/stellaops/rekor-snapshot}"
|
||||
SCANNER_SURFACE_FS_ENDPOINT: "${SCANNER_SURFACE_FS_ENDPOINT:-http://rustfs:8080}"
|
||||
SCANNER_SURFACE_FS_BUCKET: "${SCANNER_SURFACE_FS_BUCKET:-surface-cache}"
|
||||
SCANNER_SURFACE_CACHE_ROOT: "${SCANNER_SURFACE_CACHE_ROOT:-/var/lib/stellaops/surface}"
|
||||
SCANNER_SURFACE_CACHE_QUOTA_MB: "${SCANNER_SURFACE_CACHE_QUOTA_MB:-4096}"
|
||||
SCANNER_SURFACE_PREFETCH_ENABLED: "${SCANNER_SURFACE_PREFETCH_ENABLED:-false}"
|
||||
SCANNER_SURFACE_TENANT: "${SCANNER_SURFACE_TENANT:-default}"
|
||||
SCANNER_SURFACE_FEATURES: "${SCANNER_SURFACE_FEATURES:-}"
|
||||
SCANNER_SURFACE_SECRETS_PROVIDER: "${SCANNER_SURFACE_SECRETS_PROVIDER:-file}"
|
||||
SCANNER_SURFACE_SECRETS_NAMESPACE: "${SCANNER_SURFACE_SECRETS_NAMESPACE:-}"
|
||||
SCANNER_SURFACE_SECRETS_ROOT: "${SCANNER_SURFACE_SECRETS_ROOT:-/etc/stellaops/secrets}"
|
||||
SCANNER_SURFACE_SECRETS_FALLBACK_PROVIDER: "${SCANNER_SURFACE_SECRETS_FALLBACK_PROVIDER:-}"
|
||||
SCANNER_SURFACE_SECRETS_ALLOW_INLINE: "${SCANNER_SURFACE_SECRETS_ALLOW_INLINE:-false}"
|
||||
volumes:
|
||||
- scanner-surface-cache:/var/lib/stellaops/surface
|
||||
- ${SURFACE_SECRETS_HOST_PATH:-./offline/surface-secrets}:${SCANNER_SURFACE_SECRETS_ROOT:-/etc/stellaops/secrets}:ro
|
||||
- ${SCANNER_OFFLINEKIT_TRUSTROOTS_HOST_PATH:-./offline/trust-roots}:${SCANNER_OFFLINEKIT_TRUSTROOTDIRECTORY:-/etc/stellaops/trust-roots}:ro
|
||||
- ${SCANNER_OFFLINEKIT_REKOR_SNAPSHOT_HOST_PATH:-./offline/rekor-snapshot}:${SCANNER_OFFLINEKIT_REKORSNAPSHOTDIRECTORY:-/var/lib/stellaops/rekor-snapshot}:ro
|
||||
ports:
|
||||
- "${SCANNER_WEB_PORT:-8444}:8444"
|
||||
networks:
|
||||
- stellaops
|
||||
- frontdoor
|
||||
labels: *release-labels
|
||||
|
||||
scanner-worker:
|
||||
image: registry.stella-ops.org/stellaops/scanner-worker@sha256:32e25e76386eb9ea8bee0a1ad546775db9a2df989fab61ac877e351881960dab
|
||||
restart: unless-stopped
|
||||
depends_on:
|
||||
- postgres
|
||||
- valkey
|
||||
- scanner-web
|
||||
- rustfs
|
||||
environment:
|
||||
SCANNER__STORAGE__DRIVER: "postgres"
|
||||
SCANNER__STORAGE__POSTGRES__CONNECTIONSTRING: "Host=postgres;Port=5432;Database=${POSTGRES_DB:-stellaops_platform};Username=${POSTGRES_USER:-stellaops};Password=${POSTGRES_PASSWORD:-stellaops}"
|
||||
SCANNER__CACHE__REDIS__CONNECTIONSTRING: "valkey:6379"
|
||||
SCANNER__ARTIFACTSTORE__DRIVER: "rustfs"
|
||||
SCANNER__ARTIFACTSTORE__ENDPOINT: "http://rustfs:8080/api/v1"
|
||||
SCANNER__ARTIFACTSTORE__BUCKET: "scanner-artifacts"
|
||||
SCANNER__ARTIFACTSTORE__TIMEOUTSECONDS: "30"
|
||||
SCANNER__QUEUE__BROKER: "${SCANNER_QUEUE_BROKER:-valkey://valkey:6379}"
|
||||
SCANNER_SURFACE_FS_ENDPOINT: "${SCANNER_SURFACE_FS_ENDPOINT:-http://rustfs:8080}"
|
||||
SCANNER_SURFACE_FS_BUCKET: "${SCANNER_SURFACE_FS_BUCKET:-surface-cache}"
|
||||
SCANNER_SURFACE_CACHE_ROOT: "${SCANNER_SURFACE_CACHE_ROOT:-/var/lib/stellaops/surface}"
|
||||
SCANNER_SURFACE_CACHE_QUOTA_MB: "${SCANNER_SURFACE_CACHE_QUOTA_MB:-4096}"
|
||||
SCANNER_SURFACE_PREFETCH_ENABLED: "${SCANNER_SURFACE_PREFETCH_ENABLED:-false}"
|
||||
SCANNER_SURFACE_TENANT: "${SCANNER_SURFACE_TENANT:-default}"
|
||||
SCANNER_SURFACE_FEATURES: "${SCANNER_SURFACE_FEATURES:-}"
|
||||
SCANNER_SURFACE_SECRETS_PROVIDER: "${SCANNER_SURFACE_SECRETS_PROVIDER:-file}"
|
||||
SCANNER_SURFACE_SECRETS_NAMESPACE: "${SCANNER_SURFACE_SECRETS_NAMESPACE:-}"
|
||||
SCANNER_SURFACE_SECRETS_ROOT: "${SCANNER_SURFACE_SECRETS_ROOT:-/etc/stellaops/secrets}"
|
||||
SCANNER_SURFACE_SECRETS_FALLBACK_PROVIDER: "${SCANNER_SURFACE_SECRETS_FALLBACK_PROVIDER:-}"
|
||||
SCANNER_SURFACE_SECRETS_ALLOW_INLINE: "${SCANNER_SURFACE_SECRETS_ALLOW_INLINE:-false}"
|
||||
volumes:
|
||||
- scanner-surface-cache:/var/lib/stellaops/surface
|
||||
- ${SURFACE_SECRETS_HOST_PATH:-./offline/surface-secrets}:${SCANNER_SURFACE_SECRETS_ROOT:-/etc/stellaops/secrets}:ro
|
||||
networks:
|
||||
- stellaops
|
||||
labels: *release-labels
|
||||
|
||||
scheduler-worker:
|
||||
image: registry.stella-ops.org/stellaops/scheduler-worker:2025.10.0-edge
|
||||
restart: unless-stopped
|
||||
depends_on:
|
||||
- postgres
|
||||
- valkey
|
||||
- scanner-web
|
||||
command:
|
||||
- "dotnet"
|
||||
- "StellaOps.Scheduler.Worker.Host.dll"
|
||||
environment:
|
||||
SCHEDULER__STORAGE__DRIVER: "postgres"
|
||||
SCHEDULER__STORAGE__POSTGRES__CONNECTIONSTRING: "Host=postgres;Port=5432;Database=${POSTGRES_DB:-stellaops_platform};Username=${POSTGRES_USER:-stellaops};Password=${POSTGRES_PASSWORD:-stellaops}"
|
||||
SCHEDULER__QUEUE__KIND: "${SCHEDULER_QUEUE_KIND:-Valkey}"
|
||||
SCHEDULER__QUEUE__VALKEY__URL: "${SCHEDULER_QUEUE_VALKEY_URL:-valkey:6379}"
|
||||
SCHEDULER__WORKER__RUNNER__SCANNER__BASEADDRESS: "${SCHEDULER_SCANNER_BASEADDRESS:-http://scanner-web:8444}"
|
||||
networks:
|
||||
- stellaops
|
||||
labels: *release-labels
|
||||
|
||||
notify-web:
|
||||
image: ${NOTIFY_WEB_IMAGE:-registry.stella-ops.org/stellaops/notify-web:2025.09.2}
|
||||
restart: unless-stopped
|
||||
depends_on:
|
||||
- postgres
|
||||
- authority
|
||||
environment:
|
||||
DOTNET_ENVIRONMENT: Production
|
||||
volumes:
|
||||
- ../../etc/notify.prod.yaml:/app/etc/notify.yaml:ro
|
||||
ports:
|
||||
- "${NOTIFY_WEB_PORT:-8446}:8446"
|
||||
networks:
|
||||
- stellaops
|
||||
- frontdoor
|
||||
labels: *release-labels
|
||||
|
||||
excititor:
|
||||
image: registry.stella-ops.org/stellaops/excititor@sha256:59022e2016aebcef5c856d163ae705755d3f81949d41195256e935ef40a627fa
|
||||
restart: unless-stopped
|
||||
depends_on:
|
||||
- postgres
|
||||
- concelier
|
||||
environment:
|
||||
EXCITITOR__CONCELIER__BASEURL: "https://concelier:8445"
|
||||
EXCITITOR__STORAGE__DRIVER: "postgres"
|
||||
EXCITITOR__STORAGE__POSTGRES__CONNECTIONSTRING: "Host=postgres;Port=5432;Database=${POSTGRES_DB:-stellaops_platform};Username=${POSTGRES_USER:-stellaops};Password=${POSTGRES_PASSWORD:-stellaops}"
|
||||
networks:
|
||||
- stellaops
|
||||
labels: *release-labels
|
||||
|
||||
advisory-ai-web:
|
||||
image: registry.stella-ops.org/stellaops/advisory-ai-web:2025.09.2
|
||||
restart: unless-stopped
|
||||
depends_on:
|
||||
- scanner-web
|
||||
environment:
|
||||
ADVISORYAI__AdvisoryAI__SbomBaseAddress: "${ADVISORY_AI_SBOM_BASEADDRESS:-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: "${ADVISORY_AI_INFERENCE_MODE:-Local}"
|
||||
ADVISORYAI__AdvisoryAI__Inference__Remote__BaseAddress: "${ADVISORY_AI_REMOTE_BASEADDRESS:-}"
|
||||
ADVISORYAI__AdvisoryAI__Inference__Remote__ApiKey: "${ADVISORY_AI_REMOTE_APIKEY:-}"
|
||||
ports:
|
||||
- "${ADVISORY_AI_WEB_PORT:-8448}:8448"
|
||||
volumes:
|
||||
- advisory-ai-queue:/var/lib/advisory-ai/queue
|
||||
- advisory-ai-plans:/var/lib/advisory-ai/plans
|
||||
- advisory-ai-outputs:/var/lib/advisory-ai/outputs
|
||||
networks:
|
||||
- stellaops
|
||||
- frontdoor
|
||||
labels: *release-labels
|
||||
|
||||
advisory-ai-worker:
|
||||
image: registry.stella-ops.org/stellaops/advisory-ai-worker:2025.09.2
|
||||
restart: unless-stopped
|
||||
depends_on:
|
||||
- advisory-ai-web
|
||||
environment:
|
||||
ADVISORYAI__AdvisoryAI__SbomBaseAddress: "${ADVISORY_AI_SBOM_BASEADDRESS:-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: "${ADVISORY_AI_INFERENCE_MODE:-Local}"
|
||||
ADVISORYAI__AdvisoryAI__Inference__Remote__BaseAddress: "${ADVISORY_AI_REMOTE_BASEADDRESS:-}"
|
||||
ADVISORYAI__AdvisoryAI__Inference__Remote__ApiKey: "${ADVISORY_AI_REMOTE_APIKEY:-}"
|
||||
volumes:
|
||||
- advisory-ai-queue:/var/lib/advisory-ai/queue
|
||||
- advisory-ai-plans:/var/lib/advisory-ai/plans
|
||||
- advisory-ai-outputs:/var/lib/advisory-ai/outputs
|
||||
networks:
|
||||
- stellaops
|
||||
labels: *release-labels
|
||||
|
||||
web-ui:
|
||||
image: registry.stella-ops.org/stellaops/web-ui@sha256:10d924808c48e4353e3a241da62eb7aefe727a1d6dc830eb23a8e181013b3a23
|
||||
restart: unless-stopped
|
||||
depends_on:
|
||||
- scanner-web
|
||||
environment:
|
||||
STELLAOPS_UI__BACKEND__BASEURL: "https://scanner-web:8444"
|
||||
ports:
|
||||
- "${UI_PORT:-8443}:8443"
|
||||
networks:
|
||||
- stellaops
|
||||
- frontdoor
|
||||
labels: *release-labels
|
||||
@@ -1,301 +0,0 @@
|
||||
# StellaOps Docker Compose - International Profile
|
||||
# Cryptography: GOST R 34.10-2012, GOST R 34.11-2012 (Streebog)
|
||||
# Provider: openssl.gost, pkcs11.gost, cryptopro.gost
|
||||
# Jurisdiction: world
|
||||
|
||||
x-release-labels: &release-labels
|
||||
com.stellaops.release.version: "2025.10.0-edge"
|
||||
com.stellaops.release.channel: "edge"
|
||||
com.stellaops.profile: "russia"
|
||||
com.stellaops.crypto.profile: "russia"
|
||||
com.stellaops.crypto.provider: "openssl.gost, pkcs11.gost, cryptopro.gost"
|
||||
|
||||
x-crypto-env: &crypto-env
|
||||
# Crypto configuration
|
||||
STELLAOPS_CRYPTO_PROFILE: "russia"
|
||||
STELLAOPS_CRYPTO_CONFIG_PATH: "/app/etc/appsettings.crypto.yaml"
|
||||
STELLAOPS_CRYPTO_MANIFEST_PATH: "/app/etc/crypto-plugins-manifest.json"
|
||||
|
||||
networks:
|
||||
stellaops:
|
||||
driver: bridge
|
||||
|
||||
volumes:
|
||||
rustfs-data:
|
||||
concelier-jobs:
|
||||
nats-data:
|
||||
valkey-data:
|
||||
advisory-ai-queue:
|
||||
advisory-ai-plans:
|
||||
advisory-ai-outputs:
|
||||
postgres-data:
|
||||
|
||||
services:
|
||||
postgres:
|
||||
image: docker.io/library/postgres:16
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
POSTGRES_USER: "${POSTGRES_USER:-stellaops}"
|
||||
POSTGRES_PASSWORD: "${POSTGRES_PASSWORD:-stellaops}"
|
||||
POSTGRES_DB: "${POSTGRES_DB:-stellaops_platform}"
|
||||
PGDATA: /var/lib/postgresql/data/pgdata
|
||||
volumes:
|
||||
- postgres-data:/var/lib/postgresql/data
|
||||
- ../postgres-partitioning:/docker-entrypoint-initdb.d:ro
|
||||
ports:
|
||||
- "${POSTGRES_PORT:-5432}:5432"
|
||||
networks:
|
||||
- stellaops
|
||||
labels: *release-labels
|
||||
|
||||
valkey:
|
||||
image: docker.io/valkey/valkey:8.0
|
||||
restart: unless-stopped
|
||||
command: ["valkey-server", "--appendonly", "yes"]
|
||||
volumes:
|
||||
- valkey-data:/data
|
||||
ports:
|
||||
- "${VALKEY_PORT:-6379}:6379"
|
||||
networks:
|
||||
- stellaops
|
||||
labels: *release-labels
|
||||
|
||||
rustfs:
|
||||
image: registry.stella-ops.org/stellaops/rustfs:2025.10.0-edge
|
||||
command: ["serve", "--listen", "0.0.0.0:8080", "--root", "/data"]
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
RUSTFS__LOG__LEVEL: info
|
||||
RUSTFS__STORAGE__PATH: /data
|
||||
volumes:
|
||||
- rustfs-data:/data
|
||||
ports:
|
||||
- "${RUSTFS_HTTP_PORT:-8080}:8080"
|
||||
networks:
|
||||
- stellaops
|
||||
labels: *release-labels
|
||||
|
||||
nats:
|
||||
image: docker.io/library/nats@sha256:c82559e4476289481a8a5196e675ebfe67eea81d95e5161e3e78eccfe766608e
|
||||
command:
|
||||
- "-js"
|
||||
- "-sd"
|
||||
- /data
|
||||
restart: unless-stopped
|
||||
ports:
|
||||
- "${NATS_CLIENT_PORT:-4222}:4222"
|
||||
volumes:
|
||||
- nats-data:/data
|
||||
networks:
|
||||
- stellaops
|
||||
labels: *release-labels
|
||||
|
||||
authority:
|
||||
image: registry.stella-ops.org/stellaops/authority:russia
|
||||
restart: unless-stopped
|
||||
depends_on:
|
||||
- postgres
|
||||
environment:
|
||||
<<: *crypto-env
|
||||
STELLAOPS_AUTHORITY__ISSUER: "${AUTHORITY_ISSUER}"
|
||||
STELLAOPS_AUTHORITY__STORAGE__DRIVER: "postgres"
|
||||
STELLAOPS_AUTHORITY__STORAGE__POSTGRES__CONNECTIONSTRING: "Host=postgres;Port=5432;Database=${POSTGRES_DB:-stellaops_platform};Username=${POSTGRES_USER:-stellaops};Password=${POSTGRES_PASSWORD:-stellaops}"
|
||||
STELLAOPS_AUTHORITY__PLUGINDIRECTORIES__0: "/app/plugins"
|
||||
STELLAOPS_AUTHORITY__PLUGINS__CONFIGURATIONDIRECTORY: "/app/etc/authority.plugins"
|
||||
volumes:
|
||||
- ../../etc/authority.yaml:/etc/authority.yaml:ro
|
||||
- ../../etc/authority.plugins:/app/etc/authority.plugins:ro
|
||||
- ../../etc/appsettings.crypto.russia.yaml:/app/etc/appsettings.crypto.yaml:ro
|
||||
- ../../etc/crypto-plugins-manifest.json:/app/etc/crypto-plugins-manifest.json:ro
|
||||
ports:
|
||||
- "${AUTHORITY_PORT:-8440}:8440"
|
||||
networks:
|
||||
- stellaops
|
||||
labels: *release-labels
|
||||
|
||||
signer:
|
||||
image: registry.stella-ops.org/stellaops/signer:russia
|
||||
restart: unless-stopped
|
||||
depends_on:
|
||||
- postgres
|
||||
environment:
|
||||
<<: *crypto-env
|
||||
STELLAOPS_SIGNER__STORAGE__DRIVER: "postgres"
|
||||
STELLAOPS_SIGNER__STORAGE__POSTGRES__CONNECTIONSTRING: "Host=postgres;Port=5432;Database=${POSTGRES_DB:-stellaops_platform};Username=${POSTGRES_USER:-stellaops};Password=${POSTGRES_PASSWORD:-stellaops}"
|
||||
volumes:
|
||||
- ../../etc/appsettings.crypto.russia.yaml:/app/etc/appsettings.crypto.yaml:ro
|
||||
- ../../etc/crypto-plugins-manifest.json:/app/etc/crypto-plugins-manifest.json:ro
|
||||
ports:
|
||||
- "${SIGNER_PORT:-8441}:8441"
|
||||
networks:
|
||||
- stellaops
|
||||
labels: *release-labels
|
||||
|
||||
attestor:
|
||||
image: registry.stella-ops.org/stellaops/attestor:russia
|
||||
restart: unless-stopped
|
||||
depends_on:
|
||||
- signer
|
||||
environment:
|
||||
<<: *crypto-env
|
||||
STELLAOPS_ATTESTOR__SIGNER__BASEURL: "http://signer:8441"
|
||||
volumes:
|
||||
- ../../etc/appsettings.crypto.russia.yaml:/app/etc/appsettings.crypto.yaml:ro
|
||||
- ../../etc/crypto-plugins-manifest.json:/app/etc/crypto-plugins-manifest.json:ro
|
||||
ports:
|
||||
- "${ATTESTOR_PORT:-8442}:8442"
|
||||
networks:
|
||||
- stellaops
|
||||
labels: *release-labels
|
||||
|
||||
concelier:
|
||||
image: registry.stella-ops.org/stellaops/concelier:russia
|
||||
restart: unless-stopped
|
||||
depends_on:
|
||||
- postgres
|
||||
- rustfs
|
||||
environment:
|
||||
<<: *crypto-env
|
||||
STELLAOPS_CONCELIER__STORAGE__DRIVER: "postgres"
|
||||
STELLAOPS_CONCELIER__STORAGE__POSTGRES__CONNECTIONSTRING: "Host=postgres;Port=5432;Database=${POSTGRES_DB:-stellaops_platform};Username=${POSTGRES_USER:-stellaops};Password=${POSTGRES_PASSWORD:-stellaops}"
|
||||
STELLAOPS_CONCELIER__STORAGE__RUSTFS__BASEURL: "http://rustfs:8080"
|
||||
volumes:
|
||||
- ../../etc/appsettings.crypto.russia.yaml:/app/etc/appsettings.crypto.yaml:ro
|
||||
- ../../etc/crypto-plugins-manifest.json:/app/etc/crypto-plugins-manifest.json:ro
|
||||
- concelier-jobs:/app/jobs
|
||||
ports:
|
||||
- "${CONCELIER_PORT:-8443}:8443"
|
||||
networks:
|
||||
- stellaops
|
||||
labels: *release-labels
|
||||
|
||||
scanner:
|
||||
image: registry.stella-ops.org/stellaops/scanner:russia
|
||||
restart: unless-stopped
|
||||
depends_on:
|
||||
- postgres
|
||||
environment:
|
||||
<<: *crypto-env
|
||||
STELLAOPS_SCANNER__STORAGE__DRIVER: "postgres"
|
||||
STELLAOPS_SCANNER__STORAGE__POSTGRES__CONNECTIONSTRING: "Host=postgres;Port=5432;Database=${POSTGRES_DB:-stellaops_platform};Username=${POSTGRES_USER:-stellaops};Password=${POSTGRES_PASSWORD:-stellaops}"
|
||||
volumes:
|
||||
- ../../etc/appsettings.crypto.russia.yaml:/app/etc/appsettings.crypto.yaml:ro
|
||||
- ../../etc/crypto-plugins-manifest.json:/app/etc/crypto-plugins-manifest.json:ro
|
||||
ports:
|
||||
- "${SCANNER_PORT:-8444}:8444"
|
||||
networks:
|
||||
- stellaops
|
||||
labels: *release-labels
|
||||
|
||||
excititor:
|
||||
image: registry.stella-ops.org/stellaops/excititor:russia
|
||||
restart: unless-stopped
|
||||
depends_on:
|
||||
- postgres
|
||||
environment:
|
||||
<<: *crypto-env
|
||||
STELLAOPS_EXCITITOR__STORAGE__DRIVER: "postgres"
|
||||
STELLAOPS_EXCITITOR__STORAGE__POSTGRES__CONNECTIONSTRING: "Host=postgres;Port=5432;Database=${POSTGRES_DB:-stellaops_platform};Username=${POSTGRES_USER:-stellaops};Password=${POSTGRES_PASSWORD:-stellaops}"
|
||||
volumes:
|
||||
- ../../etc/appsettings.crypto.russia.yaml:/app/etc/appsettings.crypto.yaml:ro
|
||||
- ../../etc/crypto-plugins-manifest.json:/app/etc/crypto-plugins-manifest.json:ro
|
||||
ports:
|
||||
- "${EXCITITOR_PORT:-8445}:8445"
|
||||
networks:
|
||||
- stellaops
|
||||
labels: *release-labels
|
||||
|
||||
policy:
|
||||
image: registry.stella-ops.org/stellaops/policy:russia
|
||||
restart: unless-stopped
|
||||
depends_on:
|
||||
- postgres
|
||||
environment:
|
||||
<<: *crypto-env
|
||||
STELLAOPS_POLICY__STORAGE__DRIVER: "postgres"
|
||||
STELLAOPS_POLICY__STORAGE__POSTGRES__CONNECTIONSTRING: "Host=postgres;Port=5432;Database=${POSTGRES_DB:-stellaops_platform};Username=${POSTGRES_USER:-stellaops};Password=${POSTGRES_PASSWORD:-stellaops}"
|
||||
volumes:
|
||||
- ../../etc/appsettings.crypto.russia.yaml:/app/etc/appsettings.crypto.yaml:ro
|
||||
- ../../etc/crypto-plugins-manifest.json:/app/etc/crypto-plugins-manifest.json:ro
|
||||
ports:
|
||||
- "${POLICY_PORT:-8446}:8446"
|
||||
networks:
|
||||
- stellaops
|
||||
labels: *release-labels
|
||||
|
||||
scheduler:
|
||||
image: registry.stella-ops.org/stellaops/scheduler:russia
|
||||
restart: unless-stopped
|
||||
depends_on:
|
||||
- postgres
|
||||
- nats
|
||||
environment:
|
||||
<<: *crypto-env
|
||||
STELLAOPS_SCHEDULER__STORAGE__DRIVER: "postgres"
|
||||
STELLAOPS_SCHEDULER__STORAGE__POSTGRES__CONNECTIONSTRING: "Host=postgres;Port=5432;Database=${POSTGRES_DB:-stellaops_platform};Username=${POSTGRES_USER:-stellaops};Password=${POSTGRES_PASSWORD:-stellaops}"
|
||||
STELLAOPS_SCHEDULER__MESSAGING__NATS__URL: "nats://nats:4222"
|
||||
volumes:
|
||||
- ../../etc/appsettings.crypto.russia.yaml:/app/etc/appsettings.crypto.yaml:ro
|
||||
- ../../etc/crypto-plugins-manifest.json:/app/etc/crypto-plugins-manifest.json:ro
|
||||
ports:
|
||||
- "${SCHEDULER_PORT:-8447}:8447"
|
||||
networks:
|
||||
- stellaops
|
||||
labels: *release-labels
|
||||
|
||||
notify:
|
||||
image: registry.stella-ops.org/stellaops/notify:russia
|
||||
restart: unless-stopped
|
||||
depends_on:
|
||||
- postgres
|
||||
environment:
|
||||
<<: *crypto-env
|
||||
STELLAOPS_NOTIFY__STORAGE__DRIVER: "postgres"
|
||||
STELLAOPS_NOTIFY__STORAGE__POSTGRES__CONNECTIONSTRING: "Host=postgres;Port=5432;Database=${POSTGRES_DB:-stellaops_platform};Username=${POSTGRES_USER:-stellaops};Password=${POSTGRES_PASSWORD:-stellaops}"
|
||||
volumes:
|
||||
- ../../etc/appsettings.crypto.russia.yaml:/app/etc/appsettings.crypto.yaml:ro
|
||||
- ../../etc/crypto-plugins-manifest.json:/app/etc/crypto-plugins-manifest.json:ro
|
||||
ports:
|
||||
- "${NOTIFY_PORT:-8448}:8448"
|
||||
networks:
|
||||
- stellaops
|
||||
labels: *release-labels
|
||||
|
||||
zastava:
|
||||
image: registry.stella-ops.org/stellaops/zastava:russia
|
||||
restart: unless-stopped
|
||||
depends_on:
|
||||
- postgres
|
||||
environment:
|
||||
<<: *crypto-env
|
||||
STELLAOPS_ZASTAVA__STORAGE__DRIVER: "postgres"
|
||||
STELLAOPS_ZASTAVA__STORAGE__POSTGRES__CONNECTIONSTRING: "Host=postgres;Port=5432;Database=${POSTGRES_DB:-stellaops_platform};Username=${POSTGRES_USER:-stellaops};Password=${POSTGRES_PASSWORD:-stellaops}"
|
||||
volumes:
|
||||
- ../../etc/appsettings.crypto.russia.yaml:/app/etc/appsettings.crypto.yaml:ro
|
||||
- ../../etc/crypto-plugins-manifest.json:/app/etc/crypto-plugins-manifest.json:ro
|
||||
ports:
|
||||
- "${ZASTAVA_PORT:-8449}:8449"
|
||||
networks:
|
||||
- stellaops
|
||||
labels: *release-labels
|
||||
|
||||
gateway:
|
||||
image: registry.stella-ops.org/stellaops/gateway:russia
|
||||
restart: unless-stopped
|
||||
depends_on:
|
||||
- authority
|
||||
- concelier
|
||||
- scanner
|
||||
environment:
|
||||
<<: *crypto-env
|
||||
STELLAOPS_GATEWAY__AUTHORITY__BASEURL: "http://authority:8440"
|
||||
STELLAOPS_GATEWAY__CONCELIER__BASEURL: "http://concelier:8443"
|
||||
STELLAOPS_GATEWAY__SCANNER__BASEURL: "http://scanner:8444"
|
||||
volumes:
|
||||
- ../../etc/appsettings.crypto.russia.yaml:/app/etc/appsettings.crypto.yaml:ro
|
||||
- ../../etc/crypto-plugins-manifest.json:/app/etc/crypto-plugins-manifest.json:ro
|
||||
ports:
|
||||
- "${GATEWAY_PORT:-8080}:8080"
|
||||
networks:
|
||||
- stellaops
|
||||
labels: *release-labels
|
||||
@@ -1,369 +0,0 @@
|
||||
x-release-labels: &release-labels
|
||||
com.stellaops.release.version: "2025.09.2"
|
||||
com.stellaops.release.channel: "stable"
|
||||
com.stellaops.profile: "stage"
|
||||
|
||||
networks:
|
||||
stellaops:
|
||||
driver: bridge
|
||||
|
||||
volumes:
|
||||
valkey-data:
|
||||
rustfs-data:
|
||||
concelier-jobs:
|
||||
nats-data:
|
||||
scanner-surface-cache:
|
||||
postgres-data:
|
||||
advisory-ai-queue:
|
||||
advisory-ai-plans:
|
||||
advisory-ai-outputs:
|
||||
|
||||
services:
|
||||
valkey:
|
||||
image: docker.io/valkey/valkey:8.0
|
||||
restart: unless-stopped
|
||||
command: ["valkey-server", "--appendonly", "yes"]
|
||||
volumes:
|
||||
- valkey-data:/data
|
||||
ports:
|
||||
- "${VALKEY_PORT:-6379}:6379"
|
||||
networks:
|
||||
- stellaops
|
||||
labels: *release-labels
|
||||
|
||||
postgres:
|
||||
image: docker.io/library/postgres:16
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
POSTGRES_USER: "${POSTGRES_USER:-stellaops}"
|
||||
POSTGRES_PASSWORD: "${POSTGRES_PASSWORD:-stellaops}"
|
||||
POSTGRES_DB: "${POSTGRES_DB:-stellaops_platform}"
|
||||
PGDATA: /var/lib/postgresql/data/pgdata
|
||||
volumes:
|
||||
- postgres-data:/var/lib/postgresql/data
|
||||
ports:
|
||||
- "${POSTGRES_PORT:-5432}:5432"
|
||||
networks:
|
||||
- stellaops
|
||||
labels: *release-labels
|
||||
|
||||
rustfs:
|
||||
image: registry.stella-ops.org/stellaops/rustfs:2025.10.0-edge
|
||||
command: ["serve", "--listen", "0.0.0.0:8080", "--root", "/data"]
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
RUSTFS__LOG__LEVEL: info
|
||||
RUSTFS__STORAGE__PATH: /data
|
||||
volumes:
|
||||
- rustfs-data:/data
|
||||
ports:
|
||||
- "${RUSTFS_HTTP_PORT:-8080}:8080"
|
||||
networks:
|
||||
- stellaops
|
||||
labels: *release-labels
|
||||
|
||||
nats:
|
||||
image: docker.io/library/nats@sha256:c82559e4476289481a8a5196e675ebfe67eea81d95e5161e3e78eccfe766608e
|
||||
command:
|
||||
- "-js"
|
||||
- "-sd"
|
||||
- /data
|
||||
restart: unless-stopped
|
||||
ports:
|
||||
- "${NATS_CLIENT_PORT:-4222}:4222"
|
||||
volumes:
|
||||
- nats-data:/data
|
||||
networks:
|
||||
- stellaops
|
||||
labels: *release-labels
|
||||
|
||||
authority:
|
||||
image: registry.stella-ops.org/stellaops/authority@sha256:b0348bad1d0b401cc3c71cb40ba034c8043b6c8874546f90d4783c9dbfcc0bf5
|
||||
restart: unless-stopped
|
||||
depends_on:
|
||||
- postgres
|
||||
- valkey
|
||||
environment:
|
||||
STELLAOPS_AUTHORITY__ISSUER: "${AUTHORITY_ISSUER}"
|
||||
STELLAOPS_AUTHORITY__STORAGE__DRIVER: "postgres"
|
||||
STELLAOPS_AUTHORITY__STORAGE__POSTGRES__CONNECTIONSTRING: "Host=postgres;Port=5432;Database=${POSTGRES_DB:-stellaops_platform};Username=${POSTGRES_USER:-stellaops};Password=${POSTGRES_PASSWORD:-stellaops}"
|
||||
STELLAOPS_AUTHORITY__CACHE__REDIS__CONNECTIONSTRING: "valkey:6379"
|
||||
STELLAOPS_AUTHORITY__PLUGINDIRECTORIES__0: "/app/plugins"
|
||||
STELLAOPS_AUTHORITY__PLUGINS__CONFIGURATIONDIRECTORY: "/app/etc/authority.plugins"
|
||||
volumes:
|
||||
- ../../etc/authority.yaml:/etc/authority.yaml:ro
|
||||
- ../../etc/authority.plugins:/app/etc/authority.plugins:ro
|
||||
ports:
|
||||
- "${AUTHORITY_PORT:-8440}:8440"
|
||||
networks:
|
||||
- stellaops
|
||||
labels: *release-labels
|
||||
|
||||
signer:
|
||||
image: registry.stella-ops.org/stellaops/signer@sha256:8ad574e61f3a9e9bda8a58eb2700ae46813284e35a150b1137bc7c2b92ac0f2e
|
||||
restart: unless-stopped
|
||||
depends_on:
|
||||
- postgres
|
||||
- authority
|
||||
environment:
|
||||
SIGNER__AUTHORITY__BASEURL: "https://authority:8440"
|
||||
SIGNER__POE__INTROSPECTURL: "${SIGNER_POE_INTROSPECT_URL}"
|
||||
SIGNER__STORAGE__DRIVER: "postgres"
|
||||
SIGNER__STORAGE__POSTGRES__CONNECTIONSTRING: "Host=postgres;Port=5432;Database=${POSTGRES_DB:-stellaops_platform};Username=${POSTGRES_USER:-stellaops};Password=${POSTGRES_PASSWORD:-stellaops}"
|
||||
ports:
|
||||
- "${SIGNER_PORT:-8441}:8441"
|
||||
networks:
|
||||
- stellaops
|
||||
labels: *release-labels
|
||||
|
||||
attestor:
|
||||
image: registry.stella-ops.org/stellaops/attestor@sha256:0534985f978b0b5d220d73c96fddd962cd9135f616811cbe3bff4666c5af568f
|
||||
restart: unless-stopped
|
||||
depends_on:
|
||||
- signer
|
||||
- postgres
|
||||
environment:
|
||||
ATTESTOR__SIGNER__BASEURL: "https://signer:8441"
|
||||
ATTESTOR__STORAGE__DRIVER: "postgres"
|
||||
ATTESTOR__STORAGE__POSTGRES__CONNECTIONSTRING: "Host=postgres;Port=5432;Database=${POSTGRES_DB:-stellaops_platform};Username=${POSTGRES_USER:-stellaops};Password=${POSTGRES_PASSWORD:-stellaops}"
|
||||
ports:
|
||||
- "${ATTESTOR_PORT:-8442}:8442"
|
||||
networks:
|
||||
- stellaops
|
||||
labels: *release-labels
|
||||
|
||||
issuer-directory:
|
||||
image: registry.stella-ops.org/stellaops/issuer-directory-web:2025.10.0-edge
|
||||
restart: unless-stopped
|
||||
depends_on:
|
||||
- postgres
|
||||
- authority
|
||||
environment:
|
||||
ISSUERDIRECTORY__CONFIG: "/etc/issuer-directory.yaml"
|
||||
ISSUERDIRECTORY__AUTHORITY__ISSUER: "${AUTHORITY_ISSUER}"
|
||||
ISSUERDIRECTORY__AUTHORITY__BASEURL: "https://authority:8440"
|
||||
ISSUERDIRECTORY__STORAGE__DRIVER: "postgres"
|
||||
ISSUERDIRECTORY__STORAGE__POSTGRES__CONNECTIONSTRING: "Host=postgres;Port=5432;Database=${POSTGRES_DB:-stellaops_platform};Username=${POSTGRES_USER:-stellaops};Password=${POSTGRES_PASSWORD:-stellaops}"
|
||||
ISSUERDIRECTORY__SEEDCSAFPUBLISHERS: "${ISSUER_DIRECTORY_SEED_CSAF:-true}"
|
||||
volumes:
|
||||
- ../../etc/issuer-directory.yaml:/etc/issuer-directory.yaml:ro
|
||||
ports:
|
||||
- "${ISSUER_DIRECTORY_PORT:-8447}:8080"
|
||||
networks:
|
||||
- stellaops
|
||||
labels: *release-labels
|
||||
|
||||
concelier:
|
||||
image: registry.stella-ops.org/stellaops/concelier@sha256:c58cdcaee1d266d68d498e41110a589dd204b487d37381096bd61ab345a867c5
|
||||
restart: unless-stopped
|
||||
depends_on:
|
||||
- postgres
|
||||
- valkey
|
||||
environment:
|
||||
CONCELIER__STORAGE__DRIVER: "postgres"
|
||||
CONCELIER__STORAGE__POSTGRES__CONNECTIONSTRING: "Host=postgres;Port=5432;Database=${POSTGRES_DB:-stellaops_platform};Username=${POSTGRES_USER:-stellaops};Password=${POSTGRES_PASSWORD:-stellaops}"
|
||||
CONCELIER__STORAGE__S3__ENDPOINT: "http://rustfs:8080"
|
||||
CONCELIER__AUTHORITY__BASEURL: "https://authority:8440"
|
||||
CONCELIER__AUTHORITY__RESILIENCE__ALLOWOFFLINECACHEFALLBACK: "true"
|
||||
CONCELIER__AUTHORITY__RESILIENCE__OFFLINECACHETOLERANCE: "${AUTHORITY_OFFLINE_CACHE_TOLERANCE:-00:30:00}"
|
||||
volumes:
|
||||
- concelier-jobs:/var/lib/concelier/jobs
|
||||
ports:
|
||||
- "${CONCELIER_PORT:-8445}:8445"
|
||||
networks:
|
||||
- stellaops
|
||||
labels: *release-labels
|
||||
|
||||
scanner-web:
|
||||
image: registry.stella-ops.org/stellaops/scanner-web@sha256:14b23448c3f9586a9156370b3e8c1991b61907efa666ca37dd3aaed1e79fe3b7
|
||||
restart: unless-stopped
|
||||
depends_on:
|
||||
- postgres
|
||||
- valkey
|
||||
- concelier
|
||||
- rustfs
|
||||
environment:
|
||||
SCANNER__STORAGE__DRIVER: "postgres"
|
||||
SCANNER__STORAGE__POSTGRES__CONNECTIONSTRING: "Host=postgres;Port=5432;Database=${POSTGRES_DB:-stellaops_platform};Username=${POSTGRES_USER:-stellaops};Password=${POSTGRES_PASSWORD:-stellaops}"
|
||||
SCANNER__CACHE__REDIS__CONNECTIONSTRING: "valkey:6379"
|
||||
SCANNER__ARTIFACTSTORE__DRIVER: "rustfs"
|
||||
SCANNER__ARTIFACTSTORE__ENDPOINT: "http://rustfs:8080/api/v1"
|
||||
SCANNER__ARTIFACTSTORE__BUCKET: "scanner-artifacts"
|
||||
SCANNER__ARTIFACTSTORE__TIMEOUTSECONDS: "30"
|
||||
SCANNER__QUEUE__BROKER: "${SCANNER_QUEUE_BROKER:-valkey://valkey:6379}"
|
||||
SCANNER__EVENTS__ENABLED: "${SCANNER_EVENTS_ENABLED:-false}"
|
||||
SCANNER__EVENTS__DRIVER: "${SCANNER_EVENTS_DRIVER:-valkey}"
|
||||
SCANNER__EVENTS__DSN: "${SCANNER_EVENTS_DSN:-}"
|
||||
SCANNER__EVENTS__STREAM: "${SCANNER_EVENTS_STREAM:-stella.events}"
|
||||
SCANNER__EVENTS__PUBLISHTIMEOUTSECONDS: "${SCANNER_EVENTS_PUBLISH_TIMEOUT_SECONDS:-5}"
|
||||
SCANNER__EVENTS__MAXSTREAMLENGTH: "${SCANNER_EVENTS_MAX_STREAM_LENGTH:-10000}"
|
||||
SCANNER__OFFLINEKIT__ENABLED: "${SCANNER_OFFLINEKIT_ENABLED:-false}"
|
||||
SCANNER__OFFLINEKIT__REQUIREDSSE: "${SCANNER_OFFLINEKIT_REQUIREDSSE:-true}"
|
||||
SCANNER__OFFLINEKIT__REKOROFFLINEMODE: "${SCANNER_OFFLINEKIT_REKOROFFLINEMODE:-true}"
|
||||
SCANNER__OFFLINEKIT__TRUSTROOTDIRECTORY: "${SCANNER_OFFLINEKIT_TRUSTROOTDIRECTORY:-/etc/stellaops/trust-roots}"
|
||||
SCANNER__OFFLINEKIT__REKORSNAPSHOTDIRECTORY: "${SCANNER_OFFLINEKIT_REKORSNAPSHOTDIRECTORY:-/var/lib/stellaops/rekor-snapshot}"
|
||||
SCANNER_SURFACE_FS_ENDPOINT: "${SCANNER_SURFACE_FS_ENDPOINT:-http://rustfs:8080}"
|
||||
SCANNER_SURFACE_FS_BUCKET: "${SCANNER_SURFACE_FS_BUCKET:-surface-cache}"
|
||||
SCANNER_SURFACE_CACHE_ROOT: "${SCANNER_SURFACE_CACHE_ROOT:-/var/lib/stellaops/surface}"
|
||||
SCANNER_SURFACE_CACHE_QUOTA_MB: "${SCANNER_SURFACE_CACHE_QUOTA_MB:-4096}"
|
||||
SCANNER_SURFACE_PREFETCH_ENABLED: "${SCANNER_SURFACE_PREFETCH_ENABLED:-false}"
|
||||
SCANNER_SURFACE_TENANT: "${SCANNER_SURFACE_TENANT:-default}"
|
||||
SCANNER_SURFACE_FEATURES: "${SCANNER_SURFACE_FEATURES:-}"
|
||||
SCANNER_SURFACE_SECRETS_PROVIDER: "${SCANNER_SURFACE_SECRETS_PROVIDER:-file}"
|
||||
SCANNER_SURFACE_SECRETS_NAMESPACE: "${SCANNER_SURFACE_SECRETS_NAMESPACE:-}"
|
||||
SCANNER_SURFACE_SECRETS_ROOT: "${SCANNER_SURFACE_SECRETS_ROOT:-/etc/stellaops/secrets}"
|
||||
SCANNER_SURFACE_SECRETS_FALLBACK_PROVIDER: "${SCANNER_SURFACE_SECRETS_FALLBACK_PROVIDER:-}"
|
||||
SCANNER_SURFACE_SECRETS_ALLOW_INLINE: "${SCANNER_SURFACE_SECRETS_ALLOW_INLINE:-false}"
|
||||
volumes:
|
||||
- scanner-surface-cache:/var/lib/stellaops/surface
|
||||
- ${SURFACE_SECRETS_HOST_PATH:-./offline/surface-secrets}:${SCANNER_SURFACE_SECRETS_ROOT:-/etc/stellaops/secrets}:ro
|
||||
- ${SCANNER_OFFLINEKIT_TRUSTROOTS_HOST_PATH:-./offline/trust-roots}:${SCANNER_OFFLINEKIT_TRUSTROOTDIRECTORY:-/etc/stellaops/trust-roots}:ro
|
||||
- ${SCANNER_OFFLINEKIT_REKOR_SNAPSHOT_HOST_PATH:-./offline/rekor-snapshot}:${SCANNER_OFFLINEKIT_REKORSNAPSHOTDIRECTORY:-/var/lib/stellaops/rekor-snapshot}:ro
|
||||
ports:
|
||||
- "${SCANNER_WEB_PORT:-8444}:8444"
|
||||
networks:
|
||||
- stellaops
|
||||
labels: *release-labels
|
||||
|
||||
scanner-worker:
|
||||
image: registry.stella-ops.org/stellaops/scanner-worker@sha256:32e25e76386eb9ea8bee0a1ad546775db9a2df989fab61ac877e351881960dab
|
||||
restart: unless-stopped
|
||||
depends_on:
|
||||
- postgres
|
||||
- valkey
|
||||
- scanner-web
|
||||
- rustfs
|
||||
environment:
|
||||
SCANNER__STORAGE__DRIVER: "postgres"
|
||||
SCANNER__STORAGE__POSTGRES__CONNECTIONSTRING: "Host=postgres;Port=5432;Database=${POSTGRES_DB:-stellaops_platform};Username=${POSTGRES_USER:-stellaops};Password=${POSTGRES_PASSWORD:-stellaops}"
|
||||
SCANNER__CACHE__REDIS__CONNECTIONSTRING: "valkey:6379"
|
||||
SCANNER__ARTIFACTSTORE__DRIVER: "rustfs"
|
||||
SCANNER__ARTIFACTSTORE__ENDPOINT: "http://rustfs:8080/api/v1"
|
||||
SCANNER__ARTIFACTSTORE__BUCKET: "scanner-artifacts"
|
||||
SCANNER__ARTIFACTSTORE__TIMEOUTSECONDS: "30"
|
||||
SCANNER__QUEUE__BROKER: "${SCANNER_QUEUE_BROKER:-valkey://valkey:6379}"
|
||||
SCANNER_SURFACE_FS_ENDPOINT: "${SCANNER_SURFACE_FS_ENDPOINT:-http://rustfs:8080}"
|
||||
SCANNER_SURFACE_FS_BUCKET: "${SCANNER_SURFACE_FS_BUCKET:-surface-cache}"
|
||||
SCANNER_SURFACE_CACHE_ROOT: "${SCANNER_SURFACE_CACHE_ROOT:-/var/lib/stellaops/surface}"
|
||||
SCANNER_SURFACE_CACHE_QUOTA_MB: "${SCANNER_SURFACE_CACHE_QUOTA_MB:-4096}"
|
||||
SCANNER_SURFACE_PREFETCH_ENABLED: "${SCANNER_SURFACE_PREFETCH_ENABLED:-false}"
|
||||
SCANNER_SURFACE_TENANT: "${SCANNER_SURFACE_TENANT:-default}"
|
||||
SCANNER_SURFACE_FEATURES: "${SCANNER_SURFACE_FEATURES:-}"
|
||||
SCANNER_SURFACE_SECRETS_PROVIDER: "${SCANNER_SURFACE_SECRETS_PROVIDER:-file}"
|
||||
SCANNER_SURFACE_SECRETS_NAMESPACE: "${SCANNER_SURFACE_SECRETS_NAMESPACE:-}"
|
||||
SCANNER_SURFACE_SECRETS_ROOT: "${SCANNER_SURFACE_SECRETS_ROOT:-/etc/stellaops/secrets}"
|
||||
SCANNER_SURFACE_SECRETS_FALLBACK_PROVIDER: "${SCANNER_SURFACE_SECRETS_FALLBACK_PROVIDER:-}"
|
||||
SCANNER_SURFACE_SECRETS_ALLOW_INLINE: "${SCANNER_SURFACE_SECRETS_ALLOW_INLINE:-false}"
|
||||
volumes:
|
||||
- scanner-surface-cache:/var/lib/stellaops/surface
|
||||
- ${SURFACE_SECRETS_HOST_PATH:-./offline/surface-secrets}:${SCANNER_SURFACE_SECRETS_ROOT:-/etc/stellaops/secrets}:ro
|
||||
networks:
|
||||
- stellaops
|
||||
labels: *release-labels
|
||||
|
||||
scheduler-worker:
|
||||
image: registry.stella-ops.org/stellaops/scheduler-worker:2025.10.0-edge
|
||||
restart: unless-stopped
|
||||
depends_on:
|
||||
- postgres
|
||||
- valkey
|
||||
- scanner-web
|
||||
command:
|
||||
- "dotnet"
|
||||
- "StellaOps.Scheduler.Worker.Host.dll"
|
||||
environment:
|
||||
SCHEDULER__STORAGE__DRIVER: "postgres"
|
||||
SCHEDULER__STORAGE__POSTGRES__CONNECTIONSTRING: "Host=postgres;Port=5432;Database=${POSTGRES_DB:-stellaops_platform};Username=${POSTGRES_USER:-stellaops};Password=${POSTGRES_PASSWORD:-stellaops}"
|
||||
SCHEDULER__QUEUE__KIND: "${SCHEDULER_QUEUE_KIND:-Valkey}"
|
||||
SCHEDULER__QUEUE__VALKEY__URL: "${SCHEDULER_QUEUE_VALKEY_URL:-valkey:6379}"
|
||||
SCHEDULER__WORKER__RUNNER__SCANNER__BASEADDRESS: "${SCHEDULER_SCANNER_BASEADDRESS:-http://scanner-web:8444}"
|
||||
networks:
|
||||
- stellaops
|
||||
labels: *release-labels
|
||||
|
||||
notify-web:
|
||||
image: ${NOTIFY_WEB_IMAGE:-registry.stella-ops.org/stellaops/notify-web:2025.09.2}
|
||||
restart: unless-stopped
|
||||
depends_on:
|
||||
- postgres
|
||||
- authority
|
||||
environment:
|
||||
DOTNET_ENVIRONMENT: Production
|
||||
volumes:
|
||||
- ../../etc/notify.stage.yaml:/app/etc/notify.yaml:ro
|
||||
ports:
|
||||
- "${NOTIFY_WEB_PORT:-8446}:8446"
|
||||
networks:
|
||||
- stellaops
|
||||
labels: *release-labels
|
||||
|
||||
excititor:
|
||||
image: registry.stella-ops.org/stellaops/excititor@sha256:59022e2016aebcef5c856d163ae705755d3f81949d41195256e935ef40a627fa
|
||||
restart: unless-stopped
|
||||
depends_on:
|
||||
- postgres
|
||||
- concelier
|
||||
environment:
|
||||
EXCITITOR__CONCELIER__BASEURL: "https://concelier:8445"
|
||||
EXCITITOR__STORAGE__DRIVER: "postgres"
|
||||
EXCITITOR__STORAGE__POSTGRES__CONNECTIONSTRING: "Host=postgres;Port=5432;Database=${POSTGRES_DB:-stellaops_platform};Username=${POSTGRES_USER:-stellaops};Password=${POSTGRES_PASSWORD:-stellaops}"
|
||||
networks:
|
||||
- stellaops
|
||||
labels: *release-labels
|
||||
|
||||
advisory-ai-web:
|
||||
image: registry.stella-ops.org/stellaops/advisory-ai-web:2025.09.2
|
||||
restart: unless-stopped
|
||||
depends_on:
|
||||
- scanner-web
|
||||
environment:
|
||||
ADVISORYAI__AdvisoryAI__SbomBaseAddress: "${ADVISORY_AI_SBOM_BASEADDRESS:-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: "${ADVISORY_AI_INFERENCE_MODE:-Local}"
|
||||
ADVISORYAI__AdvisoryAI__Inference__Remote__BaseAddress: "${ADVISORY_AI_REMOTE_BASEADDRESS:-}"
|
||||
ADVISORYAI__AdvisoryAI__Inference__Remote__ApiKey: "${ADVISORY_AI_REMOTE_APIKEY:-}"
|
||||
ports:
|
||||
- "${ADVISORY_AI_WEB_PORT:-8448}:8448"
|
||||
volumes:
|
||||
- advisory-ai-queue:/var/lib/advisory-ai/queue
|
||||
- advisory-ai-plans:/var/lib/advisory-ai/plans
|
||||
- advisory-ai-outputs:/var/lib/advisory-ai/outputs
|
||||
networks:
|
||||
- stellaops
|
||||
labels: *release-labels
|
||||
|
||||
advisory-ai-worker:
|
||||
image: registry.stella-ops.org/stellaops/advisory-ai-worker:2025.09.2
|
||||
restart: unless-stopped
|
||||
depends_on:
|
||||
- advisory-ai-web
|
||||
environment:
|
||||
ADVISORYAI__AdvisoryAI__SbomBaseAddress: "${ADVISORY_AI_SBOM_BASEADDRESS:-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: "${ADVISORY_AI_INFERENCE_MODE:-Local}"
|
||||
ADVISORYAI__AdvisoryAI__Inference__Remote__BaseAddress: "${ADVISORY_AI_REMOTE_BASEADDRESS:-}"
|
||||
ADVISORYAI__AdvisoryAI__Inference__Remote__ApiKey: "${ADVISORY_AI_REMOTE_APIKEY:-}"
|
||||
volumes:
|
||||
- advisory-ai-queue:/var/lib/advisory-ai/queue
|
||||
- advisory-ai-plans:/var/lib/advisory-ai/plans
|
||||
- advisory-ai-outputs:/var/lib/advisory-ai/outputs
|
||||
networks:
|
||||
- stellaops
|
||||
labels: *release-labels
|
||||
|
||||
web-ui:
|
||||
image: registry.stella-ops.org/stellaops/web-ui@sha256:10d924808c48e4353e3a241da62eb7aefe727a1d6dc830eb23a8e181013b3a23
|
||||
restart: unless-stopped
|
||||
depends_on:
|
||||
- scanner-web
|
||||
environment:
|
||||
STELLAOPS_UI__BACKEND__BASEURL: "https://scanner-web:8444"
|
||||
ports:
|
||||
- "${UI_PORT:-8443}:8443"
|
||||
networks:
|
||||
- stellaops
|
||||
labels: *release-labels
|
||||
@@ -1,57 +0,0 @@
|
||||
version: "3.9"
|
||||
|
||||
services:
|
||||
prometheus:
|
||||
image: prom/prometheus:v2.53.0
|
||||
container_name: stellaops-prometheus
|
||||
command:
|
||||
- "--config.file=/etc/prometheus/prometheus.yaml"
|
||||
volumes:
|
||||
- ../telemetry/storage/prometheus.yaml:/etc/prometheus/prometheus.yaml:ro
|
||||
- prometheus-data:/prometheus
|
||||
- ../telemetry/certs:/etc/telemetry/tls:ro
|
||||
- ../telemetry/storage/auth:/etc/telemetry/auth:ro
|
||||
environment:
|
||||
PROMETHEUS_COLLECTOR_TARGET: stellaops-otel-collector:9464
|
||||
ports:
|
||||
- "9090:9090"
|
||||
depends_on:
|
||||
- tempo
|
||||
- loki
|
||||
|
||||
tempo:
|
||||
image: grafana/tempo:2.5.0
|
||||
container_name: stellaops-tempo
|
||||
command:
|
||||
- "-config.file=/etc/tempo/tempo.yaml"
|
||||
volumes:
|
||||
- ../telemetry/storage/tempo.yaml:/etc/tempo/tempo.yaml:ro
|
||||
- ../telemetry/storage/tenants/tempo-overrides.yaml:/etc/telemetry/tenants/tempo-overrides.yaml:ro
|
||||
- ../telemetry/certs:/etc/telemetry/tls:ro
|
||||
- tempo-data:/var/tempo
|
||||
ports:
|
||||
- "3200:3200"
|
||||
environment:
|
||||
TEMPO_ZONE: docker
|
||||
|
||||
loki:
|
||||
image: grafana/loki:3.1.0
|
||||
container_name: stellaops-loki
|
||||
command:
|
||||
- "-config.file=/etc/loki/loki.yaml"
|
||||
volumes:
|
||||
- ../telemetry/storage/loki.yaml:/etc/loki/loki.yaml:ro
|
||||
- ../telemetry/storage/tenants/loki-overrides.yaml:/etc/telemetry/tenants/loki-overrides.yaml:ro
|
||||
- ../telemetry/certs:/etc/telemetry/tls:ro
|
||||
- loki-data:/var/loki
|
||||
ports:
|
||||
- "3100:3100"
|
||||
|
||||
volumes:
|
||||
prometheus-data:
|
||||
tempo-data:
|
||||
loki-data:
|
||||
|
||||
networks:
|
||||
default:
|
||||
name: stellaops-telemetry
|
||||
@@ -1,42 +0,0 @@
|
||||
version: "3.9"
|
||||
|
||||
services:
|
||||
otel-collector:
|
||||
image: otel/opentelemetry-collector:0.105.0
|
||||
container_name: stellaops-otel-collector
|
||||
command:
|
||||
- "--config=/etc/otel-collector/config.yaml"
|
||||
environment:
|
||||
STELLAOPS_OTEL_TLS_CERT: /etc/otel-collector/tls/collector.crt
|
||||
STELLAOPS_OTEL_TLS_KEY: /etc/otel-collector/tls/collector.key
|
||||
STELLAOPS_OTEL_TLS_CA: /etc/otel-collector/tls/ca.crt
|
||||
STELLAOPS_OTEL_PROMETHEUS_ENDPOINT: 0.0.0.0:9464
|
||||
STELLAOPS_OTEL_REQUIRE_CLIENT_CERT: "true"
|
||||
STELLAOPS_TENANT_ID: dev
|
||||
STELLAOPS_TEMPO_ENDPOINT: https://stellaops-tempo:3200
|
||||
STELLAOPS_TEMPO_TLS_CERT_FILE: /etc/otel-collector/tls/client.crt
|
||||
STELLAOPS_TEMPO_TLS_KEY_FILE: /etc/otel-collector/tls/client.key
|
||||
STELLAOPS_TEMPO_TLS_CA_FILE: /etc/otel-collector/tls/ca.crt
|
||||
STELLAOPS_LOKI_ENDPOINT: https://stellaops-loki:3100/loki/api/v1/push
|
||||
STELLAOPS_LOKI_TLS_CERT_FILE: /etc/otel-collector/tls/client.crt
|
||||
STELLAOPS_LOKI_TLS_KEY_FILE: /etc/otel-collector/tls/client.key
|
||||
STELLAOPS_LOKI_TLS_CA_FILE: /etc/otel-collector/tls/ca.crt
|
||||
volumes:
|
||||
- ../telemetry/otel-collector-config.yaml:/etc/otel-collector/config.yaml:ro
|
||||
- ../telemetry/certs:/etc/otel-collector/tls:ro
|
||||
ports:
|
||||
- "4317:4317" # OTLP gRPC (mTLS)
|
||||
- "4318:4318" # OTLP HTTP (mTLS)
|
||||
- "9464:9464" # Prometheus exporter (mTLS)
|
||||
- "13133:13133" # Health check
|
||||
- "1777:1777" # pprof
|
||||
healthcheck:
|
||||
test: ["CMD", "curl", "-fsk", "--cert", "/etc/otel-collector/tls/client.crt", "--key", "/etc/otel-collector/tls/client.key", "--cacert", "/etc/otel-collector/tls/ca.crt", "https://localhost:13133/healthz"]
|
||||
interval: 30s
|
||||
start_period: 15s
|
||||
timeout: 5s
|
||||
retries: 3
|
||||
|
||||
networks:
|
||||
default:
|
||||
name: stellaops-telemetry
|
||||
91
deploy/compose/env/airgap.env.example
vendored
91
deploy/compose/env/airgap.env.example
vendored
@@ -1,91 +0,0 @@
|
||||
# Substitutions for docker-compose.airgap.yaml
|
||||
|
||||
# PostgreSQL Database
|
||||
POSTGRES_USER=stellaops
|
||||
POSTGRES_PASSWORD=airgap-postgres-password
|
||||
POSTGRES_DB=stellaops_platform
|
||||
POSTGRES_PORT=25432
|
||||
|
||||
# Valkey (Redis-compatible cache and messaging)
|
||||
VALKEY_PORT=26379
|
||||
|
||||
# RustFS Object Storage
|
||||
RUSTFS_HTTP_PORT=8080
|
||||
|
||||
# Authority (OAuth2/OIDC)
|
||||
AUTHORITY_ISSUER=https://authority.airgap.local
|
||||
AUTHORITY_PORT=8440
|
||||
AUTHORITY_OFFLINE_CACHE_TOLERANCE=00:45:00
|
||||
|
||||
# Signer
|
||||
SIGNER_POE_INTROSPECT_URL=file:///offline/poe/introspect.json
|
||||
SIGNER_PORT=8441
|
||||
|
||||
# Attestor
|
||||
ATTESTOR_PORT=8442
|
||||
|
||||
# Issuer Directory
|
||||
ISSUER_DIRECTORY_PORT=8447
|
||||
ISSUER_DIRECTORY_SEED_CSAF=true
|
||||
|
||||
# Concelier
|
||||
CONCELIER_PORT=8445
|
||||
|
||||
# Scanner
|
||||
SCANNER_WEB_PORT=8444
|
||||
SCANNER_QUEUE_BROKER=valkey://valkey:6379
|
||||
SCANNER_EVENTS_ENABLED=false
|
||||
SCANNER_EVENTS_DRIVER=valkey
|
||||
SCANNER_EVENTS_DSN=
|
||||
SCANNER_EVENTS_STREAM=stella.events
|
||||
SCANNER_EVENTS_PUBLISH_TIMEOUT_SECONDS=5
|
||||
SCANNER_EVENTS_MAX_STREAM_LENGTH=10000
|
||||
|
||||
# Surface.Env configuration
|
||||
SCANNER_SURFACE_FS_ENDPOINT=http://rustfs:8080
|
||||
SCANNER_SURFACE_FS_BUCKET=surface-cache
|
||||
SCANNER_SURFACE_CACHE_ROOT=/var/lib/stellaops/surface
|
||||
SCANNER_SURFACE_CACHE_QUOTA_MB=4096
|
||||
SCANNER_SURFACE_PREFETCH_ENABLED=false
|
||||
SCANNER_SURFACE_TENANT=default
|
||||
SCANNER_SURFACE_FEATURES=
|
||||
SCANNER_SURFACE_SECRETS_PROVIDER=file
|
||||
SCANNER_SURFACE_SECRETS_NAMESPACE=
|
||||
SCANNER_SURFACE_SECRETS_ROOT=/etc/stellaops/secrets
|
||||
SCANNER_SURFACE_SECRETS_FALLBACK_PROVIDER=
|
||||
SCANNER_SURFACE_SECRETS_ALLOW_INLINE=false
|
||||
SURFACE_SECRETS_HOST_PATH=./offline/surface-secrets
|
||||
|
||||
# Offline Kit configuration
|
||||
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_OFFLINEKIT_TRUSTROOTS_HOST_PATH=./offline/trust-roots
|
||||
SCANNER_OFFLINEKIT_REKOR_SNAPSHOT_HOST_PATH=./offline/rekor-snapshot
|
||||
|
||||
# Zastava inherits Scanner defaults; override if Observer/Webhook diverge
|
||||
ZASTAVA_SURFACE_FS_ENDPOINT=${SCANNER_SURFACE_FS_ENDPOINT}
|
||||
ZASTAVA_SURFACE_CACHE_ROOT=${SCANNER_SURFACE_CACHE_ROOT}
|
||||
|
||||
# Scheduler
|
||||
SCHEDULER_QUEUE_KIND=Valkey
|
||||
SCHEDULER_QUEUE_VALKEY_URL=valkey:6379
|
||||
SCHEDULER_SCANNER_BASEADDRESS=http://scanner-web:8444
|
||||
|
||||
# Notify
|
||||
NOTIFY_WEB_PORT=9446
|
||||
|
||||
# Advisory AI
|
||||
ADVISORY_AI_WEB_PORT=8448
|
||||
ADVISORY_AI_SBOM_BASEADDRESS=http://scanner-web:8444
|
||||
ADVISORY_AI_INFERENCE_MODE=Local
|
||||
ADVISORY_AI_REMOTE_BASEADDRESS=
|
||||
ADVISORY_AI_REMOTE_APIKEY=
|
||||
|
||||
# Web UI
|
||||
UI_PORT=9443
|
||||
|
||||
# NATS
|
||||
NATS_CLIENT_PORT=24222
|
||||
118
deploy/compose/env/cas.env.example
vendored
118
deploy/compose/env/cas.env.example
vendored
@@ -1,118 +0,0 @@
|
||||
# CAS (Content Addressable Storage) Environment Configuration
|
||||
# Copy to .env and customize for your deployment
|
||||
#
|
||||
# Aligned with best-in-class vulnerability scanner retention policies:
|
||||
# - Trivy: 7 days vulnerability DB
|
||||
# - Grype: 5 days DB, configurable
|
||||
# - Anchore Enterprise: 90-365 days typical
|
||||
# - Snyk Enterprise: 365 days
|
||||
|
||||
# =============================================================================
|
||||
# DATA PATHS (ensure directories exist with proper permissions)
|
||||
# =============================================================================
|
||||
CAS_DATA_PATH=/var/lib/stellaops/cas
|
||||
CAS_EVIDENCE_PATH=/var/lib/stellaops/evidence
|
||||
CAS_ATTESTATION_PATH=/var/lib/stellaops/attestations
|
||||
|
||||
# =============================================================================
|
||||
# RUSTFS CONFIGURATION
|
||||
# =============================================================================
|
||||
RUSTFS_LOG_LEVEL=info
|
||||
RUSTFS_COMPRESSION=zstd
|
||||
RUSTFS_COMPRESSION_LEVEL=3
|
||||
|
||||
# =============================================================================
|
||||
# PORTS
|
||||
# =============================================================================
|
||||
RUSTFS_CAS_PORT=8180
|
||||
RUSTFS_EVIDENCE_PORT=8181
|
||||
RUSTFS_ATTESTATION_PORT=8182
|
||||
|
||||
# =============================================================================
|
||||
# ACCESS CONTROL - API KEYS
|
||||
# IMPORTANT: Change these in production!
|
||||
# =============================================================================
|
||||
|
||||
# CAS Storage (mutable, lifecycle-managed)
|
||||
RUSTFS_CAS_API_KEY=cas-api-key-CHANGE-IN-PRODUCTION
|
||||
RUSTFS_CAS_READONLY_KEY=cas-readonly-key-CHANGE-IN-PRODUCTION
|
||||
|
||||
# Evidence Storage (immutable)
|
||||
RUSTFS_EVIDENCE_API_KEY=evidence-api-key-CHANGE-IN-PRODUCTION
|
||||
RUSTFS_EVIDENCE_READONLY_KEY=evidence-readonly-key-CHANGE-IN-PRODUCTION
|
||||
|
||||
# Attestation Storage (immutable)
|
||||
RUSTFS_ATTESTATION_API_KEY=attestation-api-key-CHANGE-IN-PRODUCTION
|
||||
RUSTFS_ATTESTATION_READONLY_KEY=attestation-readonly-key-CHANGE-IN-PRODUCTION
|
||||
|
||||
# =============================================================================
|
||||
# SERVICE ACCOUNT KEYS
|
||||
# Each service has its own key for fine-grained access control
|
||||
# IMPORTANT: Generate unique keys per environment!
|
||||
# =============================================================================
|
||||
|
||||
# Scanner service - access to scanner artifacts, surface cache, runtime facts
|
||||
RUSTFS_SCANNER_KEY=scanner-svc-key-GENERATE-UNIQUE
|
||||
# Bucket access: scanner-artifacts (rw), surface-cache (rw), runtime-facts (rw)
|
||||
|
||||
# Signals service - access to runtime facts, signals data, provenance feed
|
||||
RUSTFS_SIGNALS_KEY=signals-svc-key-GENERATE-UNIQUE
|
||||
# Bucket access: runtime-facts (rw), signals-data (rw), provenance-feed (rw)
|
||||
|
||||
# Replay service - access to replay bundles, inputs lock files
|
||||
RUSTFS_REPLAY_KEY=replay-svc-key-GENERATE-UNIQUE
|
||||
# Bucket access: replay-bundles (rw), inputs-lock (rw)
|
||||
|
||||
# Ledger service - access to evidence bundles, merkle roots, hash chains
|
||||
RUSTFS_LEDGER_KEY=ledger-svc-key-GENERATE-UNIQUE
|
||||
# Bucket access: evidence-bundles (rw), merkle-roots (rw), hash-chains (rw)
|
||||
|
||||
# Exporter service - read-only access to evidence bundles
|
||||
RUSTFS_EXPORTER_KEY=exporter-svc-key-GENERATE-UNIQUE
|
||||
# Bucket access: evidence-bundles (r)
|
||||
|
||||
# Attestor service - access to attestations, DSSE envelopes, Rekor receipts
|
||||
RUSTFS_ATTESTOR_KEY=attestor-svc-key-GENERATE-UNIQUE
|
||||
# Bucket access: attestations (rw), dsse-envelopes (rw), rekor-receipts (rw)
|
||||
|
||||
# Verifier service - read-only access to attestations
|
||||
RUSTFS_VERIFIER_KEY=verifier-svc-key-GENERATE-UNIQUE
|
||||
# Bucket access: attestations (r), dsse-envelopes (r), rekor-receipts (r)
|
||||
|
||||
# Global read-only key (for debugging/auditing)
|
||||
RUSTFS_READONLY_KEY=readonly-global-key-GENERATE-UNIQUE
|
||||
# Bucket access: * (r)
|
||||
|
||||
# =============================================================================
|
||||
# LIFECYCLE MANAGEMENT
|
||||
# =============================================================================
|
||||
# Cron schedule for retention policy enforcement (default: 3 AM daily)
|
||||
LIFECYCLE_CRON=0 3 * * *
|
||||
LIFECYCLE_TELEMETRY=true
|
||||
|
||||
# =============================================================================
|
||||
# RETENTION POLICIES (days, 0 = indefinite)
|
||||
# Aligned with enterprise vulnerability scanner best practices
|
||||
# =============================================================================
|
||||
# Vulnerability DB: 7 days (matches Trivy default, Grype uses 5)
|
||||
CAS_RETENTION_VULNERABILITY_DB_DAYS=7
|
||||
|
||||
# SBOM artifacts: 365 days (audit compliance - SOC2, ISO27001, FedRAMP)
|
||||
CAS_RETENTION_SBOM_ARTIFACTS_DAYS=365
|
||||
|
||||
# Scan results: 90 days (common compliance window)
|
||||
CAS_RETENTION_SCAN_RESULTS_DAYS=90
|
||||
|
||||
# Evidence bundles: indefinite (content-addressed, immutable, audit trail)
|
||||
CAS_RETENTION_EVIDENCE_BUNDLES_DAYS=0
|
||||
|
||||
# Attestations: indefinite (signed, immutable, verifiable)
|
||||
CAS_RETENTION_ATTESTATIONS_DAYS=0
|
||||
|
||||
# Temporary artifacts: 1 day (work-in-progress, intermediate files)
|
||||
CAS_RETENTION_TEMP_ARTIFACTS_DAYS=1
|
||||
|
||||
# =============================================================================
|
||||
# TELEMETRY (optional)
|
||||
# =============================================================================
|
||||
OTLP_ENDPOINT=
|
||||
78
deploy/compose/env/dev.env.example
vendored
78
deploy/compose/env/dev.env.example
vendored
@@ -1,78 +0,0 @@
|
||||
# Substitutions for docker-compose.dev.yaml
|
||||
|
||||
# PostgreSQL Database
|
||||
POSTGRES_USER=stellaops
|
||||
POSTGRES_PASSWORD=dev-postgres-password
|
||||
POSTGRES_DB=stellaops_platform
|
||||
POSTGRES_PORT=5432
|
||||
|
||||
# Valkey (Redis-compatible cache and messaging)
|
||||
VALKEY_PORT=6379
|
||||
|
||||
# RustFS Object Storage
|
||||
RUSTFS_HTTP_PORT=8080
|
||||
|
||||
# Authority (OAuth2/OIDC)
|
||||
AUTHORITY_ISSUER=https://authority.localtest.me
|
||||
AUTHORITY_PORT=8440
|
||||
|
||||
# Signer
|
||||
SIGNER_POE_INTROSPECT_URL=https://licensing.svc.local/introspect
|
||||
SIGNER_PORT=8441
|
||||
|
||||
# Attestor
|
||||
ATTESTOR_PORT=8442
|
||||
|
||||
# Issuer Directory
|
||||
ISSUER_DIRECTORY_PORT=8447
|
||||
ISSUER_DIRECTORY_SEED_CSAF=true
|
||||
|
||||
# Concelier
|
||||
CONCELIER_PORT=8445
|
||||
|
||||
# Scanner
|
||||
SCANNER_WEB_PORT=8444
|
||||
SCANNER_QUEUE_BROKER=nats://nats:4222
|
||||
SCANNER_EVENTS_ENABLED=false
|
||||
SCANNER_EVENTS_DRIVER=valkey
|
||||
SCANNER_EVENTS_DSN=valkey:6379
|
||||
SCANNER_EVENTS_STREAM=stella.events
|
||||
SCANNER_EVENTS_PUBLISH_TIMEOUT_SECONDS=5
|
||||
SCANNER_EVENTS_MAX_STREAM_LENGTH=10000
|
||||
|
||||
# Surface.Env defaults keep worker/web service aligned with local RustFS and inline secrets
|
||||
SCANNER_SURFACE_FS_ENDPOINT=http://rustfs:8080/api/v1
|
||||
SCANNER_SURFACE_CACHE_ROOT=/var/lib/stellaops/surface
|
||||
SCANNER_SURFACE_SECRETS_PROVIDER=inline
|
||||
SCANNER_SURFACE_SECRETS_ROOT=
|
||||
|
||||
# Zastava inherits Scanner defaults; override if Observer/Webhook diverge
|
||||
ZASTAVA_SURFACE_FS_ENDPOINT=${SCANNER_SURFACE_FS_ENDPOINT}
|
||||
ZASTAVA_SURFACE_CACHE_ROOT=${SCANNER_SURFACE_CACHE_ROOT}
|
||||
ZASTAVA_SURFACE_SECRETS_PROVIDER=${SCANNER_SURFACE_SECRETS_PROVIDER}
|
||||
ZASTAVA_SURFACE_SECRETS_ROOT=${SCANNER_SURFACE_SECRETS_ROOT}
|
||||
|
||||
# Scheduler
|
||||
SCHEDULER_QUEUE_KIND=Nats
|
||||
SCHEDULER_QUEUE_NATS_URL=nats://nats:4222
|
||||
SCHEDULER_SCANNER_BASEADDRESS=http://scanner-web:8444
|
||||
|
||||
# Notify
|
||||
NOTIFY_WEB_PORT=8446
|
||||
|
||||
# Advisory AI
|
||||
ADVISORY_AI_WEB_PORT=8448
|
||||
ADVISORY_AI_SBOM_BASEADDRESS=http://scanner-web:8444
|
||||
ADVISORY_AI_INFERENCE_MODE=Local
|
||||
ADVISORY_AI_REMOTE_BASEADDRESS=
|
||||
ADVISORY_AI_REMOTE_APIKEY=
|
||||
|
||||
# Web UI
|
||||
UI_PORT=8443
|
||||
|
||||
# NATS
|
||||
NATS_CLIENT_PORT=4222
|
||||
|
||||
# CryptoPro (optional)
|
||||
CRYPTOPRO_PORT=18080
|
||||
CRYPTOPRO_ACCEPT_EULA=0
|
||||
64
deploy/compose/env/mirror.env.example
vendored
64
deploy/compose/env/mirror.env.example
vendored
@@ -1,64 +0,0 @@
|
||||
# Managed mirror profile substitutions
|
||||
|
||||
# Core infrastructure credentials
|
||||
MONGO_INITDB_ROOT_USERNAME=stellaops_mirror
|
||||
MONGO_INITDB_ROOT_PASSWORD=mirror-password
|
||||
MINIO_ROOT_USER=stellaops-mirror
|
||||
MINIO_ROOT_PASSWORD=mirror-minio-secret
|
||||
RUSTFS_HTTP_PORT=8080
|
||||
|
||||
# Scanner surface integration
|
||||
SCANNER_SURFACE_FS_ENDPOINT=http://rustfs:8080/api/v1
|
||||
SCANNER_SURFACE_CACHE_ROOT=/var/lib/stellaops/surface
|
||||
SCANNER_SURFACE_SECRETS_PROVIDER=file
|
||||
SCANNER_SURFACE_SECRETS_ROOT=/etc/stellaops/secrets
|
||||
|
||||
# Mirror HTTP listeners
|
||||
MIRROR_GATEWAY_HTTP_PORT=8080
|
||||
MIRROR_GATEWAY_HTTPS_PORT=9443
|
||||
|
||||
# Concelier mirror configuration
|
||||
CONCELIER_MIRROR_LATEST_SEGMENT=latest
|
||||
CONCELIER_MIRROR_DIRECTORY_SEGMENT=mirror
|
||||
CONCELIER_MIRROR_REQUIRE_AUTH=true
|
||||
CONCELIER_MIRROR_INDEX_BUDGET=600
|
||||
CONCELIER_MIRROR_DOMAIN_PRIMARY_ID=primary
|
||||
CONCELIER_MIRROR_DOMAIN_PRIMARY_NAME=Primary Mirror
|
||||
CONCELIER_MIRROR_DOMAIN_PRIMARY_AUTH=true
|
||||
CONCELIER_MIRROR_DOMAIN_PRIMARY_DOWNLOAD_BUDGET=3600
|
||||
CONCELIER_MIRROR_DOMAIN_SECONDARY_ID=community
|
||||
CONCELIER_MIRROR_DOMAIN_SECONDARY_NAME=Community Mirror
|
||||
CONCELIER_MIRROR_DOMAIN_SECONDARY_AUTH=false
|
||||
CONCELIER_MIRROR_DOMAIN_SECONDARY_DOWNLOAD_BUDGET=1800
|
||||
|
||||
# Authority integration (tokens issued by production Authority)
|
||||
CONCELIER_AUTHORITY_ENABLED=true
|
||||
CONCELIER_AUTHORITY_ALLOW_ANON=false
|
||||
CONCELIER_AUTHORITY_ISSUER=https://authority.stella-ops.org
|
||||
CONCELIER_AUTHORITY_METADATA=
|
||||
CONCELIER_AUTHORITY_CLIENT_ID=stellaops-concelier-mirror
|
||||
CONCELIER_AUTHORITY_SCOPE=concelier.mirror.read
|
||||
CONCELIER_AUTHORITY_AUDIENCE=api://concelier.mirror
|
||||
|
||||
# Excititor mirror configuration
|
||||
EXCITITOR_MONGO_DATABASE=excititor
|
||||
EXCITITOR_FILESYSTEM_OVERWRITE=false
|
||||
EXCITITOR_MIRROR_DOMAIN_PRIMARY_ID=primary
|
||||
EXCITITOR_MIRROR_DOMAIN_PRIMARY_NAME=Primary Mirror
|
||||
EXCITITOR_MIRROR_DOMAIN_PRIMARY_AUTH=true
|
||||
EXCITITOR_MIRROR_DOMAIN_PRIMARY_INDEX_BUDGET=300
|
||||
EXCITITOR_MIRROR_DOMAIN_PRIMARY_DOWNLOAD_BUDGET=2400
|
||||
EXCITITOR_MIRROR_PRIMARY_EXPORT_CONSENSUS_KEY=consensus-json
|
||||
EXCITITOR_MIRROR_PRIMARY_EXPORT_CONSENSUS_FORMAT=json
|
||||
EXCITITOR_MIRROR_PRIMARY_EXPORT_CONSENSUS_VIEW=consensus
|
||||
EXCITITOR_MIRROR_PRIMARY_EXPORT_OPENVEX_KEY=consensus-openvex
|
||||
EXCITITOR_MIRROR_PRIMARY_EXPORT_OPENVEX_FORMAT=openvex
|
||||
EXCITITOR_MIRROR_PRIMARY_EXPORT_OPENVEX_VIEW=consensus
|
||||
EXCITITOR_MIRROR_DOMAIN_SECONDARY_ID=community
|
||||
EXCITITOR_MIRROR_DOMAIN_SECONDARY_NAME=Community Mirror
|
||||
EXCITITOR_MIRROR_DOMAIN_SECONDARY_AUTH=false
|
||||
EXCITITOR_MIRROR_DOMAIN_SECONDARY_INDEX_BUDGET=120
|
||||
EXCITITOR_MIRROR_DOMAIN_SECONDARY_DOWNLOAD_BUDGET=600
|
||||
EXCITITOR_MIRROR_SECONDARY_EXPORT_KEY=community-consensus
|
||||
EXCITITOR_MIRROR_SECONDARY_EXPORT_FORMAT=json
|
||||
EXCITITOR_MIRROR_SECONDARY_EXPORT_VIEW=consensus
|
||||
12
deploy/compose/env/mock.env.example
vendored
12
deploy/compose/env/mock.env.example
vendored
@@ -1,12 +0,0 @@
|
||||
# Dev-only overlay env for docker-compose.mock.yaml
|
||||
# Use together with dev.env.example:
|
||||
# docker compose --env-file env/dev.env.example --env-file env/mock.env.example -f docker-compose.dev.yaml -f docker-compose.mock.yaml config
|
||||
|
||||
# Optional: override ports if you expose mock services
|
||||
ORCHESTRATOR_PORT=8450
|
||||
POLICY_REGISTRY_PORT=8451
|
||||
VEX_LENS_PORT=8452
|
||||
FINDINGS_LEDGER_PORT=8453
|
||||
VULN_EXPLORER_API_PORT=8454
|
||||
PACKS_REGISTRY_PORT=8455
|
||||
TASK_RUNNER_PORT=8456
|
||||
96
deploy/compose/env/prod.env.example
vendored
96
deploy/compose/env/prod.env.example
vendored
@@ -1,96 +0,0 @@
|
||||
# Substitutions for docker-compose.prod.yaml
|
||||
# WARNING: Replace all placeholder secrets with values sourced from your secret manager.
|
||||
|
||||
# PostgreSQL Database
|
||||
POSTGRES_USER=stellaops-prod
|
||||
POSTGRES_PASSWORD=REPLACE_WITH_STRONG_PASSWORD
|
||||
POSTGRES_DB=stellaops_platform
|
||||
POSTGRES_PORT=5432
|
||||
|
||||
# Valkey (Redis-compatible cache and messaging)
|
||||
VALKEY_PORT=6379
|
||||
|
||||
# RustFS Object Storage
|
||||
RUSTFS_HTTP_PORT=8080
|
||||
|
||||
# Authority (OAuth2/OIDC)
|
||||
AUTHORITY_ISSUER=https://authority.prod.stella-ops.org
|
||||
AUTHORITY_PORT=8440
|
||||
AUTHORITY_OFFLINE_CACHE_TOLERANCE=00:30:00
|
||||
|
||||
# Signer
|
||||
SIGNER_POE_INTROSPECT_URL=https://licensing.prod.stella-ops.org/introspect
|
||||
SIGNER_PORT=8441
|
||||
|
||||
# Attestor
|
||||
ATTESTOR_PORT=8442
|
||||
|
||||
# Issuer Directory
|
||||
ISSUER_DIRECTORY_PORT=8447
|
||||
ISSUER_DIRECTORY_SEED_CSAF=true
|
||||
|
||||
# Concelier
|
||||
CONCELIER_PORT=8445
|
||||
|
||||
# Scanner
|
||||
SCANNER_WEB_PORT=8444
|
||||
SCANNER_QUEUE_BROKER=valkey://valkey:6379
|
||||
# `true` enables signed scanner events for Notify ingestion.
|
||||
SCANNER_EVENTS_ENABLED=true
|
||||
SCANNER_EVENTS_DRIVER=valkey
|
||||
SCANNER_EVENTS_DSN=
|
||||
SCANNER_EVENTS_STREAM=stella.events
|
||||
SCANNER_EVENTS_PUBLISH_TIMEOUT_SECONDS=5
|
||||
SCANNER_EVENTS_MAX_STREAM_LENGTH=10000
|
||||
|
||||
# Surface.Env configuration
|
||||
SCANNER_SURFACE_FS_ENDPOINT=https://surfacefs.prod.stella-ops.org/api/v1
|
||||
SCANNER_SURFACE_FS_BUCKET=surface-cache
|
||||
SCANNER_SURFACE_CACHE_ROOT=/var/lib/stellaops/surface
|
||||
SCANNER_SURFACE_CACHE_QUOTA_MB=4096
|
||||
SCANNER_SURFACE_PREFETCH_ENABLED=false
|
||||
SCANNER_SURFACE_TENANT=default
|
||||
SCANNER_SURFACE_FEATURES=
|
||||
SCANNER_SURFACE_SECRETS_PROVIDER=kubernetes
|
||||
SCANNER_SURFACE_SECRETS_NAMESPACE=
|
||||
SCANNER_SURFACE_SECRETS_ROOT=stellaops/scanner
|
||||
SCANNER_SURFACE_SECRETS_FALLBACK_PROVIDER=
|
||||
SCANNER_SURFACE_SECRETS_ALLOW_INLINE=false
|
||||
SURFACE_SECRETS_HOST_PATH=./offline/surface-secrets
|
||||
|
||||
# Offline Kit configuration
|
||||
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_OFFLINEKIT_TRUSTROOTS_HOST_PATH=./offline/trust-roots
|
||||
SCANNER_OFFLINEKIT_REKOR_SNAPSHOT_HOST_PATH=./offline/rekor-snapshot
|
||||
|
||||
# Zastava inherits Scanner defaults; override if Observer/Webhook diverge
|
||||
ZASTAVA_SURFACE_FS_ENDPOINT=${SCANNER_SURFACE_FS_ENDPOINT}
|
||||
ZASTAVA_SURFACE_CACHE_ROOT=${SCANNER_SURFACE_CACHE_ROOT}
|
||||
|
||||
# Scheduler
|
||||
SCHEDULER_QUEUE_KIND=Valkey
|
||||
SCHEDULER_QUEUE_VALKEY_URL=valkey:6379
|
||||
SCHEDULER_SCANNER_BASEADDRESS=http://scanner-web:8444
|
||||
|
||||
# Notify
|
||||
NOTIFY_WEB_PORT=8446
|
||||
|
||||
# Advisory AI
|
||||
ADVISORY_AI_WEB_PORT=8448
|
||||
ADVISORY_AI_SBOM_BASEADDRESS=https://scanner-web:8444
|
||||
ADVISORY_AI_INFERENCE_MODE=Local
|
||||
ADVISORY_AI_REMOTE_BASEADDRESS=
|
||||
ADVISORY_AI_REMOTE_APIKEY=
|
||||
|
||||
# Web UI
|
||||
UI_PORT=8443
|
||||
|
||||
# NATS
|
||||
NATS_CLIENT_PORT=4222
|
||||
|
||||
# External reverse proxy (Traefik, Envoy, etc.) that terminates TLS.
|
||||
FRONTDOOR_NETWORK=stellaops_frontdoor
|
||||
91
deploy/compose/env/stage.env.example
vendored
91
deploy/compose/env/stage.env.example
vendored
@@ -1,91 +0,0 @@
|
||||
# Substitutions for docker-compose.stage.yaml
|
||||
|
||||
# PostgreSQL Database
|
||||
POSTGRES_USER=stellaops
|
||||
POSTGRES_PASSWORD=stage-postgres-password
|
||||
POSTGRES_DB=stellaops_platform
|
||||
POSTGRES_PORT=5432
|
||||
|
||||
# Valkey (Redis-compatible cache and messaging)
|
||||
VALKEY_PORT=6379
|
||||
|
||||
# RustFS Object Storage
|
||||
RUSTFS_HTTP_PORT=8080
|
||||
|
||||
# Authority (OAuth2/OIDC)
|
||||
AUTHORITY_ISSUER=https://authority.stage.stella-ops.internal
|
||||
AUTHORITY_PORT=8440
|
||||
AUTHORITY_OFFLINE_CACHE_TOLERANCE=00:30:00
|
||||
|
||||
# Signer
|
||||
SIGNER_POE_INTROSPECT_URL=https://licensing.stage.stella-ops.internal/introspect
|
||||
SIGNER_PORT=8441
|
||||
|
||||
# Attestor
|
||||
ATTESTOR_PORT=8442
|
||||
|
||||
# Issuer Directory
|
||||
ISSUER_DIRECTORY_PORT=8447
|
||||
ISSUER_DIRECTORY_SEED_CSAF=true
|
||||
|
||||
# Concelier
|
||||
CONCELIER_PORT=8445
|
||||
|
||||
# Scanner
|
||||
SCANNER_WEB_PORT=8444
|
||||
SCANNER_QUEUE_BROKER=valkey://valkey:6379
|
||||
SCANNER_EVENTS_ENABLED=false
|
||||
SCANNER_EVENTS_DRIVER=valkey
|
||||
SCANNER_EVENTS_DSN=
|
||||
SCANNER_EVENTS_STREAM=stella.events
|
||||
SCANNER_EVENTS_PUBLISH_TIMEOUT_SECONDS=5
|
||||
SCANNER_EVENTS_MAX_STREAM_LENGTH=10000
|
||||
|
||||
# Surface.Env configuration
|
||||
SCANNER_SURFACE_FS_ENDPOINT=http://rustfs:8080
|
||||
SCANNER_SURFACE_FS_BUCKET=surface-cache
|
||||
SCANNER_SURFACE_CACHE_ROOT=/var/lib/stellaops/surface
|
||||
SCANNER_SURFACE_CACHE_QUOTA_MB=4096
|
||||
SCANNER_SURFACE_PREFETCH_ENABLED=false
|
||||
SCANNER_SURFACE_TENANT=default
|
||||
SCANNER_SURFACE_FEATURES=
|
||||
SCANNER_SURFACE_SECRETS_PROVIDER=kubernetes
|
||||
SCANNER_SURFACE_SECRETS_NAMESPACE=
|
||||
SCANNER_SURFACE_SECRETS_ROOT=stellaops/scanner
|
||||
SCANNER_SURFACE_SECRETS_FALLBACK_PROVIDER=
|
||||
SCANNER_SURFACE_SECRETS_ALLOW_INLINE=false
|
||||
SURFACE_SECRETS_HOST_PATH=./offline/surface-secrets
|
||||
|
||||
# Offline Kit configuration
|
||||
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_OFFLINEKIT_TRUSTROOTS_HOST_PATH=./offline/trust-roots
|
||||
SCANNER_OFFLINEKIT_REKOR_SNAPSHOT_HOST_PATH=./offline/rekor-snapshot
|
||||
|
||||
# Zastava inherits Scanner defaults; override if Observer/Webhook diverge
|
||||
ZASTAVA_SURFACE_FS_ENDPOINT=${SCANNER_SURFACE_FS_ENDPOINT}
|
||||
ZASTAVA_SURFACE_CACHE_ROOT=${SCANNER_SURFACE_CACHE_ROOT}
|
||||
|
||||
# Scheduler
|
||||
SCHEDULER_QUEUE_KIND=Valkey
|
||||
SCHEDULER_QUEUE_VALKEY_URL=valkey:6379
|
||||
SCHEDULER_SCANNER_BASEADDRESS=http://scanner-web:8444
|
||||
|
||||
# Notify
|
||||
NOTIFY_WEB_PORT=8446
|
||||
|
||||
# Advisory AI
|
||||
ADVISORY_AI_WEB_PORT=8448
|
||||
ADVISORY_AI_SBOM_BASEADDRESS=http://scanner-web:8444
|
||||
ADVISORY_AI_INFERENCE_MODE=Local
|
||||
ADVISORY_AI_REMOTE_BASEADDRESS=
|
||||
ADVISORY_AI_REMOTE_APIKEY=
|
||||
|
||||
# Web UI
|
||||
UI_PORT=8443
|
||||
|
||||
# NATS
|
||||
NATS_CLIENT_PORT=4222
|
||||
@@ -1,13 +0,0 @@
|
||||
# Mirror Gateway Assets
|
||||
|
||||
This directory holds the reverse-proxy configuration and TLS material for the managed
|
||||
mirror profile:
|
||||
|
||||
- `conf.d/*.conf` – nginx configuration shipped with the profile.
|
||||
- `tls/` – place environment-specific certificates and private keys
|
||||
(`mirror-primary.{crt,key}`, `mirror-community.{crt,key}`, etc.).
|
||||
- `secrets/` – populate Basic Auth credential stores (`*.htpasswd`) that gate each
|
||||
mirror domain. Generate with `htpasswd -B`.
|
||||
|
||||
The Compose bundle mounts these paths read-only. Populate `tls/` with the actual
|
||||
certificates before invoking `docker compose config` or `docker compose up`.
|
||||
@@ -1,44 +0,0 @@
|
||||
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;
|
||||
}
|
||||
@@ -1,51 +0,0 @@
|
||||
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 concelier:8445;
|
||||
keepalive 32;
|
||||
}
|
||||
|
||||
upstream excititor_backend {
|
||||
server 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;
|
||||
}
|
||||
@@ -1,33 +0,0 @@
|
||||
-- PostgreSQL initialization for StellaOps air-gap deployment
|
||||
-- This script runs automatically on first container start
|
||||
|
||||
-- Enable pg_stat_statements extension for query performance analysis
|
||||
CREATE EXTENSION IF NOT EXISTS pg_stat_statements;
|
||||
|
||||
-- Enable other useful extensions
|
||||
CREATE EXTENSION IF NOT EXISTS pg_trgm; -- Fuzzy text search
|
||||
CREATE EXTENSION IF NOT EXISTS btree_gin; -- GIN indexes for scalar types
|
||||
CREATE EXTENSION IF NOT EXISTS pgcrypto; -- Cryptographic functions
|
||||
|
||||
-- Create schemas for all modules
|
||||
-- Migrations will create tables within these schemas
|
||||
CREATE SCHEMA IF NOT EXISTS authority;
|
||||
CREATE SCHEMA IF NOT EXISTS vuln;
|
||||
CREATE SCHEMA IF NOT EXISTS vex;
|
||||
CREATE SCHEMA IF NOT EXISTS scheduler;
|
||||
CREATE SCHEMA IF NOT EXISTS notify;
|
||||
CREATE SCHEMA IF NOT EXISTS policy;
|
||||
CREATE SCHEMA IF NOT EXISTS concelier;
|
||||
CREATE SCHEMA IF NOT EXISTS audit;
|
||||
CREATE SCHEMA IF NOT EXISTS unknowns;
|
||||
|
||||
-- Grant usage to application user (assumes POSTGRES_USER is the app user)
|
||||
GRANT USAGE ON SCHEMA authority TO PUBLIC;
|
||||
GRANT USAGE ON SCHEMA vuln TO PUBLIC;
|
||||
GRANT USAGE ON SCHEMA vex TO PUBLIC;
|
||||
GRANT USAGE ON SCHEMA scheduler TO PUBLIC;
|
||||
GRANT USAGE ON SCHEMA notify TO PUBLIC;
|
||||
GRANT USAGE ON SCHEMA policy TO PUBLIC;
|
||||
GRANT USAGE ON SCHEMA concelier TO PUBLIC;
|
||||
GRANT USAGE ON SCHEMA audit TO PUBLIC;
|
||||
GRANT USAGE ON SCHEMA unknowns TO PUBLIC;
|
||||
@@ -1,28 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
echo "StellaOps Compose Backup"
|
||||
echo "This will create a tar.gz of Mongo, MinIO (object-store), and Redis data volumes."
|
||||
read -rp "Proceed? [y/N] " ans
|
||||
[[ ${ans:-N} =~ ^[Yy]$ ]] || { echo "Aborted."; exit 1; }
|
||||
|
||||
TS=$(date -u +%Y%m%dT%H%M%SZ)
|
||||
OUT_DIR=${BACKUP_DIR:-backups}
|
||||
mkdir -p "$OUT_DIR"
|
||||
|
||||
docker compose ps >/dev/null
|
||||
|
||||
echo "Pausing worker containers for consistency..."
|
||||
docker compose pause scanner-worker scheduler-worker taskrunner-worker || true
|
||||
|
||||
echo "Backing up volumes..."
|
||||
docker run --rm \
|
||||
-v stellaops-mongo:/data/db:ro \
|
||||
-v stellaops-minio:/data/minio:ro \
|
||||
-v stellaops-redis:/data/redis:ro \
|
||||
-v "$PWD/$OUT_DIR":/out \
|
||||
alpine sh -c "cd / && tar czf /out/stellaops-backup-$TS.tar.gz data"
|
||||
|
||||
docker compose unpause scanner-worker scheduler-worker taskrunner-worker || true
|
||||
|
||||
echo "Backup written to $OUT_DIR/stellaops-backup-$TS.tar.gz"
|
||||
@@ -1,25 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
COMPOSE_DIR="$(cd "$SCRIPT_DIR/.." && pwd)"
|
||||
|
||||
ENV_FILE="${1:-$COMPOSE_DIR/env/dev.env.example}"
|
||||
USE_MOCK="${USE_MOCK:-0}"
|
||||
|
||||
FILES=(-f "$COMPOSE_DIR/docker-compose.dev.yaml")
|
||||
ENV_FILES=(--env-file "$ENV_FILE")
|
||||
|
||||
if [[ "$USE_MOCK" == "1" ]]; then
|
||||
FILES+=(-f "$COMPOSE_DIR/docker-compose.mock.yaml")
|
||||
ENV_FILES+=(--env-file "$COMPOSE_DIR/env/mock.env.example")
|
||||
fi
|
||||
|
||||
echo "Validating compose config..."
|
||||
docker compose "${ENV_FILES[@]}" "${FILES[@]}" config > /tmp/compose-validated.yaml
|
||||
echo "Config written to /tmp/compose-validated.yaml"
|
||||
|
||||
echo "Starting stack..."
|
||||
docker compose "${ENV_FILES[@]}" "${FILES[@]}" up -d
|
||||
|
||||
echo "Stack started. To stop: docker compose ${ENV_FILES[*]} ${FILES[*]} down"
|
||||
@@ -1,15 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
echo "WARNING: This will stop the stack and wipe Mongo, MinIO, and Redis volumes."
|
||||
read -rp "Type 'RESET' to continue: " ans
|
||||
[[ ${ans:-} == "RESET" ]] || { echo "Aborted."; exit 1; }
|
||||
|
||||
docker compose down
|
||||
|
||||
for vol in stellaops-mongo stellaops-minio stellaops-redis; do
|
||||
echo "Removing volume $vol"
|
||||
docker volume rm "$vol" || true
|
||||
done
|
||||
|
||||
echo "Reset complete. Re-run compose with your env file to recreate volumes."
|
||||
@@ -1,172 +0,0 @@
|
||||
# syntax=docker/dockerfile:1.4
|
||||
# StellaOps Regional Crypto Profile
|
||||
# Selects regional cryptographic configuration at build time
|
||||
|
||||
# ============================================================================
|
||||
# Build Arguments
|
||||
# ============================================================================
|
||||
ARG CRYPTO_PROFILE=international
|
||||
ARG BASE_IMAGE=stellaops/platform:latest
|
||||
ARG SERVICE_NAME=authority
|
||||
|
||||
# ============================================================================
|
||||
# Regional Crypto Profile Layer
|
||||
# ============================================================================
|
||||
FROM ${BASE_IMAGE} AS regional-profile
|
||||
|
||||
# Copy regional cryptographic configuration
|
||||
ARG CRYPTO_PROFILE
|
||||
COPY etc/appsettings.crypto.${CRYPTO_PROFILE}.yaml /app/etc/appsettings.crypto.yaml
|
||||
COPY etc/crypto-plugins-manifest.json /app/etc/crypto-plugins-manifest.json
|
||||
|
||||
# Set environment variable for runtime verification
|
||||
ENV STELLAOPS_CRYPTO_PROFILE=${CRYPTO_PROFILE}
|
||||
ENV STELLAOPS_CRYPTO_CONFIG_PATH=/app/etc/appsettings.crypto.yaml
|
||||
ENV STELLAOPS_CRYPTO_MANIFEST_PATH=/app/etc/crypto-plugins-manifest.json
|
||||
|
||||
# Add labels for metadata
|
||||
LABEL com.stellaops.crypto.profile="${CRYPTO_PROFILE}"
|
||||
LABEL com.stellaops.crypto.config="/app/etc/appsettings.crypto.${CRYPTO_PROFILE}.yaml"
|
||||
LABEL com.stellaops.crypto.runtime-selection="true"
|
||||
|
||||
# ============================================================================
|
||||
# Service-Specific Regional Images
|
||||
# ============================================================================
|
||||
|
||||
# Authority with Regional Crypto
|
||||
FROM regional-profile AS authority
|
||||
WORKDIR /app/authority
|
||||
ENTRYPOINT ["dotnet", "StellaOps.Authority.WebService.dll"]
|
||||
|
||||
# Signer with Regional Crypto
|
||||
FROM regional-profile AS signer
|
||||
WORKDIR /app/signer
|
||||
ENTRYPOINT ["dotnet", "StellaOps.Signer.WebService.dll"]
|
||||
|
||||
# Attestor with Regional Crypto
|
||||
FROM regional-profile AS attestor
|
||||
WORKDIR /app/attestor
|
||||
ENTRYPOINT ["dotnet", "StellaOps.Attestor.WebService.dll"]
|
||||
|
||||
# Concelier with Regional Crypto
|
||||
FROM regional-profile AS concelier
|
||||
WORKDIR /app/concelier
|
||||
ENTRYPOINT ["dotnet", "StellaOps.Concelier.WebService.dll"]
|
||||
|
||||
# Scanner with Regional Crypto
|
||||
FROM regional-profile AS scanner
|
||||
WORKDIR /app/scanner
|
||||
ENTRYPOINT ["dotnet", "StellaOps.Scanner.WebService.dll"]
|
||||
|
||||
# Excititor with Regional Crypto
|
||||
FROM regional-profile AS excititor
|
||||
WORKDIR /app/excititor
|
||||
ENTRYPOINT ["dotnet", "StellaOps.Excititor.WebService.dll"]
|
||||
|
||||
# Policy with Regional Crypto
|
||||
FROM regional-profile AS policy
|
||||
WORKDIR /app/policy
|
||||
ENTRYPOINT ["dotnet", "StellaOps.Policy.WebService.dll"]
|
||||
|
||||
# Scheduler with Regional Crypto
|
||||
FROM regional-profile AS scheduler
|
||||
WORKDIR /app/scheduler
|
||||
ENTRYPOINT ["dotnet", "StellaOps.Scheduler.WebService.dll"]
|
||||
|
||||
# Notify with Regional Crypto
|
||||
FROM regional-profile AS notify
|
||||
WORKDIR /app/notify
|
||||
ENTRYPOINT ["dotnet", "StellaOps.Notify.WebService.dll"]
|
||||
|
||||
# Zastava with Regional Crypto
|
||||
FROM regional-profile AS zastava
|
||||
WORKDIR /app/zastava
|
||||
ENTRYPOINT ["dotnet", "StellaOps.Zastava.WebService.dll"]
|
||||
|
||||
# Gateway with Regional Crypto
|
||||
FROM regional-profile AS gateway
|
||||
WORKDIR /app/gateway
|
||||
ENTRYPOINT ["dotnet", "StellaOps.Gateway.WebService.dll"]
|
||||
|
||||
# AirGap Importer with Regional Crypto
|
||||
FROM regional-profile AS airgap-importer
|
||||
WORKDIR /app/airgap-importer
|
||||
ENTRYPOINT ["dotnet", "StellaOps.AirGap.Importer.dll"]
|
||||
|
||||
# AirGap Exporter with Regional Crypto
|
||||
FROM regional-profile AS airgap-exporter
|
||||
WORKDIR /app/airgap-exporter
|
||||
ENTRYPOINT ["dotnet", "StellaOps.AirGap.Exporter.dll"]
|
||||
|
||||
# CLI with Regional Crypto
|
||||
FROM regional-profile AS cli
|
||||
WORKDIR /app/cli
|
||||
ENTRYPOINT ["dotnet", "StellaOps.Cli.dll"]
|
||||
|
||||
# ============================================================================
|
||||
# Build Instructions
|
||||
# ============================================================================
|
||||
# Build international profile (default):
|
||||
# docker build -f deploy/docker/Dockerfile.crypto-profile \
|
||||
# --build-arg CRYPTO_PROFILE=international \
|
||||
# --target authority \
|
||||
# -t stellaops/authority:international .
|
||||
#
|
||||
# Build Russia (GOST) profile:
|
||||
# docker build -f deploy/docker/Dockerfile.crypto-profile \
|
||||
# --build-arg CRYPTO_PROFILE=russia \
|
||||
# --target scanner \
|
||||
# -t stellaops/scanner:russia .
|
||||
#
|
||||
# Build EU (eIDAS) profile:
|
||||
# docker build -f deploy/docker/Dockerfile.crypto-profile \
|
||||
# --build-arg CRYPTO_PROFILE=eu \
|
||||
# --target signer \
|
||||
# -t stellaops/signer:eu .
|
||||
#
|
||||
# Build China (SM) profile:
|
||||
# docker build -f deploy/docker/Dockerfile.crypto-profile \
|
||||
# --build-arg CRYPTO_PROFILE=china \
|
||||
# --target attestor \
|
||||
# -t stellaops/attestor:china .
|
||||
#
|
||||
# ============================================================================
|
||||
# Regional Profile Descriptions
|
||||
# ============================================================================
|
||||
# international: Default NIST algorithms (ES256, RS256, SHA-256)
|
||||
# Uses offline-verification plugin
|
||||
# Jurisdiction: world
|
||||
#
|
||||
# russia: GOST R 34.10-2012, GOST R 34.11-2012
|
||||
# Uses CryptoPro CSP plugin
|
||||
# Jurisdiction: russia
|
||||
# Requires: CryptoPro CSP SDK
|
||||
#
|
||||
# eu: eIDAS-compliant qualified trust services
|
||||
# Uses eIDAS plugin with qualified certificates
|
||||
# Jurisdiction: eu
|
||||
# Requires: eIDAS trust service provider integration
|
||||
#
|
||||
# china: SM2, SM3, SM4 algorithms
|
||||
# Uses SM crypto plugin
|
||||
# Jurisdiction: china
|
||||
# Requires: GmSSL or BouncyCastle SM extensions
|
||||
#
|
||||
# ============================================================================
|
||||
# Runtime Configuration
|
||||
# ============================================================================
|
||||
# The crypto provider is selected at runtime based on:
|
||||
# 1. STELLAOPS_CRYPTO_PROFILE environment variable
|
||||
# 2. /app/etc/appsettings.crypto.yaml configuration file
|
||||
# 3. /app/etc/crypto-plugins-manifest.json plugin metadata
|
||||
#
|
||||
# Plugin loading sequence:
|
||||
# 1. Application starts
|
||||
# 2. CryptoPluginLoader reads /app/etc/appsettings.crypto.yaml
|
||||
# 3. Loads enabled plugins from manifest
|
||||
# 4. Validates platform compatibility
|
||||
# 5. Validates jurisdiction compliance
|
||||
# 6. Registers providers with DI container
|
||||
# 7. Application uses ICryptoProvider abstraction
|
||||
#
|
||||
# No cryptographic code is executed until runtime plugin selection completes.
|
||||
@@ -1,212 +0,0 @@
|
||||
# syntax=docker/dockerfile:1.4
|
||||
# StellaOps Platform Image - Build Once, Deploy Everywhere
|
||||
# Builds ALL crypto plugins unconditionally for runtime selection
|
||||
|
||||
# ============================================================================
|
||||
# Stage 1: SDK Build - Build ALL Projects and Crypto Plugins
|
||||
# ============================================================================
|
||||
FROM mcr.microsoft.com/dotnet/sdk:10.0-preview AS build
|
||||
WORKDIR /src
|
||||
|
||||
# Copy solution and project files for dependency restore
|
||||
COPY Directory.Build.props Directory.Build.targets nuget.config ./
|
||||
COPY src/StellaOps.sln ./src/
|
||||
|
||||
# Copy all crypto plugin projects
|
||||
COPY src/__Libraries/StellaOps.Cryptography/ ./src/__Libraries/StellaOps.Cryptography/
|
||||
COPY src/__Libraries/StellaOps.Cryptography.DependencyInjection/ ./src/__Libraries/StellaOps.Cryptography.DependencyInjection/
|
||||
COPY src/__Libraries/StellaOps.Cryptography.PluginLoader/ ./src/__Libraries/StellaOps.Cryptography.PluginLoader/
|
||||
|
||||
# Crypto plugins - ALL built unconditionally
|
||||
COPY src/__Libraries/StellaOps.Cryptography.Plugin.OfflineVerification/ ./src/__Libraries/StellaOps.Cryptography.Plugin.OfflineVerification/
|
||||
# Note: Additional crypto plugins can be added here when available:
|
||||
# COPY src/__Libraries/StellaOps.Cryptography.Plugin.eIDAS/ ./src/__Libraries/StellaOps.Cryptography.Plugin.eIDAS/
|
||||
# COPY src/__Libraries/StellaOps.Cryptography.Plugin.CryptoPro/ ./src/__Libraries/StellaOps.Cryptography.Plugin.CryptoPro/
|
||||
# COPY src/__Libraries/StellaOps.Cryptography.Plugin.SM/ ./src/__Libraries/StellaOps.Cryptography.Plugin.SM/
|
||||
|
||||
# Copy all module projects
|
||||
COPY src/Authority/ ./src/Authority/
|
||||
COPY src/Signer/ ./src/Signer/
|
||||
COPY src/Attestor/ ./src/Attestor/
|
||||
COPY src/Concelier/ ./src/Concelier/
|
||||
COPY src/Scanner/ ./src/Scanner/
|
||||
COPY src/AirGap/ ./src/AirGap/
|
||||
COPY src/Excititor/ ./src/Excititor/
|
||||
COPY src/Policy/ ./src/Policy/
|
||||
COPY src/Scheduler/ ./src/Scheduler/
|
||||
COPY src/Notify/ ./src/Notify/
|
||||
COPY src/Zastava/ ./src/Zastava/
|
||||
COPY src/Gateway/ ./src/Gateway/
|
||||
COPY src/Cli/ ./src/Cli/
|
||||
|
||||
# Copy shared libraries
|
||||
COPY src/__Libraries/ ./src/__Libraries/
|
||||
|
||||
# Restore dependencies
|
||||
RUN dotnet restore src/StellaOps.sln
|
||||
|
||||
# Build entire solution (Release configuration)
|
||||
RUN dotnet build src/StellaOps.sln --configuration Release --no-restore
|
||||
|
||||
# Publish all web services and libraries
|
||||
# This creates /app/publish with all assemblies including crypto plugins
|
||||
RUN dotnet publish src/Authority/StellaOps.Authority.WebService/StellaOps.Authority.WebService.csproj \
|
||||
--configuration Release --no-build --output /app/publish/authority
|
||||
|
||||
RUN dotnet publish src/Signer/StellaOps.Signer.WebService/StellaOps.Signer.WebService.csproj \
|
||||
--configuration Release --no-build --output /app/publish/signer
|
||||
|
||||
RUN dotnet publish src/Attestor/StellaOps.Attestor.WebService/StellaOps.Attestor.WebService.csproj \
|
||||
--configuration Release --no-build --output /app/publish/attestor
|
||||
|
||||
RUN dotnet publish src/Concelier/StellaOps.Concelier.WebService/StellaOps.Concelier.WebService.csproj \
|
||||
--configuration Release --no-build --output /app/publish/concelier
|
||||
|
||||
RUN dotnet publish src/Scanner/StellaOps.Scanner.WebService/StellaOps.Scanner.WebService.csproj \
|
||||
--configuration Release --no-build --output /app/publish/scanner
|
||||
|
||||
RUN dotnet publish src/Excititor/StellaOps.Excititor.WebService/StellaOps.Excititor.WebService.csproj \
|
||||
--configuration Release --no-build --output /app/publish/excititor
|
||||
|
||||
RUN dotnet publish src/Policy/StellaOps.Policy.WebService/StellaOps.Policy.WebService.csproj \
|
||||
--configuration Release --no-build --output /app/publish/policy
|
||||
|
||||
RUN dotnet publish src/Scheduler/StellaOps.Scheduler.WebService/StellaOps.Scheduler.WebService.csproj \
|
||||
--configuration Release --no-build --output /app/publish/scheduler
|
||||
|
||||
RUN dotnet publish src/Notify/StellaOps.Notify.WebService/StellaOps.Notify.WebService.csproj \
|
||||
--configuration Release --no-build --output /app/publish/notify
|
||||
|
||||
RUN dotnet publish src/Zastava/StellaOps.Zastava.WebService/StellaOps.Zastava.WebService.csproj \
|
||||
--configuration Release --no-build --output /app/publish/zastava
|
||||
|
||||
RUN dotnet publish src/Gateway/StellaOps.Gateway.WebService/StellaOps.Gateway.WebService.csproj \
|
||||
--configuration Release --no-build --output /app/publish/gateway
|
||||
|
||||
RUN dotnet publish src/AirGap/StellaOps.AirGap.Importer/StellaOps.AirGap.Importer.csproj \
|
||||
--configuration Release --no-build --output /app/publish/airgap-importer
|
||||
|
||||
RUN dotnet publish src/AirGap/StellaOps.AirGap.Exporter/StellaOps.AirGap.Exporter.csproj \
|
||||
--configuration Release --no-build --output /app/publish/airgap-exporter
|
||||
|
||||
RUN dotnet publish src/Cli/StellaOps.Cli/StellaOps.Cli.csproj \
|
||||
--configuration Release --no-build --output /app/publish/cli
|
||||
|
||||
# Copy crypto plugin manifest
|
||||
COPY etc/crypto-plugins-manifest.json /app/publish/etc/
|
||||
|
||||
# ============================================================================
|
||||
# Stage 2: Runtime Base - Contains ALL Crypto Plugins
|
||||
# ============================================================================
|
||||
FROM mcr.microsoft.com/dotnet/aspnet:10.0-preview AS runtime-base
|
||||
WORKDIR /app
|
||||
|
||||
# Install dependencies for crypto providers
|
||||
# PostgreSQL client for Authority/Concelier/etc
|
||||
RUN apt-get update && apt-get install -y \
|
||||
postgresql-client \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
# Copy all published assemblies (includes all crypto plugins)
|
||||
COPY --from=build /app/publish /app/
|
||||
|
||||
# Expose common ports (these can be overridden by docker-compose)
|
||||
EXPOSE 8080 8443
|
||||
|
||||
# Labels
|
||||
LABEL com.stellaops.image.type="platform"
|
||||
LABEL com.stellaops.image.variant="all-plugins"
|
||||
LABEL com.stellaops.crypto.plugins="offline-verification"
|
||||
# Additional plugins will be added as they become available:
|
||||
# LABEL com.stellaops.crypto.plugins="offline-verification,eidas,cryptopro,sm"
|
||||
|
||||
# Health check placeholder (can be overridden per service)
|
||||
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
|
||||
CMD curl -f http://localhost:8080/health || exit 1
|
||||
|
||||
# ============================================================================
|
||||
# Service-Specific Final Stages
|
||||
# ============================================================================
|
||||
|
||||
# Authority Service
|
||||
FROM runtime-base AS authority
|
||||
WORKDIR /app/authority
|
||||
ENTRYPOINT ["dotnet", "StellaOps.Authority.WebService.dll"]
|
||||
|
||||
# Signer Service
|
||||
FROM runtime-base AS signer
|
||||
WORKDIR /app/signer
|
||||
ENTRYPOINT ["dotnet", "StellaOps.Signer.WebService.dll"]
|
||||
|
||||
# Attestor Service
|
||||
FROM runtime-base AS attestor
|
||||
WORKDIR /app/attestor
|
||||
ENTRYPOINT ["dotnet", "StellaOps.Attestor.WebService.dll"]
|
||||
|
||||
# Concelier Service
|
||||
FROM runtime-base AS concelier
|
||||
WORKDIR /app/concelier
|
||||
ENTRYPOINT ["dotnet", "StellaOps.Concelier.WebService.dll"]
|
||||
|
||||
# Scanner Service
|
||||
FROM runtime-base AS scanner
|
||||
WORKDIR /app/scanner
|
||||
ENTRYPOINT ["dotnet", "StellaOps.Scanner.WebService.dll"]
|
||||
|
||||
# Excititor Service
|
||||
FROM runtime-base AS excititor
|
||||
WORKDIR /app/excititor
|
||||
ENTRYPOINT ["dotnet", "StellaOps.Excititor.WebService.dll"]
|
||||
|
||||
# Policy Service
|
||||
FROM runtime-base AS policy
|
||||
WORKDIR /app/policy
|
||||
ENTRYPOINT ["dotnet", "StellaOps.Policy.WebService.dll"]
|
||||
|
||||
# Scheduler Service
|
||||
FROM runtime-base AS scheduler
|
||||
WORKDIR /app/scheduler
|
||||
ENTRYPOINT ["dotnet", "StellaOps.Scheduler.WebService.dll"]
|
||||
|
||||
# Notify Service
|
||||
FROM runtime-base AS notify
|
||||
WORKDIR /app/notify
|
||||
ENTRYPOINT ["dotnet", "StellaOps.Notify.WebService.dll"]
|
||||
|
||||
# Zastava Service
|
||||
FROM runtime-base AS zastava
|
||||
WORKDIR /app/zastava
|
||||
ENTRYPOINT ["dotnet", "StellaOps.Zastava.WebService.dll"]
|
||||
|
||||
# Gateway Service
|
||||
FROM runtime-base AS gateway
|
||||
WORKDIR /app/gateway
|
||||
ENTRYPOINT ["dotnet", "StellaOps.Gateway.WebService.dll"]
|
||||
|
||||
# AirGap Importer (CLI tool)
|
||||
FROM runtime-base AS airgap-importer
|
||||
WORKDIR /app/airgap-importer
|
||||
ENTRYPOINT ["dotnet", "StellaOps.AirGap.Importer.dll"]
|
||||
|
||||
# AirGap Exporter (CLI tool)
|
||||
FROM runtime-base AS airgap-exporter
|
||||
WORKDIR /app/airgap-exporter
|
||||
ENTRYPOINT ["dotnet", "StellaOps.AirGap.Exporter.dll"]
|
||||
|
||||
# CLI Tool
|
||||
FROM runtime-base AS cli
|
||||
WORKDIR /app/cli
|
||||
ENTRYPOINT ["dotnet", "StellaOps.Cli.dll"]
|
||||
|
||||
# ============================================================================
|
||||
# Build Instructions
|
||||
# ============================================================================
|
||||
# Build platform image:
|
||||
# docker build -f deploy/docker/Dockerfile.platform --target runtime-base -t stellaops/platform:latest .
|
||||
#
|
||||
# Build specific service:
|
||||
# docker build -f deploy/docker/Dockerfile.platform --target authority -t stellaops/authority:latest .
|
||||
# docker build -f deploy/docker/Dockerfile.platform --target scanner -t stellaops/scanner:latest .
|
||||
#
|
||||
# The platform image contains ALL crypto plugins.
|
||||
# Regional selection happens at runtime via configuration (see Dockerfile.crypto-profile).
|
||||
@@ -1,18 +0,0 @@
|
||||
{
|
||||
"version": "2025.09.2-mock",
|
||||
"generatedAt": "2025-12-06T00:00:00Z",
|
||||
"items": [
|
||||
{
|
||||
"name": "console-web",
|
||||
"type": "container",
|
||||
"image": "registry.stella-ops.org/stellaops/web-ui@sha256:3878c335df50ca958907849b09d43ce397900d32fc7a417c0bf76742e1217ba1",
|
||||
"channel": "dev-mock"
|
||||
},
|
||||
{
|
||||
"name": "console-bundle",
|
||||
"type": "archive",
|
||||
"url": "https://downloads.stella-ops.mock/console/2025.09.2-mock/console.tar.gz",
|
||||
"sha256": "12dd89e012b1262ac61188ac5b7721ddab80c4e2b6341251d03925eb49a48521"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -1,126 +0,0 @@
|
||||
# StellaOps GitLab CI Templates
|
||||
|
||||
Production-ready GitLab CI templates for keyless signing integration with StellaOps.
|
||||
|
||||
## Quick Start
|
||||
|
||||
Include the templates in your `.gitlab-ci.yml`:
|
||||
|
||||
```yaml
|
||||
include:
|
||||
- project: 'stella-ops/templates'
|
||||
file: 'deploy/gitlab/examples/.gitlab-ci-stellaops.yml'
|
||||
|
||||
sign-my-image:
|
||||
extends: .stellaops-sign
|
||||
variables:
|
||||
ARTIFACT_DIGEST: $IMAGE_DIGEST
|
||||
ARTIFACT_TYPE: image
|
||||
```
|
||||
|
||||
## Available Templates
|
||||
|
||||
### `.stellaops-sign`
|
||||
|
||||
Signs artifacts using keyless signing with Fulcio certificates.
|
||||
|
||||
**Variables:**
|
||||
| Variable | Required | Default | Description |
|
||||
|----------|----------|---------|-------------|
|
||||
| `ARTIFACT_DIGEST` | Yes | - | SHA256 digest of artifact to sign |
|
||||
| `ARTIFACT_TYPE` | No | `image` | Type: image, sbom, verdict, report |
|
||||
| `INCLUDE_REKOR` | No | `true` | Log to Rekor transparency log |
|
||||
| `PUSH_ATTESTATION` | No | `true` | Push attestation to registry |
|
||||
|
||||
**Outputs (dotenv):**
|
||||
- `ATTESTATION_DIGEST`: Digest of created attestation
|
||||
- `REKOR_UUID`: Rekor transparency log UUID
|
||||
- `CERTIFICATE_IDENTITY`: OIDC identity from certificate
|
||||
|
||||
### `.stellaops-verify`
|
||||
|
||||
Verifies attestations before deployment.
|
||||
|
||||
**Variables:**
|
||||
| Variable | Required | Default | Description |
|
||||
|----------|----------|---------|-------------|
|
||||
| `ARTIFACT_DIGEST` | Yes | - | SHA256 digest to verify |
|
||||
| `CERTIFICATE_IDENTITY` | Yes | - | Expected identity pattern (regex) |
|
||||
| `CERTIFICATE_OIDC_ISSUER` | No | `https://gitlab.com` | Expected OIDC issuer |
|
||||
| `REQUIRE_REKOR` | No | `true` | Require Rekor proof |
|
||||
| `STRICT` | No | `true` | Fail on any issue |
|
||||
|
||||
**Outputs (dotenv):**
|
||||
- `VERIFIED`: Whether verification passed
|
||||
- `ATTESTATION_COUNT`: Number of attestations found
|
||||
|
||||
### `.stellaops-sbom`
|
||||
|
||||
Generates, signs, and attaches SBOM to image.
|
||||
|
||||
**Variables:**
|
||||
| Variable | Required | Default | Description |
|
||||
|----------|----------|---------|-------------|
|
||||
| `IMAGE` | Yes | - | Image to generate SBOM for |
|
||||
| `SBOM_FORMAT` | No | `cyclonedx-json` | SBOM format |
|
||||
| `SBOM_OUTPUT` | No | `sbom.json` | Output filename |
|
||||
|
||||
### `.stellaops-verdict`
|
||||
|
||||
Evaluates policy and signs the verdict.
|
||||
|
||||
**Variables:**
|
||||
| Variable | Required | Default | Description |
|
||||
|----------|----------|---------|-------------|
|
||||
| `IMAGE` | Yes | - | Image to evaluate |
|
||||
| `POLICY` | No | `default` | Policy pack ID |
|
||||
| `FAIL_ON_BLOCK` | No | `true` | Fail job if blocked |
|
||||
|
||||
## Identity Patterns for GitLab
|
||||
|
||||
When verifying, use these identity patterns:
|
||||
|
||||
| Constraint | Pattern |
|
||||
|------------|---------|
|
||||
| Any ref in project | `project_path:<group>/<project>:.*` |
|
||||
| Main branch only | `project_path:<group>/<project>:ref_type:branch:ref:main` |
|
||||
| Protected refs | `project_path:<group>/<project>:ref_protected:true` |
|
||||
| Tags | `project_path:<group>/<project>:ref_type:tag:ref:.*` |
|
||||
|
||||
**OIDC Issuer:** Use `${CI_SERVER_URL}` for self-hosted GitLab, or `https://gitlab.com` for GitLab.com.
|
||||
|
||||
## Example Pipeline
|
||||
|
||||
See `examples/example-pipeline.gitlab-ci.yml` for a complete pipeline example.
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### OIDC Token Not Available
|
||||
|
||||
Ensure your job has `id_tokens` configured:
|
||||
|
||||
```yaml
|
||||
my-job:
|
||||
id_tokens:
|
||||
STELLAOPS_OIDC_TOKEN:
|
||||
aud: sigstore
|
||||
```
|
||||
|
||||
### Permission Denied
|
||||
|
||||
Check that:
|
||||
1. The project has OIDC enabled (Settings > CI/CD > Token Access)
|
||||
2. Protected branch/tag settings if using protected pipelines
|
||||
|
||||
### Verification Fails
|
||||
|
||||
Common issues:
|
||||
- Identity pattern doesn't match (check `ref_type` and `ref`)
|
||||
- Wrong issuer (use `${CI_SERVER_URL}` for self-hosted)
|
||||
- Signature was created by different branch/tag
|
||||
|
||||
## Resources
|
||||
|
||||
- [Keyless Signing Guide](../../docs/modules/signer/guides/keyless-signing.md)
|
||||
- [Identity Constraints](../../docs/guides/identity-constraints.md)
|
||||
- [GitLab OIDC Documentation](https://docs.gitlab.com/ee/ci/secrets/id_token_authentication.html)
|
||||
@@ -1,305 +0,0 @@
|
||||
# deploy/gitlab/examples/.gitlab-ci-stellaops.yml
|
||||
# StellaOps Keyless Signing Templates for GitLab CI
|
||||
#
|
||||
# Include this file in your .gitlab-ci.yml to enable keyless signing:
|
||||
#
|
||||
# include:
|
||||
# - project: 'stella-ops/templates'
|
||||
# file: 'deploy/gitlab/examples/.gitlab-ci-stellaops.yml'
|
||||
#
|
||||
# sign-image:
|
||||
# extends: .stellaops-sign
|
||||
# variables:
|
||||
# ARTIFACT_DIGEST: $CI_REGISTRY_IMAGE@sha256:...
|
||||
# ARTIFACT_TYPE: image
|
||||
#
|
||||
# See: docs/modules/signer/guides/keyless-signing.md
|
||||
|
||||
# ==============================================================================
|
||||
# Base Configuration
|
||||
# ==============================================================================
|
||||
|
||||
variables:
|
||||
STELLAOPS_URL: "https://api.stella-ops.org"
|
||||
STELLAOPS_CLI_VERSION: "latest"
|
||||
|
||||
# ==============================================================================
|
||||
# Keyless Signing Job Template
|
||||
# ==============================================================================
|
||||
|
||||
.stellaops-sign:
|
||||
image: stella-ops/cli:${STELLAOPS_CLI_VERSION}
|
||||
id_tokens:
|
||||
STELLAOPS_OIDC_TOKEN:
|
||||
aud: sigstore
|
||||
variables:
|
||||
# Required - must be set by extending job
|
||||
ARTIFACT_DIGEST: ""
|
||||
# Optional - defaults to 'image'
|
||||
ARTIFACT_TYPE: "image"
|
||||
# Optional - include in Rekor transparency log
|
||||
INCLUDE_REKOR: "true"
|
||||
# Optional - push attestation to registry
|
||||
PUSH_ATTESTATION: "true"
|
||||
before_script:
|
||||
- |
|
||||
if [[ -z "${ARTIFACT_DIGEST}" ]]; then
|
||||
echo "ERROR: ARTIFACT_DIGEST must be set"
|
||||
exit 1
|
||||
fi
|
||||
script:
|
||||
- |
|
||||
set -euo pipefail
|
||||
|
||||
SIGN_ARGS=(
|
||||
--keyless
|
||||
--artifact "${ARTIFACT_DIGEST}"
|
||||
--type "${ARTIFACT_TYPE}"
|
||||
--output json
|
||||
)
|
||||
|
||||
if [[ "${INCLUDE_REKOR}" == "true" ]]; then
|
||||
SIGN_ARGS+=(--rekor)
|
||||
fi
|
||||
|
||||
echo "Signing artifact: ${ARTIFACT_DIGEST}"
|
||||
RESULT=$(stella attest sign "${SIGN_ARGS[@]}")
|
||||
|
||||
# Extract outputs for downstream jobs
|
||||
ATTESTATION_DIGEST=$(echo "$RESULT" | jq -r '.attestationDigest')
|
||||
REKOR_UUID=$(echo "$RESULT" | jq -r '.rekorUuid // empty')
|
||||
CERT_IDENTITY=$(echo "$RESULT" | jq -r '.certificateIdentity // empty')
|
||||
|
||||
echo "ATTESTATION_DIGEST=${ATTESTATION_DIGEST}" >> sign.env
|
||||
echo "REKOR_UUID=${REKOR_UUID}" >> sign.env
|
||||
echo "CERTIFICATE_IDENTITY=${CERT_IDENTITY}" >> sign.env
|
||||
|
||||
echo "Attestation created: ${ATTESTATION_DIGEST}"
|
||||
if [[ -n "${REKOR_UUID}" ]]; then
|
||||
echo "Rekor UUID: ${REKOR_UUID}"
|
||||
fi
|
||||
|
||||
# Push attestation if requested
|
||||
if [[ "${PUSH_ATTESTATION}" == "true" ]]; then
|
||||
echo "Pushing attestation to registry..."
|
||||
stella attest push \
|
||||
--attestation "${ATTESTATION_DIGEST}" \
|
||||
--registry "${CI_REGISTRY_IMAGE}"
|
||||
fi
|
||||
artifacts:
|
||||
reports:
|
||||
dotenv: sign.env
|
||||
|
||||
# ==============================================================================
|
||||
# Verification Job Template
|
||||
# ==============================================================================
|
||||
|
||||
.stellaops-verify:
|
||||
image: stella-ops/cli:${STELLAOPS_CLI_VERSION}
|
||||
variables:
|
||||
# Required - must be set by extending job
|
||||
ARTIFACT_DIGEST: ""
|
||||
CERTIFICATE_IDENTITY: ""
|
||||
CERTIFICATE_OIDC_ISSUER: "https://gitlab.com"
|
||||
# Optional - verification settings
|
||||
REQUIRE_REKOR: "true"
|
||||
STRICT: "true"
|
||||
REQUIRE_SBOM: "false"
|
||||
REQUIRE_VERDICT: "false"
|
||||
before_script:
|
||||
- |
|
||||
if [[ -z "${ARTIFACT_DIGEST}" ]]; then
|
||||
echo "ERROR: ARTIFACT_DIGEST must be set"
|
||||
exit 1
|
||||
fi
|
||||
if [[ -z "${CERTIFICATE_IDENTITY}" ]]; then
|
||||
echo "ERROR: CERTIFICATE_IDENTITY must be set"
|
||||
exit 1
|
||||
fi
|
||||
script:
|
||||
- |
|
||||
set -euo pipefail
|
||||
|
||||
VERIFY_ARGS=(
|
||||
--artifact "${ARTIFACT_DIGEST}"
|
||||
--certificate-identity "${CERTIFICATE_IDENTITY}"
|
||||
--certificate-oidc-issuer "${CERTIFICATE_OIDC_ISSUER}"
|
||||
--output json
|
||||
)
|
||||
|
||||
if [[ "${REQUIRE_REKOR}" == "true" ]]; then
|
||||
VERIFY_ARGS+=(--require-rekor)
|
||||
fi
|
||||
|
||||
if [[ "${REQUIRE_SBOM}" == "true" ]]; then
|
||||
VERIFY_ARGS+=(--require-sbom)
|
||||
fi
|
||||
|
||||
if [[ "${REQUIRE_VERDICT}" == "true" ]]; then
|
||||
VERIFY_ARGS+=(--require-verdict)
|
||||
fi
|
||||
|
||||
echo "Verifying artifact: ${ARTIFACT_DIGEST}"
|
||||
echo "Expected identity: ${CERTIFICATE_IDENTITY}"
|
||||
|
||||
set +e
|
||||
RESULT=$(stella attest verify "${VERIFY_ARGS[@]}" 2>&1)
|
||||
EXIT_CODE=$?
|
||||
set -e
|
||||
|
||||
VERIFIED=$(echo "$RESULT" | jq -r '.valid // false')
|
||||
ATTESTATION_COUNT=$(echo "$RESULT" | jq -r '.attestationCount // 0')
|
||||
|
||||
echo "VERIFIED=${VERIFIED}" >> verify.env
|
||||
echo "ATTESTATION_COUNT=${ATTESTATION_COUNT}" >> verify.env
|
||||
|
||||
echo "Verified: ${VERIFIED}"
|
||||
echo "Attestations found: ${ATTESTATION_COUNT}"
|
||||
|
||||
if [[ "$VERIFIED" != "true" ]]; then
|
||||
echo "Verification issues:"
|
||||
echo "$RESULT" | jq -r '.issues[]? | " - \(.code): \(.message)"'
|
||||
|
||||
if [[ "${STRICT}" == "true" ]]; then
|
||||
echo "ERROR: Verification failed in strict mode"
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
artifacts:
|
||||
reports:
|
||||
dotenv: verify.env
|
||||
|
||||
# ==============================================================================
|
||||
# SBOM Generation and Signing Template
|
||||
# ==============================================================================
|
||||
|
||||
.stellaops-sbom:
|
||||
image: stella-ops/cli:${STELLAOPS_CLI_VERSION}
|
||||
id_tokens:
|
||||
STELLAOPS_OIDC_TOKEN:
|
||||
aud: sigstore
|
||||
variables:
|
||||
# Required - image to generate SBOM for
|
||||
IMAGE: ""
|
||||
# Optional - SBOM format
|
||||
SBOM_FORMAT: "cyclonedx-json"
|
||||
# Optional - output file
|
||||
SBOM_OUTPUT: "sbom.json"
|
||||
before_script:
|
||||
- |
|
||||
if [[ -z "${IMAGE}" ]]; then
|
||||
echo "ERROR: IMAGE must be set"
|
||||
exit 1
|
||||
fi
|
||||
script:
|
||||
- |
|
||||
set -euo pipefail
|
||||
|
||||
echo "Generating SBOM for: ${IMAGE}"
|
||||
|
||||
# Generate SBOM
|
||||
stella sbom generate \
|
||||
--image "${IMAGE}" \
|
||||
--format "${SBOM_FORMAT}" \
|
||||
--output "${SBOM_OUTPUT}"
|
||||
|
||||
# Calculate digest
|
||||
SBOM_DIGEST="sha256:$(sha256sum "${SBOM_OUTPUT}" | cut -d' ' -f1)"
|
||||
echo "SBOM digest: ${SBOM_DIGEST}"
|
||||
|
||||
# Sign SBOM
|
||||
echo "Signing SBOM..."
|
||||
RESULT=$(stella attest sign \
|
||||
--keyless \
|
||||
--artifact "${SBOM_DIGEST}" \
|
||||
--type sbom \
|
||||
--rekor \
|
||||
--output json)
|
||||
|
||||
ATTESTATION_DIGEST=$(echo "$RESULT" | jq -r '.attestationDigest')
|
||||
REKOR_UUID=$(echo "$RESULT" | jq -r '.rekorUuid // empty')
|
||||
|
||||
echo "SBOM_DIGEST=${SBOM_DIGEST}" >> sbom.env
|
||||
echo "SBOM_ATTESTATION_DIGEST=${ATTESTATION_DIGEST}" >> sbom.env
|
||||
echo "SBOM_REKOR_UUID=${REKOR_UUID}" >> sbom.env
|
||||
|
||||
# Attach to image
|
||||
echo "Attaching SBOM to image..."
|
||||
stella attest attach \
|
||||
--image "${IMAGE}" \
|
||||
--attestation "${ATTESTATION_DIGEST}" \
|
||||
--type sbom
|
||||
|
||||
echo "SBOM signed and attached successfully"
|
||||
artifacts:
|
||||
paths:
|
||||
- ${SBOM_OUTPUT}
|
||||
reports:
|
||||
dotenv: sbom.env
|
||||
|
||||
# ==============================================================================
|
||||
# Policy Verdict Template
|
||||
# ==============================================================================
|
||||
|
||||
.stellaops-verdict:
|
||||
image: stella-ops/cli:${STELLAOPS_CLI_VERSION}
|
||||
id_tokens:
|
||||
STELLAOPS_OIDC_TOKEN:
|
||||
aud: sigstore
|
||||
variables:
|
||||
# Required - image to evaluate
|
||||
IMAGE: ""
|
||||
# Optional - policy pack ID
|
||||
POLICY: "default"
|
||||
# Optional - fail on block verdict
|
||||
FAIL_ON_BLOCK: "true"
|
||||
before_script:
|
||||
- |
|
||||
if [[ -z "${IMAGE}" ]]; then
|
||||
echo "ERROR: IMAGE must be set"
|
||||
exit 1
|
||||
fi
|
||||
script:
|
||||
- |
|
||||
set -euo pipefail
|
||||
|
||||
echo "Evaluating policy '${POLICY}' for: ${IMAGE}"
|
||||
|
||||
RESULT=$(stella policy evaluate \
|
||||
--image "${IMAGE}" \
|
||||
--policy "${POLICY}" \
|
||||
--output json)
|
||||
|
||||
VERDICT=$(echo "$RESULT" | jq -r '.verdict')
|
||||
VERDICT_DIGEST=$(echo "$RESULT" | jq -r '.verdictDigest')
|
||||
PASSED=$(echo "$RESULT" | jq -r '.passed')
|
||||
|
||||
echo "Verdict: ${VERDICT}"
|
||||
echo "Passed: ${PASSED}"
|
||||
|
||||
# Sign verdict
|
||||
echo "Signing verdict..."
|
||||
SIGN_RESULT=$(stella attest sign \
|
||||
--keyless \
|
||||
--artifact "${VERDICT_DIGEST}" \
|
||||
--type verdict \
|
||||
--rekor \
|
||||
--output json)
|
||||
|
||||
ATTESTATION_DIGEST=$(echo "$SIGN_RESULT" | jq -r '.attestationDigest')
|
||||
REKOR_UUID=$(echo "$SIGN_RESULT" | jq -r '.rekorUuid // empty')
|
||||
|
||||
echo "VERDICT=${VERDICT}" >> verdict.env
|
||||
echo "VERDICT_DIGEST=${VERDICT_DIGEST}" >> verdict.env
|
||||
echo "VERDICT_PASSED=${PASSED}" >> verdict.env
|
||||
echo "VERDICT_ATTESTATION_DIGEST=${ATTESTATION_DIGEST}" >> verdict.env
|
||||
echo "VERDICT_REKOR_UUID=${REKOR_UUID}" >> verdict.env
|
||||
|
||||
# Check if we should fail
|
||||
if [[ "${PASSED}" != "true" && "${FAIL_ON_BLOCK}" == "true" ]]; then
|
||||
echo "ERROR: Policy verdict is ${VERDICT} - blocking deployment"
|
||||
exit 1
|
||||
fi
|
||||
artifacts:
|
||||
reports:
|
||||
dotenv: verdict.env
|
||||
@@ -1,195 +0,0 @@
|
||||
# deploy/gitlab/examples/example-pipeline.gitlab-ci.yml
|
||||
# Example GitLab CI pipeline with StellaOps keyless signing
|
||||
#
|
||||
# This example demonstrates:
|
||||
# - Building and pushing a container image
|
||||
# - Generating and signing SBOM
|
||||
# - Evaluating and signing policy verdict
|
||||
# - Verification gate before deployment
|
||||
#
|
||||
# To use, copy this file to your repository's .gitlab-ci.yml
|
||||
|
||||
include:
|
||||
- local: 'deploy/gitlab/examples/.gitlab-ci-stellaops.yml'
|
||||
# Or include from StellaOps templates project:
|
||||
# - project: 'stella-ops/templates'
|
||||
# file: 'deploy/gitlab/examples/.gitlab-ci-stellaops.yml'
|
||||
|
||||
stages:
|
||||
- build
|
||||
- scan
|
||||
- sign
|
||||
- verify
|
||||
- deploy
|
||||
|
||||
variables:
|
||||
DOCKER_TLS_CERTDIR: "/certs"
|
||||
IMAGE: ${CI_REGISTRY_IMAGE}:${CI_COMMIT_SHORT_SHA}
|
||||
|
||||
# ==============================================================================
|
||||
# Build Stage
|
||||
# ==============================================================================
|
||||
|
||||
build:
|
||||
stage: build
|
||||
image: docker:24
|
||||
services:
|
||||
- docker:24-dind
|
||||
before_script:
|
||||
- docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY
|
||||
script:
|
||||
- |
|
||||
docker build -t ${IMAGE} .
|
||||
docker push ${IMAGE}
|
||||
|
||||
# Get digest
|
||||
DIGEST=$(docker inspect --format='{{index .RepoDigests 0}}' ${IMAGE} | cut -d@ -f2)
|
||||
echo "IMAGE_DIGEST=${DIGEST}" >> build.env
|
||||
echo "IMAGE_REF=${CI_REGISTRY_IMAGE}@${DIGEST}" >> build.env
|
||||
artifacts:
|
||||
reports:
|
||||
dotenv: build.env
|
||||
rules:
|
||||
- if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
|
||||
- if: $CI_COMMIT_TAG
|
||||
|
||||
# ==============================================================================
|
||||
# Scan Stage
|
||||
# ==============================================================================
|
||||
|
||||
generate-sbom:
|
||||
stage: scan
|
||||
extends: .stellaops-sbom
|
||||
needs:
|
||||
- build
|
||||
variables:
|
||||
IMAGE: ${IMAGE_REF}
|
||||
SBOM_FORMAT: "cyclonedx-json"
|
||||
SBOM_OUTPUT: "sbom.cdx.json"
|
||||
rules:
|
||||
- if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
|
||||
- if: $CI_COMMIT_TAG
|
||||
|
||||
vulnerability-scan:
|
||||
stage: scan
|
||||
image: stella-ops/cli:latest
|
||||
needs:
|
||||
- build
|
||||
script:
|
||||
- |
|
||||
stella scan vulnerability \
|
||||
--image "${IMAGE_REF}" \
|
||||
--output json > vulnerabilities.json
|
||||
|
||||
# Extract summary
|
||||
CRITICAL=$(jq '.summary.critical // 0' vulnerabilities.json)
|
||||
HIGH=$(jq '.summary.high // 0' vulnerabilities.json)
|
||||
|
||||
echo "Critical: ${CRITICAL}, High: ${HIGH}"
|
||||
|
||||
if [[ "${CRITICAL}" -gt 0 ]]; then
|
||||
echo "WARNING: ${CRITICAL} critical vulnerabilities found"
|
||||
fi
|
||||
artifacts:
|
||||
paths:
|
||||
- vulnerabilities.json
|
||||
rules:
|
||||
- if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
|
||||
- if: $CI_COMMIT_TAG
|
||||
|
||||
# ==============================================================================
|
||||
# Sign Stage
|
||||
# ==============================================================================
|
||||
|
||||
sign-image:
|
||||
stage: sign
|
||||
extends: .stellaops-sign
|
||||
needs:
|
||||
- build
|
||||
variables:
|
||||
ARTIFACT_DIGEST: ${IMAGE_DIGEST}
|
||||
ARTIFACT_TYPE: "image"
|
||||
rules:
|
||||
- if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
|
||||
- if: $CI_COMMIT_TAG
|
||||
|
||||
evaluate-policy:
|
||||
stage: sign
|
||||
extends: .stellaops-verdict
|
||||
needs:
|
||||
- build
|
||||
- vulnerability-scan
|
||||
variables:
|
||||
IMAGE: ${IMAGE_REF}
|
||||
POLICY: "production"
|
||||
FAIL_ON_BLOCK: "false" # Don't fail here, let verify stage handle it
|
||||
rules:
|
||||
- if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
|
||||
- if: $CI_COMMIT_TAG
|
||||
|
||||
# ==============================================================================
|
||||
# Verify Stage
|
||||
# ==============================================================================
|
||||
|
||||
verify-for-deployment:
|
||||
stage: verify
|
||||
extends: .stellaops-verify
|
||||
needs:
|
||||
- build
|
||||
- sign-image
|
||||
- generate-sbom
|
||||
- evaluate-policy
|
||||
variables:
|
||||
ARTIFACT_DIGEST: ${IMAGE_DIGEST}
|
||||
CERTIFICATE_IDENTITY: "project_path:${CI_PROJECT_PATH}:ref_type:branch:ref:${CI_COMMIT_REF_NAME}"
|
||||
CERTIFICATE_OIDC_ISSUER: "${CI_SERVER_URL}"
|
||||
REQUIRE_SBOM: "true"
|
||||
REQUIRE_VERDICT: "true"
|
||||
STRICT: "true"
|
||||
rules:
|
||||
- if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
|
||||
- if: $CI_COMMIT_TAG
|
||||
|
||||
# ==============================================================================
|
||||
# Deploy Stage
|
||||
# ==============================================================================
|
||||
|
||||
deploy-staging:
|
||||
stage: deploy
|
||||
needs:
|
||||
- build
|
||||
- verify-for-deployment
|
||||
environment:
|
||||
name: staging
|
||||
url: https://staging.example.com
|
||||
script:
|
||||
- |
|
||||
echo "Deploying ${IMAGE_REF} to staging"
|
||||
echo "All attestations verified:"
|
||||
echo " - Image signature: ${ATTESTATION_DIGEST}"
|
||||
echo " - SBOM: ${SBOM_ATTESTATION_DIGEST}"
|
||||
echo " - Policy verdict: ${VERDICT_ATTESTATION_DIGEST}"
|
||||
|
||||
# Add your deployment commands here
|
||||
# kubectl set image deployment/app app=${IMAGE_REF}
|
||||
rules:
|
||||
- if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
|
||||
|
||||
deploy-production:
|
||||
stage: deploy
|
||||
needs:
|
||||
- build
|
||||
- verify-for-deployment
|
||||
- deploy-staging
|
||||
environment:
|
||||
name: production
|
||||
url: https://example.com
|
||||
script:
|
||||
- |
|
||||
echo "Deploying ${IMAGE_REF} to production"
|
||||
echo "Policy verdict: ${VERDICT}"
|
||||
|
||||
# Add your deployment commands here
|
||||
rules:
|
||||
- if: $CI_COMMIT_TAG
|
||||
when: manual
|
||||
@@ -1,306 +0,0 @@
|
||||
# -----------------------------------------------------------------------------
|
||||
# stellaops-gate-example.gitlab-ci.yml
|
||||
# Sprint: SPRINT_20251226_001_BE_cicd_gate_integration
|
||||
# Task: CICD-GATE-08 - GitLab CI example workflow using stella gate evaluate
|
||||
# Description: Example GitLab CI configuration for StellaOps release gate integration
|
||||
# -----------------------------------------------------------------------------
|
||||
#
|
||||
# This configuration demonstrates how to integrate StellaOps release gates into
|
||||
# your GitLab CI/CD pipeline. The gate evaluates security drift between your
|
||||
# current build and the approved baseline, blocking releases that introduce new
|
||||
# reachable vulnerabilities.
|
||||
#
|
||||
# Usage:
|
||||
# Include this file in your .gitlab-ci.yml:
|
||||
# include:
|
||||
# - project: 'stellaops/ci-templates'
|
||||
# file: '/templates/stellaops-gate.gitlab-ci.yml'
|
||||
#
|
||||
# Prerequisites:
|
||||
# 1. STELLAOPS_API_TOKEN variable configured in CI/CD settings
|
||||
# 2. STELLAOPS_BACKEND_URL variable configured (or use default)
|
||||
# 3. Container image built and pushed to registry
|
||||
#
|
||||
# Exit codes:
|
||||
# 0 = Pass - Release may proceed
|
||||
# 1 = Warn - Release may proceed with warnings (configurable)
|
||||
# 2 = Fail - Release blocked due to security policy violation
|
||||
#
|
||||
|
||||
variables:
|
||||
STELLAOPS_BACKEND_URL: ${STELLAOPS_BACKEND_URL:-https://stellaops.internal}
|
||||
STELLAOPS_CLI_VERSION: "latest"
|
||||
# Registry configuration
|
||||
REGISTRY: ${CI_REGISTRY}
|
||||
IMAGE_NAME: ${CI_REGISTRY_IMAGE}
|
||||
|
||||
stages:
|
||||
- build
|
||||
- scan
|
||||
- gate
|
||||
- deploy
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# Build Stage: Build and push container image
|
||||
# -----------------------------------------------------------------------------
|
||||
build:
|
||||
stage: build
|
||||
image: docker:24
|
||||
services:
|
||||
- docker:24-dind
|
||||
variables:
|
||||
DOCKER_TLS_CERTDIR: "/certs"
|
||||
before_script:
|
||||
- docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY
|
||||
script:
|
||||
- |
|
||||
# Build with BuildKit for better caching
|
||||
export DOCKER_BUILDKIT=1
|
||||
|
||||
# Generate image tag based on commit
|
||||
IMAGE_TAG="${CI_REGISTRY_IMAGE}:${CI_COMMIT_SHORT_SHA}"
|
||||
|
||||
# Build and push
|
||||
docker build \
|
||||
--label "org.opencontainers.image.revision=${CI_COMMIT_SHA}" \
|
||||
--label "org.opencontainers.image.source=${CI_PROJECT_URL}" \
|
||||
-t "${IMAGE_TAG}" \
|
||||
.
|
||||
|
||||
docker push "${IMAGE_TAG}"
|
||||
|
||||
# Get the digest
|
||||
IMAGE_DIGEST=$(docker inspect --format='{{index .RepoDigests 0}}' "${IMAGE_TAG}" | cut -d'@' -f2)
|
||||
echo "IMAGE_DIGEST=${IMAGE_DIGEST}" >> build.env
|
||||
echo "IMAGE_REF=${CI_REGISTRY_IMAGE}@${IMAGE_DIGEST}" >> build.env
|
||||
artifacts:
|
||||
reports:
|
||||
dotenv: build.env
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# Gate Stage: Evaluate StellaOps release gate
|
||||
# -----------------------------------------------------------------------------
|
||||
.stellaops-gate-base:
|
||||
stage: gate
|
||||
image: alpine:3.19
|
||||
variables:
|
||||
# Baseline strategy: auto-detect based on branch
|
||||
BASELINE_STRATEGY: "auto"
|
||||
# Allow warnings to pass by default
|
||||
ALLOW_WARNINGS: "true"
|
||||
before_script:
|
||||
- |
|
||||
# Install dependencies
|
||||
apk add --no-cache curl jq bash
|
||||
|
||||
# Install StellaOps CLI
|
||||
curl -sSL https://get.stella-ops.org/cli | bash
|
||||
export PATH="$HOME/.stellaops/bin:$PATH"
|
||||
|
||||
# Verify installation
|
||||
stella --version
|
||||
|
||||
stellaops-gate:
|
||||
extends: .stellaops-gate-base
|
||||
needs:
|
||||
- job: build
|
||||
artifacts: true
|
||||
script:
|
||||
- |
|
||||
# Determine baseline strategy based on branch
|
||||
if [ "$BASELINE_STRATEGY" = "auto" ]; then
|
||||
case "$CI_COMMIT_REF_NAME" in
|
||||
main|master)
|
||||
BASELINE="production"
|
||||
;;
|
||||
release/*)
|
||||
BASELINE="last-approved"
|
||||
;;
|
||||
*)
|
||||
BASELINE="previous-build"
|
||||
;;
|
||||
esac
|
||||
else
|
||||
BASELINE="$BASELINE_STRATEGY"
|
||||
fi
|
||||
|
||||
echo "============================================"
|
||||
echo "StellaOps Release Gate Evaluation"
|
||||
echo "============================================"
|
||||
echo "Image Digest: ${IMAGE_DIGEST}"
|
||||
echo "Baseline Strategy: ${BASELINE}"
|
||||
echo "Branch: ${CI_COMMIT_REF_NAME}"
|
||||
echo "============================================"
|
||||
|
||||
# Run gate evaluation
|
||||
set +e
|
||||
RESULT=$(stella gate evaluate \
|
||||
--image "${IMAGE_DIGEST}" \
|
||||
--baseline "${BASELINE}" \
|
||||
--output json \
|
||||
--ci-context "gitlab-ci" \
|
||||
--repository "${CI_PROJECT_PATH}" \
|
||||
--tag "${CI_COMMIT_SHORT_SHA}" \
|
||||
2>&1)
|
||||
EXIT_CODE=$?
|
||||
set -e
|
||||
|
||||
# Parse results
|
||||
DECISION_ID=$(echo "$RESULT" | jq -r '.decisionId // "unknown"')
|
||||
STATUS=$(echo "$RESULT" | jq -r '.status // "unknown"')
|
||||
SUMMARY=$(echo "$RESULT" | jq -r '.summary // "No summary"')
|
||||
|
||||
# Store for downstream jobs
|
||||
echo "GATE_DECISION_ID=${DECISION_ID}" >> gate.env
|
||||
echo "GATE_STATUS=${STATUS}" >> gate.env
|
||||
echo "GATE_EXIT_CODE=${EXIT_CODE}" >> gate.env
|
||||
|
||||
# Display results
|
||||
echo ""
|
||||
echo "============================================"
|
||||
echo "Gate Result: ${STATUS}"
|
||||
echo "Decision ID: ${DECISION_ID}"
|
||||
echo "============================================"
|
||||
echo "${SUMMARY}"
|
||||
echo "============================================"
|
||||
|
||||
# Handle exit codes
|
||||
case $EXIT_CODE in
|
||||
0)
|
||||
echo "Gate PASSED - Release may proceed"
|
||||
;;
|
||||
1)
|
||||
echo "Gate PASSED WITH WARNINGS"
|
||||
if [ "$ALLOW_WARNINGS" = "true" ]; then
|
||||
echo "Warnings allowed - continuing pipeline"
|
||||
exit 0
|
||||
else
|
||||
echo "Warnings not allowed - blocking pipeline"
|
||||
exit 1
|
||||
fi
|
||||
;;
|
||||
2)
|
||||
echo "Gate BLOCKED - Security policy violation"
|
||||
echo "Review the gate decision for details:"
|
||||
echo "${STELLAOPS_BACKEND_URL}/gates/decisions/${DECISION_ID}"
|
||||
exit 2
|
||||
;;
|
||||
*)
|
||||
echo "Gate evaluation error (exit code: $EXIT_CODE)"
|
||||
exit $EXIT_CODE
|
||||
;;
|
||||
esac
|
||||
artifacts:
|
||||
reports:
|
||||
dotenv: gate.env
|
||||
rules:
|
||||
- if: $CI_COMMIT_BRANCH
|
||||
- if: $CI_MERGE_REQUEST_IID
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# Gate Override: Manual override for blocked releases
|
||||
# -----------------------------------------------------------------------------
|
||||
stellaops-gate-override:
|
||||
extends: .stellaops-gate-base
|
||||
needs:
|
||||
- job: build
|
||||
artifacts: true
|
||||
- job: stellaops-gate
|
||||
artifacts: true
|
||||
script:
|
||||
- |
|
||||
if [ "$GATE_STATUS" != "Fail" ]; then
|
||||
echo "Override not needed - gate status is ${GATE_STATUS}"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
echo "============================================"
|
||||
echo "StellaOps Gate Override Request"
|
||||
echo "============================================"
|
||||
echo "Original Decision ID: ${GATE_DECISION_ID}"
|
||||
echo "Override requested by: ${GITLAB_USER_LOGIN}"
|
||||
echo "Justification: ${OVERRIDE_JUSTIFICATION}"
|
||||
echo "============================================"
|
||||
|
||||
if [ -z "$OVERRIDE_JUSTIFICATION" ]; then
|
||||
echo "ERROR: OVERRIDE_JUSTIFICATION variable must be set"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Request override with justification
|
||||
stella gate evaluate \
|
||||
--image "${IMAGE_DIGEST}" \
|
||||
--baseline "last-approved" \
|
||||
--allow-override \
|
||||
--justification "${OVERRIDE_JUSTIFICATION}" \
|
||||
--ci-context "gitlab-ci-override" \
|
||||
--repository "${CI_PROJECT_PATH}" \
|
||||
--tag "${CI_COMMIT_SHORT_SHA}"
|
||||
rules:
|
||||
- if: $CI_COMMIT_BRANCH
|
||||
when: manual
|
||||
allow_failure: true
|
||||
environment:
|
||||
name: security-override
|
||||
action: prepare
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# Deploy Stage: Deploy to staging (only if gate passed)
|
||||
# -----------------------------------------------------------------------------
|
||||
deploy-staging:
|
||||
stage: deploy
|
||||
image: alpine:3.19
|
||||
needs:
|
||||
- job: build
|
||||
artifacts: true
|
||||
- job: stellaops-gate
|
||||
artifacts: true
|
||||
script:
|
||||
- |
|
||||
echo "Deploying ${IMAGE_REF} to staging..."
|
||||
|
||||
# Verify gate passed
|
||||
if [ "$GATE_STATUS" != "Pass" ] && [ "$GATE_STATUS" != "Warn" ]; then
|
||||
echo "ERROR: Gate did not pass (status: ${GATE_STATUS})"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Add your deployment commands here
|
||||
# Example: kubectl set image deployment/app app=${IMAGE_REF}
|
||||
echo "Deployment complete!"
|
||||
environment:
|
||||
name: staging
|
||||
url: https://staging.example.com
|
||||
rules:
|
||||
- if: $CI_COMMIT_BRANCH == "main"
|
||||
- if: $CI_COMMIT_BRANCH =~ /^release\//
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# Deploy Stage: Deploy to production (requires manual approval)
|
||||
# -----------------------------------------------------------------------------
|
||||
deploy-production:
|
||||
stage: deploy
|
||||
image: alpine:3.19
|
||||
needs:
|
||||
- job: build
|
||||
artifacts: true
|
||||
- job: stellaops-gate
|
||||
artifacts: true
|
||||
script:
|
||||
- |
|
||||
echo "Deploying ${IMAGE_REF} to production..."
|
||||
|
||||
# Verify gate passed (warnings not allowed for production)
|
||||
if [ "$GATE_STATUS" != "Pass" ]; then
|
||||
echo "ERROR: Production deployment requires Pass status (got: ${GATE_STATUS})"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Add your production deployment commands here
|
||||
echo "Production deployment complete!"
|
||||
environment:
|
||||
name: production
|
||||
url: https://example.com
|
||||
rules:
|
||||
- if: $CI_COMMIT_BRANCH == "main"
|
||||
when: manual
|
||||
@@ -1,555 +0,0 @@
|
||||
{
|
||||
"annotations": {
|
||||
"list": [
|
||||
{
|
||||
"builtIn": 1,
|
||||
"datasource": {
|
||||
"type": "grafana",
|
||||
"uid": "-- Grafana --"
|
||||
},
|
||||
"enable": true,
|
||||
"hide": true,
|
||||
"iconColor": "rgba(0, 211, 255, 1)",
|
||||
"name": "Annotations & Alerts",
|
||||
"type": "dashboard"
|
||||
}
|
||||
]
|
||||
},
|
||||
"editable": true,
|
||||
"fiscalYearStartMonth": 0,
|
||||
"graphTooltip": 0,
|
||||
"id": null,
|
||||
"links": [],
|
||||
"liveNow": false,
|
||||
"panels": [
|
||||
{
|
||||
"datasource": {
|
||||
"type": "prometheus",
|
||||
"uid": "${DS_PROMETHEUS}"
|
||||
},
|
||||
"fieldConfig": {
|
||||
"defaults": {
|
||||
"color": {
|
||||
"mode": "thresholds"
|
||||
},
|
||||
"mappings": [],
|
||||
"max": 1,
|
||||
"min": 0,
|
||||
"thresholds": {
|
||||
"mode": "absolute",
|
||||
"steps": [
|
||||
{
|
||||
"color": "red",
|
||||
"value": null
|
||||
},
|
||||
{
|
||||
"color": "yellow",
|
||||
"value": 0.9
|
||||
},
|
||||
{
|
||||
"color": "green",
|
||||
"value": 0.95
|
||||
}
|
||||
]
|
||||
},
|
||||
"unit": "percentunit"
|
||||
},
|
||||
"overrides": []
|
||||
},
|
||||
"gridPos": {
|
||||
"h": 8,
|
||||
"w": 6,
|
||||
"x": 0,
|
||||
"y": 0
|
||||
},
|
||||
"id": 1,
|
||||
"options": {
|
||||
"orientation": "auto",
|
||||
"reduceOptions": {
|
||||
"calcs": [
|
||||
"lastNotNull"
|
||||
],
|
||||
"fields": "",
|
||||
"values": false
|
||||
},
|
||||
"showThresholdLabels": true,
|
||||
"showThresholdMarkers": true
|
||||
},
|
||||
"pluginVersion": "10.0.0",
|
||||
"targets": [
|
||||
{
|
||||
"datasource": {
|
||||
"type": "prometheus",
|
||||
"uid": "${DS_PROMETHEUS}"
|
||||
},
|
||||
"expr": "sum(stella_attestations_created_total) / (sum(stella_attestations_created_total) + sum(stella_attestations_failed_total))",
|
||||
"refId": "A"
|
||||
}
|
||||
],
|
||||
"title": "Attestation Completeness (Target: ≥95%)",
|
||||
"type": "gauge"
|
||||
},
|
||||
{
|
||||
"datasource": {
|
||||
"type": "prometheus",
|
||||
"uid": "${DS_PROMETHEUS}"
|
||||
},
|
||||
"fieldConfig": {
|
||||
"defaults": {
|
||||
"color": {
|
||||
"mode": "palette-classic"
|
||||
},
|
||||
"custom": {
|
||||
"axisCenteredZero": false,
|
||||
"axisColorMode": "text",
|
||||
"axisLabel": "",
|
||||
"axisPlacement": "auto",
|
||||
"barAlignment": 0,
|
||||
"drawStyle": "bars",
|
||||
"fillOpacity": 80,
|
||||
"gradientMode": "none",
|
||||
"hideFrom": {
|
||||
"tooltip": false,
|
||||
"viz": false,
|
||||
"legend": false
|
||||
},
|
||||
"lineInterpolation": "linear",
|
||||
"lineWidth": 1,
|
||||
"pointSize": 5,
|
||||
"scaleDistribution": {
|
||||
"type": "linear"
|
||||
},
|
||||
"showPoints": "auto",
|
||||
"spanNulls": false,
|
||||
"stacking": {
|
||||
"group": "A",
|
||||
"mode": "none"
|
||||
},
|
||||
"thresholdsStyle": {
|
||||
"mode": "line"
|
||||
}
|
||||
},
|
||||
"mappings": [],
|
||||
"thresholds": {
|
||||
"mode": "absolute",
|
||||
"steps": [
|
||||
{
|
||||
"color": "green",
|
||||
"value": null
|
||||
},
|
||||
{
|
||||
"color": "red",
|
||||
"value": 30
|
||||
}
|
||||
]
|
||||
},
|
||||
"unit": "s"
|
||||
},
|
||||
"overrides": []
|
||||
},
|
||||
"gridPos": {
|
||||
"h": 8,
|
||||
"w": 9,
|
||||
"x": 6,
|
||||
"y": 0
|
||||
},
|
||||
"id": 2,
|
||||
"options": {
|
||||
"legend": {
|
||||
"calcs": ["mean", "max"],
|
||||
"displayMode": "table",
|
||||
"placement": "right",
|
||||
"showLegend": true
|
||||
},
|
||||
"tooltip": {
|
||||
"mode": "single",
|
||||
"sort": "none"
|
||||
}
|
||||
},
|
||||
"targets": [
|
||||
{
|
||||
"datasource": {
|
||||
"type": "prometheus",
|
||||
"uid": "${DS_PROMETHEUS}"
|
||||
},
|
||||
"expr": "histogram_quantile(0.95, rate(stella_ttfe_seconds_bucket[5m]))",
|
||||
"legendFormat": "p95",
|
||||
"refId": "A"
|
||||
},
|
||||
{
|
||||
"datasource": {
|
||||
"type": "prometheus",
|
||||
"uid": "${DS_PROMETHEUS}"
|
||||
},
|
||||
"expr": "histogram_quantile(0.50, rate(stella_ttfe_seconds_bucket[5m]))",
|
||||
"legendFormat": "p50",
|
||||
"refId": "B"
|
||||
}
|
||||
],
|
||||
"title": "TTFE Distribution (Target: ≤30s)",
|
||||
"type": "timeseries"
|
||||
},
|
||||
{
|
||||
"datasource": {
|
||||
"type": "prometheus",
|
||||
"uid": "${DS_PROMETHEUS}"
|
||||
},
|
||||
"fieldConfig": {
|
||||
"defaults": {
|
||||
"color": {
|
||||
"mode": "palette-classic"
|
||||
},
|
||||
"custom": {
|
||||
"axisCenteredZero": false,
|
||||
"axisColorMode": "text",
|
||||
"axisLabel": "",
|
||||
"axisPlacement": "auto",
|
||||
"barAlignment": 0,
|
||||
"drawStyle": "line",
|
||||
"fillOpacity": 20,
|
||||
"gradientMode": "none",
|
||||
"hideFrom": {
|
||||
"tooltip": false,
|
||||
"viz": false,
|
||||
"legend": false
|
||||
},
|
||||
"lineInterpolation": "smooth",
|
||||
"lineWidth": 2,
|
||||
"pointSize": 5,
|
||||
"scaleDistribution": {
|
||||
"type": "linear"
|
||||
},
|
||||
"showPoints": "auto",
|
||||
"spanNulls": false,
|
||||
"stacking": {
|
||||
"group": "A",
|
||||
"mode": "none"
|
||||
},
|
||||
"thresholdsStyle": {
|
||||
"mode": "off"
|
||||
}
|
||||
},
|
||||
"mappings": [],
|
||||
"max": 1,
|
||||
"min": 0,
|
||||
"thresholds": {
|
||||
"mode": "absolute",
|
||||
"steps": [
|
||||
{
|
||||
"color": "green",
|
||||
"value": null
|
||||
}
|
||||
]
|
||||
},
|
||||
"unit": "percentunit"
|
||||
},
|
||||
"overrides": []
|
||||
},
|
||||
"gridPos": {
|
||||
"h": 8,
|
||||
"w": 9,
|
||||
"x": 15,
|
||||
"y": 0
|
||||
},
|
||||
"id": 3,
|
||||
"options": {
|
||||
"legend": {
|
||||
"calcs": ["mean", "last"],
|
||||
"displayMode": "table",
|
||||
"placement": "right",
|
||||
"showLegend": true
|
||||
},
|
||||
"tooltip": {
|
||||
"mode": "single",
|
||||
"sort": "none"
|
||||
}
|
||||
},
|
||||
"targets": [
|
||||
{
|
||||
"datasource": {
|
||||
"type": "prometheus",
|
||||
"uid": "${DS_PROMETHEUS}"
|
||||
},
|
||||
"expr": "sum(rate(stella_attestations_verified_total[5m])) / (sum(rate(stella_attestations_verified_total[5m])) + sum(rate(stella_attestations_failed_total[5m])))",
|
||||
"legendFormat": "Success Rate",
|
||||
"refId": "A"
|
||||
}
|
||||
],
|
||||
"title": "Verification Success Rate",
|
||||
"type": "timeseries"
|
||||
},
|
||||
{
|
||||
"datasource": {
|
||||
"type": "prometheus",
|
||||
"uid": "${DS_PROMETHEUS}"
|
||||
},
|
||||
"fieldConfig": {
|
||||
"defaults": {
|
||||
"color": {
|
||||
"mode": "palette-classic"
|
||||
},
|
||||
"custom": {
|
||||
"axisCenteredZero": false,
|
||||
"axisColorMode": "text",
|
||||
"axisLabel": "",
|
||||
"axisPlacement": "auto",
|
||||
"barAlignment": 0,
|
||||
"drawStyle": "line",
|
||||
"fillOpacity": 20,
|
||||
"gradientMode": "none",
|
||||
"hideFrom": {
|
||||
"tooltip": false,
|
||||
"viz": false,
|
||||
"legend": false
|
||||
},
|
||||
"lineInterpolation": "smooth",
|
||||
"lineWidth": 2,
|
||||
"pointSize": 5,
|
||||
"scaleDistribution": {
|
||||
"type": "linear"
|
||||
},
|
||||
"showPoints": "auto",
|
||||
"spanNulls": false,
|
||||
"stacking": {
|
||||
"group": "A",
|
||||
"mode": "normal"
|
||||
},
|
||||
"thresholdsStyle": {
|
||||
"mode": "line"
|
||||
}
|
||||
},
|
||||
"mappings": [],
|
||||
"thresholds": {
|
||||
"mode": "absolute",
|
||||
"steps": [
|
||||
{
|
||||
"color": "green",
|
||||
"value": null
|
||||
},
|
||||
{
|
||||
"color": "red",
|
||||
"value": 1
|
||||
}
|
||||
]
|
||||
},
|
||||
"unit": "short"
|
||||
},
|
||||
"overrides": []
|
||||
},
|
||||
"gridPos": {
|
||||
"h": 8,
|
||||
"w": 12,
|
||||
"x": 0,
|
||||
"y": 8
|
||||
},
|
||||
"id": 4,
|
||||
"options": {
|
||||
"legend": {
|
||||
"calcs": ["sum"],
|
||||
"displayMode": "table",
|
||||
"placement": "right",
|
||||
"showLegend": true
|
||||
},
|
||||
"tooltip": {
|
||||
"mode": "multi",
|
||||
"sort": "none"
|
||||
}
|
||||
},
|
||||
"targets": [
|
||||
{
|
||||
"datasource": {
|
||||
"type": "prometheus",
|
||||
"uid": "${DS_PROMETHEUS}"
|
||||
},
|
||||
"expr": "sum by (environment, reason) (rate(stella_post_deploy_reversions_total[5m]))",
|
||||
"legendFormat": "{{environment}}: {{reason}}",
|
||||
"refId": "A"
|
||||
}
|
||||
],
|
||||
"title": "Post-Deploy Reversions (Trend to Zero)",
|
||||
"type": "timeseries"
|
||||
},
|
||||
{
|
||||
"datasource": {
|
||||
"type": "prometheus",
|
||||
"uid": "${DS_PROMETHEUS}"
|
||||
},
|
||||
"fieldConfig": {
|
||||
"defaults": {
|
||||
"color": {
|
||||
"mode": "palette-classic"
|
||||
},
|
||||
"custom": {
|
||||
"hideFrom": {
|
||||
"tooltip": false,
|
||||
"viz": false,
|
||||
"legend": false
|
||||
}
|
||||
},
|
||||
"mappings": []
|
||||
},
|
||||
"overrides": []
|
||||
},
|
||||
"gridPos": {
|
||||
"h": 8,
|
||||
"w": 6,
|
||||
"x": 12,
|
||||
"y": 8
|
||||
},
|
||||
"id": 5,
|
||||
"options": {
|
||||
"legend": {
|
||||
"displayMode": "table",
|
||||
"placement": "right",
|
||||
"showLegend": true,
|
||||
"values": ["value"]
|
||||
},
|
||||
"pieType": "pie",
|
||||
"tooltip": {
|
||||
"mode": "single",
|
||||
"sort": "none"
|
||||
}
|
||||
},
|
||||
"targets": [
|
||||
{
|
||||
"datasource": {
|
||||
"type": "prometheus",
|
||||
"uid": "${DS_PROMETHEUS}"
|
||||
},
|
||||
"expr": "sum by (predicate_type) (stella_attestations_created_total)",
|
||||
"legendFormat": "{{predicate_type}}",
|
||||
"refId": "A"
|
||||
}
|
||||
],
|
||||
"title": "Attestations by Type",
|
||||
"type": "piechart"
|
||||
},
|
||||
{
|
||||
"datasource": {
|
||||
"type": "prometheus",
|
||||
"uid": "${DS_PROMETHEUS}"
|
||||
},
|
||||
"fieldConfig": {
|
||||
"defaults": {
|
||||
"color": {
|
||||
"mode": "palette-classic"
|
||||
},
|
||||
"custom": {
|
||||
"axisCenteredZero": false,
|
||||
"axisColorMode": "text",
|
||||
"axisLabel": "",
|
||||
"axisPlacement": "auto",
|
||||
"barAlignment": 0,
|
||||
"drawStyle": "line",
|
||||
"fillOpacity": 20,
|
||||
"gradientMode": "none",
|
||||
"hideFrom": {
|
||||
"tooltip": false,
|
||||
"viz": false,
|
||||
"legend": false
|
||||
},
|
||||
"lineInterpolation": "smooth",
|
||||
"lineWidth": 2,
|
||||
"pointSize": 5,
|
||||
"scaleDistribution": {
|
||||
"type": "linear"
|
||||
},
|
||||
"showPoints": "auto",
|
||||
"spanNulls": false,
|
||||
"stacking": {
|
||||
"group": "A",
|
||||
"mode": "none"
|
||||
},
|
||||
"thresholdsStyle": {
|
||||
"mode": "off"
|
||||
}
|
||||
},
|
||||
"mappings": [],
|
||||
"thresholds": {
|
||||
"mode": "absolute",
|
||||
"steps": [
|
||||
{
|
||||
"color": "green",
|
||||
"value": null
|
||||
},
|
||||
{
|
||||
"color": "red",
|
||||
"value": 80
|
||||
}
|
||||
]
|
||||
},
|
||||
"unit": "short"
|
||||
},
|
||||
"overrides": []
|
||||
},
|
||||
"gridPos": {
|
||||
"h": 8,
|
||||
"w": 6,
|
||||
"x": 18,
|
||||
"y": 8
|
||||
},
|
||||
"id": 6,
|
||||
"options": {
|
||||
"legend": {
|
||||
"calcs": [],
|
||||
"displayMode": "list",
|
||||
"placement": "bottom",
|
||||
"showLegend": true
|
||||
},
|
||||
"tooltip": {
|
||||
"mode": "single",
|
||||
"sort": "none"
|
||||
}
|
||||
},
|
||||
"targets": [
|
||||
{
|
||||
"datasource": {
|
||||
"type": "prometheus",
|
||||
"uid": "${DS_PROMETHEUS}"
|
||||
},
|
||||
"expr": "sum(stella_attestations_failed_total{reason=\"stale_evidence\"})",
|
||||
"legendFormat": "Stale Evidence Alerts",
|
||||
"refId": "A"
|
||||
}
|
||||
],
|
||||
"title": "Stale Evidence Alerts",
|
||||
"type": "timeseries"
|
||||
}
|
||||
],
|
||||
"refresh": "30s",
|
||||
"schemaVersion": 38,
|
||||
"style": "dark",
|
||||
"tags": ["stellaops", "attestations", "security"],
|
||||
"templating": {
|
||||
"list": [
|
||||
{
|
||||
"current": {
|
||||
"selected": false,
|
||||
"text": "Prometheus",
|
||||
"value": "Prometheus"
|
||||
},
|
||||
"hide": 0,
|
||||
"includeAll": false,
|
||||
"label": "Data Source",
|
||||
"multi": false,
|
||||
"name": "DS_PROMETHEUS",
|
||||
"options": [],
|
||||
"query": "prometheus",
|
||||
"refresh": 1,
|
||||
"regex": "",
|
||||
"skipUrlSync": false,
|
||||
"type": "datasource"
|
||||
}
|
||||
]
|
||||
},
|
||||
"time": {
|
||||
"from": "now-6h",
|
||||
"to": "now"
|
||||
},
|
||||
"timepicker": {},
|
||||
"timezone": "",
|
||||
"title": "StellaOps - Attestation Metrics",
|
||||
"uid": "stellaops-attestations",
|
||||
"version": 1,
|
||||
"weekStart": ""
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,6 +0,0 @@
|
||||
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"
|
||||
@@ -1,64 +0,0 @@
|
||||
# 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.
|
||||
@@ -1,16 +0,0 @@
|
||||
# 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`.
|
||||
@@ -1,64 +0,0 @@
|
||||
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]
|
||||
@@ -1,43 +0,0 @@
|
||||
{{- 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 -}}
|
||||
@@ -1,10 +0,0 @@
|
||||
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 }}
|
||||
@@ -1,15 +0,0 @@
|
||||
{{- $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 }}
|
||||
@@ -1,108 +0,0 @@
|
||||
{{- 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 }}
|
||||
@@ -1,225 +0,0 @@
|
||||
{{- $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 }}
|
||||
@@ -1,28 +0,0 @@
|
||||
{{- 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 }}
|
||||
@@ -1,39 +0,0 @@
|
||||
{{- 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 }}
|
||||
@@ -1,32 +0,0 @@
|
||||
{{- 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 }}
|
||||
@@ -1,50 +0,0 @@
|
||||
{{- 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 }}
|
||||
@@ -1,45 +0,0 @@
|
||||
{{- 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 }}
|
||||
@@ -1,22 +0,0 @@
|
||||
{{- 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 }}
|
||||
@@ -1,121 +0,0 @@
|
||||
{{- 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 }}
|
||||
@@ -1,44 +0,0 @@
|
||||
{{- 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 }}
|
||||
@@ -1,22 +0,0 @@
|
||||
{{- 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 }}
|
||||
@@ -1,22 +0,0 @@
|
||||
{{- 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 }}
|
||||
@@ -1,44 +0,0 @@
|
||||
{{- 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 }}
|
||||
@@ -1,314 +0,0 @@
|
||||
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
|
||||
@@ -1,84 +0,0 @@
|
||||
# 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: {}
|
||||
@@ -1,272 +0,0 @@
|
||||
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: {}
|
||||
@@ -1,14 +0,0 @@
|
||||
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
|
||||
@@ -1,58 +0,0 @@
|
||||
# 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
|
||||
@@ -1,59 +0,0 @@
|
||||
# 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
|
||||
@@ -1,289 +0,0 @@
|
||||
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: {}
|
||||
@@ -1,18 +0,0 @@
|
||||
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
|
||||
@@ -1,15 +0,0 @@
|
||||
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
|
||||
@@ -1,209 +0,0 @@
|
||||
# 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
|
||||
@@ -1,339 +0,0 @@
|
||||
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
|
||||
@@ -1,245 +0,0 @@
|
||||
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
|
||||
@@ -1,284 +0,0 @@
|
||||
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
|
||||
@@ -1,561 +0,0 @@
|
||||
-- Partitioning Infrastructure Migration 001: Foundation
|
||||
-- Sprint: SPRINT_3422_0001_0001 - Time-Based Partitioning
|
||||
-- Category: C (infrastructure setup, requires planned maintenance)
|
||||
--
|
||||
-- Purpose: Create partition management infrastructure including:
|
||||
-- - Helper functions for partition creation and maintenance
|
||||
-- - Utility functions for BRIN index optimization
|
||||
-- - Partition maintenance scheduling support
|
||||
--
|
||||
-- This migration creates the foundation; table conversion is done in separate migrations.
|
||||
|
||||
BEGIN;
|
||||
|
||||
-- ============================================================================
|
||||
-- Step 1: Create partition management schema
|
||||
-- ============================================================================
|
||||
|
||||
CREATE SCHEMA IF NOT EXISTS partition_mgmt;
|
||||
|
||||
COMMENT ON SCHEMA partition_mgmt IS
|
||||
'Partition management utilities for time-series tables';
|
||||
|
||||
-- ============================================================================
|
||||
-- Step 2: Managed table registration
|
||||
-- ============================================================================
|
||||
|
||||
CREATE TABLE IF NOT EXISTS partition_mgmt.managed_tables (
|
||||
schema_name TEXT NOT NULL,
|
||||
table_name TEXT NOT NULL,
|
||||
partition_key TEXT NOT NULL,
|
||||
partition_type TEXT NOT NULL,
|
||||
retention_months INT NOT NULL DEFAULT 0,
|
||||
months_ahead INT NOT NULL DEFAULT 3,
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||
PRIMARY KEY (schema_name, table_name)
|
||||
);
|
||||
|
||||
COMMENT ON TABLE partition_mgmt.managed_tables IS
|
||||
'Tracks partitioned tables with retention and creation settings';
|
||||
|
||||
-- ============================================================================
|
||||
-- Step 3: Partition creation function
|
||||
-- ============================================================================
|
||||
|
||||
-- Creates a new partition for a given table and date range
|
||||
CREATE OR REPLACE FUNCTION partition_mgmt.create_partition(
|
||||
p_schema_name TEXT,
|
||||
p_table_name TEXT,
|
||||
p_partition_column TEXT,
|
||||
p_start_date DATE,
|
||||
p_end_date DATE,
|
||||
p_partition_suffix TEXT DEFAULT NULL
|
||||
)
|
||||
RETURNS TEXT
|
||||
LANGUAGE plpgsql
|
||||
AS $$
|
||||
DECLARE
|
||||
v_partition_name TEXT;
|
||||
v_parent_table TEXT;
|
||||
v_sql TEXT;
|
||||
BEGIN
|
||||
v_parent_table := format('%I.%I', p_schema_name, p_table_name);
|
||||
|
||||
-- Generate partition name: tablename_YYYY_MM or tablename_YYYY_Q#
|
||||
IF p_partition_suffix IS NOT NULL THEN
|
||||
v_partition_name := format('%s_%s', p_table_name, p_partition_suffix);
|
||||
ELSE
|
||||
v_partition_name := format('%s_%s', p_table_name, to_char(p_start_date, 'YYYY_MM'));
|
||||
END IF;
|
||||
|
||||
-- Check if partition already exists
|
||||
IF EXISTS (
|
||||
SELECT 1 FROM pg_class c
|
||||
JOIN pg_namespace n ON c.relnamespace = n.oid
|
||||
WHERE n.nspname = p_schema_name AND c.relname = v_partition_name
|
||||
) THEN
|
||||
RAISE NOTICE 'Partition % already exists, skipping', v_partition_name;
|
||||
RETURN v_partition_name;
|
||||
END IF;
|
||||
|
||||
-- Create partition
|
||||
v_sql := format(
|
||||
'CREATE TABLE %I.%I PARTITION OF %s FOR VALUES FROM (%L) TO (%L)',
|
||||
p_schema_name,
|
||||
v_partition_name,
|
||||
v_parent_table,
|
||||
p_start_date,
|
||||
p_end_date
|
||||
);
|
||||
|
||||
EXECUTE v_sql;
|
||||
|
||||
RAISE NOTICE 'Created partition %.%', p_schema_name, v_partition_name;
|
||||
RETURN v_partition_name;
|
||||
END;
|
||||
$$;
|
||||
|
||||
-- ============================================================================
|
||||
-- Step 4: Monthly partition creation helper
|
||||
-- ============================================================================
|
||||
|
||||
CREATE OR REPLACE FUNCTION partition_mgmt.create_monthly_partitions(
|
||||
p_schema_name TEXT,
|
||||
p_table_name TEXT,
|
||||
p_partition_column TEXT,
|
||||
p_start_month DATE,
|
||||
p_months_ahead INT DEFAULT 3
|
||||
)
|
||||
RETURNS SETOF TEXT
|
||||
LANGUAGE plpgsql
|
||||
AS $$
|
||||
DECLARE
|
||||
v_current_month DATE;
|
||||
v_end_month DATE;
|
||||
v_partition_name TEXT;
|
||||
BEGIN
|
||||
v_current_month := date_trunc('month', p_start_month)::DATE;
|
||||
v_end_month := date_trunc('month', NOW() + (p_months_ahead || ' months')::INTERVAL)::DATE;
|
||||
|
||||
WHILE v_current_month <= v_end_month LOOP
|
||||
v_partition_name := partition_mgmt.create_partition(
|
||||
p_schema_name,
|
||||
p_table_name,
|
||||
p_partition_column,
|
||||
v_current_month,
|
||||
(v_current_month + INTERVAL '1 month')::DATE
|
||||
);
|
||||
RETURN NEXT v_partition_name;
|
||||
v_current_month := (v_current_month + INTERVAL '1 month')::DATE;
|
||||
END LOOP;
|
||||
END;
|
||||
$$;
|
||||
|
||||
-- ============================================================================
|
||||
-- Step 5: Quarterly partition creation helper
|
||||
-- ============================================================================
|
||||
|
||||
CREATE OR REPLACE FUNCTION partition_mgmt.create_quarterly_partitions(
|
||||
p_schema_name TEXT,
|
||||
p_table_name TEXT,
|
||||
p_partition_column TEXT,
|
||||
p_start_quarter DATE,
|
||||
p_quarters_ahead INT DEFAULT 2
|
||||
)
|
||||
RETURNS SETOF TEXT
|
||||
LANGUAGE plpgsql
|
||||
AS $$
|
||||
DECLARE
|
||||
v_current_quarter DATE;
|
||||
v_end_quarter DATE;
|
||||
v_partition_name TEXT;
|
||||
v_suffix TEXT;
|
||||
BEGIN
|
||||
v_current_quarter := date_trunc('quarter', p_start_quarter)::DATE;
|
||||
v_end_quarter := date_trunc('quarter', NOW() + (p_quarters_ahead * 3 || ' months')::INTERVAL)::DATE;
|
||||
|
||||
WHILE v_current_quarter <= v_end_quarter LOOP
|
||||
-- Generate suffix like 2025_Q1, 2025_Q2, etc.
|
||||
v_suffix := to_char(v_current_quarter, 'YYYY') || '_Q' ||
|
||||
EXTRACT(QUARTER FROM v_current_quarter)::TEXT;
|
||||
|
||||
v_partition_name := partition_mgmt.create_partition(
|
||||
p_schema_name,
|
||||
p_table_name,
|
||||
p_partition_column,
|
||||
v_current_quarter,
|
||||
(v_current_quarter + INTERVAL '3 months')::DATE,
|
||||
v_suffix
|
||||
);
|
||||
RETURN NEXT v_partition_name;
|
||||
v_current_quarter := (v_current_quarter + INTERVAL '3 months')::DATE;
|
||||
END LOOP;
|
||||
END;
|
||||
$$;
|
||||
|
||||
-- ============================================================================
|
||||
-- Step 6: Ensure future partitions exist
|
||||
-- ============================================================================
|
||||
|
||||
CREATE OR REPLACE FUNCTION partition_mgmt.ensure_future_partitions(
|
||||
p_schema_name TEXT,
|
||||
p_table_name TEXT,
|
||||
p_months_ahead INT
|
||||
)
|
||||
RETURNS INT
|
||||
LANGUAGE plpgsql
|
||||
AS $$
|
||||
DECLARE
|
||||
v_partition_key TEXT;
|
||||
v_partition_type TEXT;
|
||||
v_months_ahead INT;
|
||||
v_created INT := 0;
|
||||
v_current DATE;
|
||||
v_end DATE;
|
||||
v_suffix TEXT;
|
||||
v_partition_name TEXT;
|
||||
BEGIN
|
||||
SELECT partition_key, partition_type, months_ahead
|
||||
INTO v_partition_key, v_partition_type, v_months_ahead
|
||||
FROM partition_mgmt.managed_tables
|
||||
WHERE schema_name = p_schema_name
|
||||
AND table_name = p_table_name;
|
||||
|
||||
IF v_partition_key IS NULL THEN
|
||||
RETURN 0;
|
||||
END IF;
|
||||
|
||||
IF p_months_ahead IS NOT NULL AND p_months_ahead > 0 THEN
|
||||
v_months_ahead := p_months_ahead;
|
||||
END IF;
|
||||
|
||||
IF v_months_ahead IS NULL OR v_months_ahead <= 0 THEN
|
||||
RETURN 0;
|
||||
END IF;
|
||||
|
||||
v_partition_type := lower(coalesce(v_partition_type, 'monthly'));
|
||||
|
||||
IF v_partition_type = 'monthly' THEN
|
||||
v_current := date_trunc('month', NOW())::DATE;
|
||||
v_end := date_trunc('month', NOW() + (v_months_ahead || ' months')::INTERVAL)::DATE;
|
||||
|
||||
WHILE v_current <= v_end LOOP
|
||||
v_partition_name := format('%s_%s', p_table_name, to_char(v_current, 'YYYY_MM'));
|
||||
IF NOT EXISTS (
|
||||
SELECT 1 FROM pg_class c
|
||||
JOIN pg_namespace n ON c.relnamespace = n.oid
|
||||
WHERE n.nspname = p_schema_name AND c.relname = v_partition_name
|
||||
) THEN
|
||||
PERFORM partition_mgmt.create_partition(
|
||||
p_schema_name,
|
||||
p_table_name,
|
||||
v_partition_key,
|
||||
v_current,
|
||||
(v_current + INTERVAL '1 month')::DATE
|
||||
);
|
||||
v_created := v_created + 1;
|
||||
END IF;
|
||||
|
||||
v_current := (v_current + INTERVAL '1 month')::DATE;
|
||||
END LOOP;
|
||||
ELSIF v_partition_type = 'quarterly' THEN
|
||||
v_current := date_trunc('quarter', NOW())::DATE;
|
||||
v_end := date_trunc('quarter', NOW() + (v_months_ahead || ' months')::INTERVAL)::DATE;
|
||||
|
||||
WHILE v_current <= v_end LOOP
|
||||
v_suffix := to_char(v_current, 'YYYY') || '_Q' ||
|
||||
EXTRACT(QUARTER FROM v_current)::TEXT;
|
||||
v_partition_name := format('%s_%s', p_table_name, v_suffix);
|
||||
|
||||
IF NOT EXISTS (
|
||||
SELECT 1 FROM pg_class c
|
||||
JOIN pg_namespace n ON c.relnamespace = n.oid
|
||||
WHERE n.nspname = p_schema_name AND c.relname = v_partition_name
|
||||
) THEN
|
||||
PERFORM partition_mgmt.create_partition(
|
||||
p_schema_name,
|
||||
p_table_name,
|
||||
v_partition_key,
|
||||
v_current,
|
||||
(v_current + INTERVAL '3 months')::DATE,
|
||||
v_suffix
|
||||
);
|
||||
v_created := v_created + 1;
|
||||
END IF;
|
||||
|
||||
v_current := (v_current + INTERVAL '3 months')::DATE;
|
||||
END LOOP;
|
||||
END IF;
|
||||
|
||||
RETURN v_created;
|
||||
END;
|
||||
$$;
|
||||
|
||||
-- ============================================================================
|
||||
-- Step 7: Retention enforcement function
|
||||
-- ============================================================================
|
||||
|
||||
CREATE OR REPLACE FUNCTION partition_mgmt.enforce_retention(
|
||||
p_schema_name TEXT,
|
||||
p_table_name TEXT,
|
||||
p_retention_months INT
|
||||
)
|
||||
RETURNS INT
|
||||
LANGUAGE plpgsql
|
||||
AS $$
|
||||
DECLARE
|
||||
v_retention_months INT;
|
||||
v_cutoff_date DATE;
|
||||
v_partition RECORD;
|
||||
v_dropped INT := 0;
|
||||
BEGIN
|
||||
SELECT retention_months
|
||||
INTO v_retention_months
|
||||
FROM partition_mgmt.managed_tables
|
||||
WHERE schema_name = p_schema_name
|
||||
AND table_name = p_table_name;
|
||||
|
||||
IF p_retention_months IS NOT NULL AND p_retention_months > 0 THEN
|
||||
v_retention_months := p_retention_months;
|
||||
END IF;
|
||||
|
||||
IF v_retention_months IS NULL OR v_retention_months <= 0 THEN
|
||||
RETURN 0;
|
||||
END IF;
|
||||
|
||||
v_cutoff_date := (NOW() - (v_retention_months || ' months')::INTERVAL)::DATE;
|
||||
|
||||
FOR v_partition IN
|
||||
SELECT partition_name, partition_end
|
||||
FROM partition_mgmt.partition_stats
|
||||
WHERE schema_name = p_schema_name
|
||||
AND table_name = p_table_name
|
||||
LOOP
|
||||
IF v_partition.partition_end IS NOT NULL AND v_partition.partition_end < v_cutoff_date THEN
|
||||
EXECUTE format('DROP TABLE IF EXISTS %I.%I', p_schema_name, v_partition.partition_name);
|
||||
v_dropped := v_dropped + 1;
|
||||
END IF;
|
||||
END LOOP;
|
||||
|
||||
RETURN v_dropped;
|
||||
END;
|
||||
$$;
|
||||
|
||||
-- ============================================================================
|
||||
-- Step 8: Partition detach and archive function
|
||||
-- ============================================================================
|
||||
|
||||
CREATE OR REPLACE FUNCTION partition_mgmt.detach_partition(
|
||||
p_schema_name TEXT,
|
||||
p_table_name TEXT,
|
||||
p_partition_name TEXT,
|
||||
p_archive_schema TEXT DEFAULT 'archive'
|
||||
)
|
||||
RETURNS BOOLEAN
|
||||
LANGUAGE plpgsql
|
||||
AS $$
|
||||
DECLARE
|
||||
v_parent_table TEXT;
|
||||
v_partition_full TEXT;
|
||||
v_archive_table TEXT;
|
||||
BEGIN
|
||||
v_parent_table := format('%I.%I', p_schema_name, p_table_name);
|
||||
v_partition_full := format('%I.%I', p_schema_name, p_partition_name);
|
||||
v_archive_table := format('%I.%I', p_archive_schema, p_partition_name);
|
||||
|
||||
-- Create archive schema if not exists
|
||||
EXECUTE format('CREATE SCHEMA IF NOT EXISTS %I', p_archive_schema);
|
||||
|
||||
-- Detach partition
|
||||
EXECUTE format(
|
||||
'ALTER TABLE %s DETACH PARTITION %s',
|
||||
v_parent_table,
|
||||
v_partition_full
|
||||
);
|
||||
|
||||
-- Move to archive schema
|
||||
EXECUTE format(
|
||||
'ALTER TABLE %s SET SCHEMA %I',
|
||||
v_partition_full,
|
||||
p_archive_schema
|
||||
);
|
||||
|
||||
RAISE NOTICE 'Detached and archived partition % to %', p_partition_name, v_archive_table;
|
||||
RETURN TRUE;
|
||||
EXCEPTION
|
||||
WHEN OTHERS THEN
|
||||
RAISE WARNING 'Failed to detach partition %: %', p_partition_name, SQLERRM;
|
||||
RETURN FALSE;
|
||||
END;
|
||||
$$;
|
||||
|
||||
-- ============================================================================
|
||||
-- Step 9: Partition retention cleanup function
|
||||
-- ============================================================================
|
||||
|
||||
CREATE OR REPLACE FUNCTION partition_mgmt.cleanup_old_partitions(
|
||||
p_schema_name TEXT,
|
||||
p_table_name TEXT,
|
||||
p_retention_months INT,
|
||||
p_archive_schema TEXT DEFAULT 'archive',
|
||||
p_dry_run BOOLEAN DEFAULT TRUE
|
||||
)
|
||||
RETURNS TABLE(partition_name TEXT, action TEXT)
|
||||
LANGUAGE plpgsql
|
||||
AS $$
|
||||
DECLARE
|
||||
v_cutoff_date DATE;
|
||||
v_partition RECORD;
|
||||
v_partition_end DATE;
|
||||
BEGIN
|
||||
v_cutoff_date := (NOW() - (p_retention_months || ' months')::INTERVAL)::DATE;
|
||||
|
||||
FOR v_partition IN
|
||||
SELECT c.relname as name,
|
||||
pg_get_expr(c.relpartbound, c.oid) as bound_expr
|
||||
FROM pg_class c
|
||||
JOIN pg_namespace n ON c.relnamespace = n.oid
|
||||
JOIN pg_inherits i ON c.oid = i.inhrelid
|
||||
JOIN pg_class parent ON i.inhparent = parent.oid
|
||||
WHERE n.nspname = p_schema_name
|
||||
AND parent.relname = p_table_name
|
||||
AND c.relkind = 'r'
|
||||
LOOP
|
||||
-- Parse the partition bound to get end date
|
||||
-- Format: FOR VALUES FROM ('2024-01-01') TO ('2024-02-01')
|
||||
v_partition_end := (regexp_match(v_partition.bound_expr,
|
||||
'TO \(''([^'']+)''\)'))[1]::DATE;
|
||||
|
||||
IF v_partition_end IS NOT NULL AND v_partition_end < v_cutoff_date THEN
|
||||
partition_name := v_partition.name;
|
||||
|
||||
IF p_dry_run THEN
|
||||
action := 'WOULD_ARCHIVE';
|
||||
ELSE
|
||||
IF partition_mgmt.detach_partition(
|
||||
p_schema_name, p_table_name, v_partition.name, p_archive_schema
|
||||
) THEN
|
||||
action := 'ARCHIVED';
|
||||
ELSE
|
||||
action := 'FAILED';
|
||||
END IF;
|
||||
END IF;
|
||||
|
||||
RETURN NEXT;
|
||||
END IF;
|
||||
END LOOP;
|
||||
END;
|
||||
$$;
|
||||
|
||||
-- ============================================================================
|
||||
-- Step 10: Partition statistics view
|
||||
-- ============================================================================
|
||||
|
||||
CREATE OR REPLACE VIEW partition_mgmt.partition_stats AS
|
||||
SELECT
|
||||
n.nspname AS schema_name,
|
||||
parent.relname AS table_name,
|
||||
c.relname AS partition_name,
|
||||
pg_get_expr(c.relpartbound, c.oid) AS partition_range,
|
||||
(regexp_match(pg_get_expr(c.relpartbound, c.oid), 'FROM \(''([^'']+)''\)'))[1]::DATE AS partition_start,
|
||||
(regexp_match(pg_get_expr(c.relpartbound, c.oid), 'TO \(''([^'']+)''\)'))[1]::DATE AS partition_end,
|
||||
pg_size_pretty(pg_relation_size(c.oid)) AS size,
|
||||
pg_relation_size(c.oid) AS size_bytes,
|
||||
COALESCE(s.n_live_tup, 0) AS estimated_rows,
|
||||
s.last_vacuum,
|
||||
s.last_autovacuum,
|
||||
s.last_analyze,
|
||||
s.last_autoanalyze
|
||||
FROM pg_class c
|
||||
JOIN pg_namespace n ON c.relnamespace = n.oid
|
||||
JOIN pg_inherits i ON c.oid = i.inhrelid
|
||||
JOIN pg_class parent ON i.inhparent = parent.oid
|
||||
LEFT JOIN pg_stat_user_tables s ON c.oid = s.relid
|
||||
WHERE c.relkind = 'r'
|
||||
AND parent.relkind = 'p'
|
||||
ORDER BY n.nspname, parent.relname, c.relname;
|
||||
|
||||
COMMENT ON VIEW partition_mgmt.partition_stats IS
|
||||
'Statistics for all partitioned tables in the database';
|
||||
|
||||
-- ============================================================================
|
||||
-- Step 11: BRIN index optimization helper
|
||||
-- ============================================================================
|
||||
|
||||
CREATE OR REPLACE FUNCTION partition_mgmt.create_brin_index_if_not_exists(
|
||||
p_schema_name TEXT,
|
||||
p_table_name TEXT,
|
||||
p_column_name TEXT,
|
||||
p_pages_per_range INT DEFAULT 128
|
||||
)
|
||||
RETURNS BOOLEAN
|
||||
LANGUAGE plpgsql
|
||||
AS $$
|
||||
DECLARE
|
||||
v_index_name TEXT;
|
||||
v_sql TEXT;
|
||||
BEGIN
|
||||
v_index_name := format('brin_%s_%s', p_table_name, p_column_name);
|
||||
|
||||
-- Check if index exists
|
||||
IF EXISTS (
|
||||
SELECT 1 FROM pg_indexes
|
||||
WHERE schemaname = p_schema_name AND indexname = v_index_name
|
||||
) THEN
|
||||
RAISE NOTICE 'BRIN index % already exists', v_index_name;
|
||||
RETURN FALSE;
|
||||
END IF;
|
||||
|
||||
v_sql := format(
|
||||
'CREATE INDEX %I ON %I.%I USING brin (%I) WITH (pages_per_range = %s)',
|
||||
v_index_name,
|
||||
p_schema_name,
|
||||
p_table_name,
|
||||
p_column_name,
|
||||
p_pages_per_range
|
||||
);
|
||||
|
||||
EXECUTE v_sql;
|
||||
|
||||
RAISE NOTICE 'Created BRIN index % on %.%(%)',
|
||||
v_index_name, p_schema_name, p_table_name, p_column_name;
|
||||
RETURN TRUE;
|
||||
END;
|
||||
$$;
|
||||
|
||||
-- ============================================================================
|
||||
-- Step 12: Maintenance job tracking table
|
||||
-- ============================================================================
|
||||
|
||||
CREATE TABLE IF NOT EXISTS partition_mgmt.maintenance_log (
|
||||
id BIGSERIAL PRIMARY KEY,
|
||||
operation TEXT NOT NULL,
|
||||
schema_name TEXT NOT NULL,
|
||||
table_name TEXT NOT NULL,
|
||||
partition_name TEXT,
|
||||
status TEXT NOT NULL DEFAULT 'started',
|
||||
details JSONB NOT NULL DEFAULT '{}',
|
||||
started_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||
completed_at TIMESTAMPTZ,
|
||||
error_message TEXT
|
||||
);
|
||||
|
||||
CREATE INDEX idx_maintenance_log_table ON partition_mgmt.maintenance_log(schema_name, table_name);
|
||||
CREATE INDEX idx_maintenance_log_status ON partition_mgmt.maintenance_log(status, started_at);
|
||||
|
||||
-- ============================================================================
|
||||
-- Step 13: Archive schema for detached partitions
|
||||
-- ============================================================================
|
||||
|
||||
CREATE SCHEMA IF NOT EXISTS archive;
|
||||
|
||||
COMMENT ON SCHEMA archive IS
|
||||
'Storage for detached/archived partitions awaiting deletion or offload';
|
||||
|
||||
COMMIT;
|
||||
|
||||
-- ============================================================================
|
||||
-- Usage Examples (commented out)
|
||||
-- ============================================================================
|
||||
|
||||
/*
|
||||
-- Create monthly partitions for audit table, 3 months ahead
|
||||
SELECT partition_mgmt.create_monthly_partitions(
|
||||
'scheduler', 'audit', 'created_at', '2024-01-01'::DATE, 3
|
||||
);
|
||||
|
||||
-- Preview old partitions that would be archived (dry run)
|
||||
SELECT * FROM partition_mgmt.cleanup_old_partitions(
|
||||
'scheduler', 'audit', 12, 'archive', TRUE
|
||||
);
|
||||
|
||||
-- Actually archive old partitions
|
||||
SELECT * FROM partition_mgmt.cleanup_old_partitions(
|
||||
'scheduler', 'audit', 12, 'archive', FALSE
|
||||
);
|
||||
|
||||
-- View partition statistics
|
||||
SELECT * FROM partition_mgmt.partition_stats
|
||||
WHERE schema_name = 'scheduler'
|
||||
ORDER BY table_name, partition_name;
|
||||
*/
|
||||
@@ -1,143 +0,0 @@
|
||||
-- Migration: Trust Vector Calibration Schema
|
||||
-- Sprint: 7100.0002.0002
|
||||
-- Description: Creates schema and tables for trust vector calibration system
|
||||
|
||||
-- Create calibration schema
|
||||
CREATE SCHEMA IF NOT EXISTS excititor_calibration;
|
||||
|
||||
-- Calibration manifests table
|
||||
-- Stores signed manifests for each calibration epoch
|
||||
CREATE TABLE IF NOT EXISTS excititor_calibration.calibration_manifests (
|
||||
manifest_id TEXT PRIMARY KEY,
|
||||
tenant_id TEXT NOT NULL,
|
||||
epoch_number INTEGER NOT NULL,
|
||||
epoch_start_utc TIMESTAMP NOT NULL,
|
||||
epoch_end_utc TIMESTAMP NOT NULL,
|
||||
sample_count INTEGER NOT NULL,
|
||||
learning_rate DOUBLE PRECISION NOT NULL,
|
||||
policy_hash TEXT,
|
||||
lattice_version TEXT NOT NULL,
|
||||
manifest_json JSONB NOT NULL,
|
||||
signature_envelope JSONB,
|
||||
created_at_utc TIMESTAMP NOT NULL DEFAULT (NOW() AT TIME ZONE 'UTC'),
|
||||
created_by TEXT NOT NULL,
|
||||
|
||||
CONSTRAINT uq_calibration_manifest_tenant_epoch UNIQUE (tenant_id, epoch_number)
|
||||
);
|
||||
|
||||
CREATE INDEX idx_calibration_manifests_tenant
|
||||
ON excititor_calibration.calibration_manifests(tenant_id);
|
||||
CREATE INDEX idx_calibration_manifests_created
|
||||
ON excititor_calibration.calibration_manifests(created_at_utc DESC);
|
||||
|
||||
-- Trust vector adjustments table
|
||||
-- Records each provider's trust vector changes per epoch
|
||||
CREATE TABLE IF NOT EXISTS excititor_calibration.trust_vector_adjustments (
|
||||
adjustment_id BIGSERIAL PRIMARY KEY,
|
||||
manifest_id TEXT NOT NULL REFERENCES excititor_calibration.calibration_manifests(manifest_id),
|
||||
source_id TEXT NOT NULL,
|
||||
old_provenance DOUBLE PRECISION NOT NULL,
|
||||
old_coverage DOUBLE PRECISION NOT NULL,
|
||||
old_replayability DOUBLE PRECISION NOT NULL,
|
||||
new_provenance DOUBLE PRECISION NOT NULL,
|
||||
new_coverage DOUBLE PRECISION NOT NULL,
|
||||
new_replayability DOUBLE PRECISION NOT NULL,
|
||||
adjustment_magnitude DOUBLE PRECISION NOT NULL,
|
||||
confidence_in_adjustment DOUBLE PRECISION NOT NULL,
|
||||
sample_count_for_source INTEGER NOT NULL,
|
||||
created_at_utc TIMESTAMP NOT NULL DEFAULT (NOW() AT TIME ZONE 'UTC'),
|
||||
|
||||
CONSTRAINT chk_old_provenance_range CHECK (old_provenance >= 0 AND old_provenance <= 1),
|
||||
CONSTRAINT chk_old_coverage_range CHECK (old_coverage >= 0 AND old_coverage <= 1),
|
||||
CONSTRAINT chk_old_replayability_range CHECK (old_replayability >= 0 AND old_replayability <= 1),
|
||||
CONSTRAINT chk_new_provenance_range CHECK (new_provenance >= 0 AND new_provenance <= 1),
|
||||
CONSTRAINT chk_new_coverage_range CHECK (new_coverage >= 0 AND new_coverage <= 1),
|
||||
CONSTRAINT chk_new_replayability_range CHECK (new_replayability >= 0 AND new_replayability <= 1),
|
||||
CONSTRAINT chk_confidence_range CHECK (confidence_in_adjustment >= 0 AND confidence_in_adjustment <= 1)
|
||||
);
|
||||
|
||||
CREATE INDEX idx_trust_adjustments_manifest
|
||||
ON excititor_calibration.trust_vector_adjustments(manifest_id);
|
||||
CREATE INDEX idx_trust_adjustments_source
|
||||
ON excititor_calibration.trust_vector_adjustments(source_id);
|
||||
|
||||
-- Calibration feedback samples table
|
||||
-- Stores empirical evidence used for calibration
|
||||
CREATE TABLE IF NOT EXISTS excititor_calibration.calibration_samples (
|
||||
sample_id BIGSERIAL PRIMARY KEY,
|
||||
tenant_id TEXT NOT NULL,
|
||||
source_id TEXT NOT NULL,
|
||||
cve_id TEXT NOT NULL,
|
||||
purl TEXT NOT NULL,
|
||||
expected_status TEXT NOT NULL,
|
||||
actual_status TEXT NOT NULL,
|
||||
verdict_confidence DOUBLE PRECISION NOT NULL,
|
||||
is_match BOOLEAN NOT NULL,
|
||||
feedback_source TEXT NOT NULL, -- 'reachability', 'customer_feedback', 'integration_tests'
|
||||
feedback_weight DOUBLE PRECISION NOT NULL DEFAULT 1.0,
|
||||
scan_id TEXT,
|
||||
collected_at_utc TIMESTAMP NOT NULL DEFAULT (NOW() AT TIME ZONE 'UTC'),
|
||||
processed BOOLEAN NOT NULL DEFAULT FALSE,
|
||||
processed_in_manifest_id TEXT REFERENCES excititor_calibration.calibration_manifests(manifest_id),
|
||||
|
||||
CONSTRAINT chk_verdict_confidence_range CHECK (verdict_confidence >= 0 AND verdict_confidence <= 1),
|
||||
CONSTRAINT chk_feedback_weight_range CHECK (feedback_weight >= 0 AND feedback_weight <= 1)
|
||||
);
|
||||
|
||||
CREATE INDEX idx_calibration_samples_tenant
|
||||
ON excititor_calibration.calibration_samples(tenant_id);
|
||||
CREATE INDEX idx_calibration_samples_source
|
||||
ON excititor_calibration.calibration_samples(source_id);
|
||||
CREATE INDEX idx_calibration_samples_collected
|
||||
ON excititor_calibration.calibration_samples(collected_at_utc DESC);
|
||||
CREATE INDEX idx_calibration_samples_processed
|
||||
ON excititor_calibration.calibration_samples(processed) WHERE NOT processed;
|
||||
|
||||
-- Calibration metrics table
|
||||
-- Tracks performance metrics per source/severity/status
|
||||
CREATE TABLE IF NOT EXISTS excititor_calibration.calibration_metrics (
|
||||
metric_id BIGSERIAL PRIMARY KEY,
|
||||
manifest_id TEXT NOT NULL REFERENCES excititor_calibration.calibration_manifests(manifest_id),
|
||||
source_id TEXT,
|
||||
severity TEXT,
|
||||
status TEXT,
|
||||
precision DOUBLE PRECISION NOT NULL,
|
||||
recall DOUBLE PRECISION NOT NULL,
|
||||
f1_score DOUBLE PRECISION NOT NULL,
|
||||
false_positive_rate DOUBLE PRECISION NOT NULL,
|
||||
false_negative_rate DOUBLE PRECISION NOT NULL,
|
||||
sample_count INTEGER NOT NULL,
|
||||
created_at_utc TIMESTAMP NOT NULL DEFAULT (NOW() AT TIME ZONE 'UTC'),
|
||||
|
||||
CONSTRAINT chk_precision_range CHECK (precision >= 0 AND precision <= 1),
|
||||
CONSTRAINT chk_recall_range CHECK (recall >= 0 AND recall <= 1),
|
||||
CONSTRAINT chk_f1_range CHECK (f1_score >= 0 AND f1_score <= 1),
|
||||
CONSTRAINT chk_fpr_range CHECK (false_positive_rate >= 0 AND false_positive_rate <= 1),
|
||||
CONSTRAINT chk_fnr_range CHECK (false_negative_rate >= 0 AND false_negative_rate <= 1)
|
||||
);
|
||||
|
||||
CREATE INDEX idx_calibration_metrics_manifest
|
||||
ON excititor_calibration.calibration_metrics(manifest_id);
|
||||
CREATE INDEX idx_calibration_metrics_source
|
||||
ON excititor_calibration.calibration_metrics(source_id) WHERE source_id IS NOT NULL;
|
||||
|
||||
-- Grant permissions to excititor service role
|
||||
DO $$
|
||||
BEGIN
|
||||
IF EXISTS (SELECT 1 FROM pg_roles WHERE rolname = 'excititor_service') THEN
|
||||
GRANT USAGE ON SCHEMA excititor_calibration TO excititor_service;
|
||||
GRANT SELECT, INSERT, UPDATE, DELETE ON ALL TABLES IN SCHEMA excititor_calibration TO excititor_service;
|
||||
GRANT USAGE, SELECT ON ALL SEQUENCES IN SCHEMA excititor_calibration TO excititor_service;
|
||||
ALTER DEFAULT PRIVILEGES IN SCHEMA excititor_calibration
|
||||
GRANT SELECT, INSERT, UPDATE, DELETE ON TABLES TO excititor_service;
|
||||
ALTER DEFAULT PRIVILEGES IN SCHEMA excititor_calibration
|
||||
GRANT USAGE, SELECT ON SEQUENCES TO excititor_service;
|
||||
END IF;
|
||||
END $$;
|
||||
|
||||
-- Comments for documentation
|
||||
COMMENT ON SCHEMA excititor_calibration IS 'Trust vector calibration data for VEX source scoring';
|
||||
COMMENT ON TABLE excititor_calibration.calibration_manifests IS 'Signed calibration epoch results';
|
||||
COMMENT ON TABLE excititor_calibration.trust_vector_adjustments IS 'Per-source trust vector changes per epoch';
|
||||
COMMENT ON TABLE excititor_calibration.calibration_samples IS 'Empirical feedback samples for calibration';
|
||||
COMMENT ON TABLE excititor_calibration.calibration_metrics IS 'Performance metrics per calibration epoch';
|
||||
@@ -1,97 +0,0 @@
|
||||
-- Provcache schema migration
|
||||
-- Run as: psql -d stellaops -f create_provcache_schema.sql
|
||||
|
||||
-- Create schema
|
||||
CREATE SCHEMA IF NOT EXISTS provcache;
|
||||
|
||||
-- Main cache items table
|
||||
CREATE TABLE IF NOT EXISTS provcache.provcache_items (
|
||||
verikey TEXT PRIMARY KEY,
|
||||
digest_version TEXT NOT NULL DEFAULT 'v1',
|
||||
verdict_hash TEXT NOT NULL,
|
||||
proof_root TEXT NOT NULL,
|
||||
replay_seed JSONB NOT NULL,
|
||||
policy_hash TEXT NOT NULL,
|
||||
signer_set_hash TEXT NOT NULL,
|
||||
feed_epoch TEXT NOT NULL,
|
||||
trust_score INTEGER NOT NULL CHECK (trust_score >= 0 AND trust_score <= 100),
|
||||
hit_count BIGINT NOT NULL DEFAULT 0,
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||
expires_at TIMESTAMPTZ NOT NULL,
|
||||
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||
last_accessed_at TIMESTAMPTZ,
|
||||
|
||||
-- Constraint: expires_at must be after created_at
|
||||
CONSTRAINT provcache_items_expires_check CHECK (expires_at > created_at)
|
||||
);
|
||||
|
||||
-- Indexes for invalidation queries
|
||||
CREATE INDEX IF NOT EXISTS idx_provcache_policy_hash
|
||||
ON provcache.provcache_items(policy_hash);
|
||||
CREATE INDEX IF NOT EXISTS idx_provcache_signer_set_hash
|
||||
ON provcache.provcache_items(signer_set_hash);
|
||||
CREATE INDEX IF NOT EXISTS idx_provcache_feed_epoch
|
||||
ON provcache.provcache_items(feed_epoch);
|
||||
CREATE INDEX IF NOT EXISTS idx_provcache_expires_at
|
||||
ON provcache.provcache_items(expires_at);
|
||||
CREATE INDEX IF NOT EXISTS idx_provcache_created_at
|
||||
ON provcache.provcache_items(created_at);
|
||||
|
||||
-- Evidence chunks table for large evidence storage
|
||||
CREATE TABLE IF NOT EXISTS provcache.prov_evidence_chunks (
|
||||
chunk_id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
proof_root TEXT NOT NULL,
|
||||
chunk_index INTEGER NOT NULL,
|
||||
chunk_hash TEXT NOT NULL,
|
||||
blob BYTEA NOT NULL,
|
||||
blob_size INTEGER NOT NULL,
|
||||
content_type TEXT NOT NULL,
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||
|
||||
CONSTRAINT prov_evidence_chunks_unique_index
|
||||
UNIQUE (proof_root, chunk_index)
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_prov_chunks_proof_root
|
||||
ON provcache.prov_evidence_chunks(proof_root);
|
||||
|
||||
-- Revocation audit log
|
||||
CREATE TABLE IF NOT EXISTS provcache.prov_revocations (
|
||||
revocation_id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
revocation_type TEXT NOT NULL,
|
||||
target_hash TEXT NOT NULL,
|
||||
reason TEXT,
|
||||
actor TEXT,
|
||||
entries_affected BIGINT NOT NULL,
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_prov_revocations_created_at
|
||||
ON provcache.prov_revocations(created_at);
|
||||
CREATE INDEX IF NOT EXISTS idx_prov_revocations_target_hash
|
||||
ON provcache.prov_revocations(target_hash);
|
||||
|
||||
-- Function to update updated_at timestamp
|
||||
CREATE OR REPLACE FUNCTION provcache.update_updated_at_column()
|
||||
RETURNS TRIGGER AS $$
|
||||
BEGIN
|
||||
NEW.updated_at = NOW();
|
||||
RETURN NEW;
|
||||
END;
|
||||
$$ language 'plpgsql';
|
||||
|
||||
-- Trigger for auto-updating updated_at
|
||||
DROP TRIGGER IF EXISTS update_provcache_items_updated_at ON provcache.provcache_items;
|
||||
CREATE TRIGGER update_provcache_items_updated_at
|
||||
BEFORE UPDATE ON provcache.provcache_items
|
||||
FOR EACH ROW
|
||||
EXECUTE FUNCTION provcache.update_updated_at_column();
|
||||
|
||||
-- Grant permissions (adjust role as needed)
|
||||
-- GRANT USAGE ON SCHEMA provcache TO stellaops_app;
|
||||
-- GRANT SELECT, INSERT, UPDATE, DELETE ON ALL TABLES IN SCHEMA provcache TO stellaops_app;
|
||||
-- GRANT USAGE ON ALL SEQUENCES IN SCHEMA provcache TO stellaops_app;
|
||||
|
||||
COMMENT ON TABLE provcache.provcache_items IS 'Provenance cache entries for cached security decisions';
|
||||
COMMENT ON TABLE provcache.prov_evidence_chunks IS 'Chunked evidence storage for large SBOMs and attestations';
|
||||
COMMENT ON TABLE provcache.prov_revocations IS 'Audit log of cache invalidation events';
|
||||
@@ -1,159 +0,0 @@
|
||||
-- RLS Validation Script
|
||||
-- Sprint: SPRINT_3421_0001_0001 - RLS Expansion
|
||||
--
|
||||
-- Purpose: Verify that RLS is properly configured on all tenant-scoped tables
|
||||
-- Run this script after deploying RLS migrations to validate configuration
|
||||
|
||||
-- ============================================================================
|
||||
-- Part 1: List all tables with RLS status
|
||||
-- ============================================================================
|
||||
|
||||
\echo '=== RLS Status for All Schemas ==='
|
||||
|
||||
SELECT
|
||||
schemaname AS schema,
|
||||
tablename AS table_name,
|
||||
rowsecurity AS rls_enabled,
|
||||
forcerowsecurity AS rls_forced,
|
||||
CASE
|
||||
WHEN rowsecurity AND forcerowsecurity THEN 'OK'
|
||||
WHEN rowsecurity AND NOT forcerowsecurity THEN 'WARN: Not forced'
|
||||
ELSE 'MISSING'
|
||||
END AS status
|
||||
FROM pg_tables
|
||||
WHERE schemaname IN ('scheduler', 'notify', 'authority', 'vex', 'policy', 'unknowns')
|
||||
ORDER BY schemaname, tablename;
|
||||
|
||||
-- ============================================================================
|
||||
-- Part 2: List all RLS policies
|
||||
-- ============================================================================
|
||||
|
||||
\echo ''
|
||||
\echo '=== RLS Policies ==='
|
||||
|
||||
SELECT
|
||||
schemaname AS schema,
|
||||
tablename AS table_name,
|
||||
policyname AS policy_name,
|
||||
permissive,
|
||||
roles,
|
||||
cmd AS applies_to,
|
||||
qual IS NOT NULL AS has_using,
|
||||
with_check IS NOT NULL AS has_check
|
||||
FROM pg_policies
|
||||
WHERE schemaname IN ('scheduler', 'notify', 'authority', 'vex', 'policy', 'unknowns')
|
||||
ORDER BY schemaname, tablename, policyname;
|
||||
|
||||
-- ============================================================================
|
||||
-- Part 3: Tables missing RLS that should have it (have tenant_id column)
|
||||
-- ============================================================================
|
||||
|
||||
\echo ''
|
||||
\echo '=== Tables with tenant_id but NO RLS ==='
|
||||
|
||||
SELECT
|
||||
c.table_schema AS schema,
|
||||
c.table_name AS table_name,
|
||||
'MISSING RLS' AS issue
|
||||
FROM information_schema.columns c
|
||||
JOIN pg_tables t ON c.table_schema = t.schemaname AND c.table_name = t.tablename
|
||||
WHERE c.column_name IN ('tenant_id', 'tenant')
|
||||
AND c.table_schema IN ('scheduler', 'notify', 'authority', 'vex', 'policy', 'unknowns')
|
||||
AND NOT t.rowsecurity
|
||||
ORDER BY c.table_schema, c.table_name;
|
||||
|
||||
-- ============================================================================
|
||||
-- Part 4: Verify helper functions exist
|
||||
-- ============================================================================
|
||||
|
||||
\echo ''
|
||||
\echo '=== RLS Helper Functions ==='
|
||||
|
||||
SELECT
|
||||
n.nspname AS schema,
|
||||
p.proname AS function_name,
|
||||
CASE
|
||||
WHEN p.prosecdef THEN 'SECURITY DEFINER'
|
||||
ELSE 'SECURITY INVOKER'
|
||||
END AS security,
|
||||
CASE
|
||||
WHEN p.provolatile = 's' THEN 'STABLE'
|
||||
WHEN p.provolatile = 'i' THEN 'IMMUTABLE'
|
||||
ELSE 'VOLATILE'
|
||||
END AS volatility
|
||||
FROM pg_proc p
|
||||
JOIN pg_namespace n ON p.pronamespace = n.oid
|
||||
WHERE p.proname = 'require_current_tenant'
|
||||
AND n.nspname LIKE '%_app'
|
||||
ORDER BY n.nspname;
|
||||
|
||||
-- ============================================================================
|
||||
-- Part 5: Test RLS enforcement (expect failure without tenant context)
|
||||
-- ============================================================================
|
||||
|
||||
\echo ''
|
||||
\echo '=== RLS Enforcement Test ==='
|
||||
\echo 'Testing RLS on scheduler.runs (should fail without tenant context)...'
|
||||
|
||||
-- Reset tenant context
|
||||
SELECT set_config('app.tenant_id', '', false);
|
||||
|
||||
DO $$
|
||||
BEGIN
|
||||
-- This should raise an exception if RLS is working
|
||||
PERFORM * FROM scheduler.runs LIMIT 1;
|
||||
RAISE NOTICE 'WARNING: Query succeeded without tenant context - RLS may not be working!';
|
||||
EXCEPTION
|
||||
WHEN OTHERS THEN
|
||||
RAISE NOTICE 'OK: RLS blocked query without tenant context: %', SQLERRM;
|
||||
END
|
||||
$$;
|
||||
|
||||
-- ============================================================================
|
||||
-- Part 6: Admin bypass role verification
|
||||
-- ============================================================================
|
||||
|
||||
\echo ''
|
||||
\echo '=== Admin Bypass Roles ==='
|
||||
|
||||
SELECT
|
||||
rolname AS role_name,
|
||||
rolbypassrls AS can_bypass_rls,
|
||||
rolcanlogin AS can_login
|
||||
FROM pg_roles
|
||||
WHERE rolname LIKE '%_admin'
|
||||
AND rolbypassrls = TRUE
|
||||
ORDER BY rolname;
|
||||
|
||||
-- ============================================================================
|
||||
-- Summary
|
||||
-- ============================================================================
|
||||
|
||||
\echo ''
|
||||
\echo '=== Summary ==='
|
||||
|
||||
SELECT
|
||||
'Total Tables' AS metric,
|
||||
COUNT(*)::TEXT AS value
|
||||
FROM pg_tables
|
||||
WHERE schemaname IN ('scheduler', 'notify', 'authority', 'vex', 'policy', 'unknowns')
|
||||
UNION ALL
|
||||
SELECT
|
||||
'Tables with RLS Enabled',
|
||||
COUNT(*)::TEXT
|
||||
FROM pg_tables
|
||||
WHERE schemaname IN ('scheduler', 'notify', 'authority', 'vex', 'policy', 'unknowns')
|
||||
AND rowsecurity = TRUE
|
||||
UNION ALL
|
||||
SELECT
|
||||
'Tables with RLS Forced',
|
||||
COUNT(*)::TEXT
|
||||
FROM pg_tables
|
||||
WHERE schemaname IN ('scheduler', 'notify', 'authority', 'vex', 'policy', 'unknowns')
|
||||
AND forcerowsecurity = TRUE
|
||||
UNION ALL
|
||||
SELECT
|
||||
'Active Policies',
|
||||
COUNT(*)::TEXT
|
||||
FROM pg_policies
|
||||
WHERE schemaname IN ('scheduler', 'notify', 'authority', 'vex', 'policy', 'unknowns');
|
||||
@@ -1,238 +0,0 @@
|
||||
-- Partition Validation Script
|
||||
-- Sprint: SPRINT_3422_0001_0001 - Time-Based Partitioning
|
||||
--
|
||||
-- Purpose: Verify that partitioned tables are properly configured and healthy
|
||||
|
||||
-- ============================================================================
|
||||
-- Part 1: List all partitioned tables
|
||||
-- ============================================================================
|
||||
|
||||
\echo '=== Partitioned Tables ==='
|
||||
|
||||
SELECT
|
||||
n.nspname AS schema,
|
||||
c.relname AS table_name,
|
||||
CASE pt.partstrat
|
||||
WHEN 'r' THEN 'RANGE'
|
||||
WHEN 'l' THEN 'LIST'
|
||||
WHEN 'h' THEN 'HASH'
|
||||
END AS partition_strategy,
|
||||
array_to_string(array_agg(a.attname ORDER BY k.col), ', ') AS partition_key
|
||||
FROM pg_class c
|
||||
JOIN pg_namespace n ON c.relnamespace = n.oid
|
||||
JOIN pg_partitioned_table pt ON c.oid = pt.partrelid
|
||||
JOIN LATERAL unnest(pt.partattrs) WITH ORDINALITY AS k(col, idx) ON true
|
||||
LEFT JOIN pg_attribute a ON a.attrelid = c.oid AND a.attnum = k.col
|
||||
WHERE n.nspname IN ('scheduler', 'notify', 'authority', 'vex', 'policy', 'unknowns', 'vuln')
|
||||
GROUP BY n.nspname, c.relname, pt.partstrat
|
||||
ORDER BY n.nspname, c.relname;
|
||||
|
||||
-- ============================================================================
|
||||
-- Part 2: Partition inventory with sizes
|
||||
-- ============================================================================
|
||||
|
||||
\echo ''
|
||||
\echo '=== Partition Inventory ==='
|
||||
|
||||
SELECT
|
||||
n.nspname AS schema,
|
||||
parent.relname AS parent_table,
|
||||
c.relname AS partition_name,
|
||||
pg_get_expr(c.relpartbound, c.oid) AS bounds,
|
||||
pg_size_pretty(pg_relation_size(c.oid)) AS size,
|
||||
s.n_live_tup AS estimated_rows
|
||||
FROM pg_class c
|
||||
JOIN pg_namespace n ON c.relnamespace = n.oid
|
||||
JOIN pg_inherits i ON c.oid = i.inhrelid
|
||||
JOIN pg_class parent ON i.inhparent = parent.oid
|
||||
LEFT JOIN pg_stat_user_tables s ON c.oid = s.relid
|
||||
WHERE n.nspname IN ('scheduler', 'notify', 'authority', 'vex', 'policy', 'unknowns', 'vuln')
|
||||
AND c.relkind = 'r'
|
||||
AND parent.relkind = 'p'
|
||||
ORDER BY n.nspname, parent.relname, c.relname;
|
||||
|
||||
-- ============================================================================
|
||||
-- Part 3: Check for missing future partitions
|
||||
-- ============================================================================
|
||||
|
||||
\echo ''
|
||||
\echo '=== Future Partition Coverage ==='
|
||||
|
||||
WITH partition_bounds AS (
|
||||
SELECT
|
||||
n.nspname AS schema_name,
|
||||
parent.relname AS table_name,
|
||||
c.relname AS partition_name,
|
||||
-- Extract the TO date from partition bound
|
||||
(regexp_match(pg_get_expr(c.relpartbound, c.oid), 'TO \(''([^'']+)''\)'))[1]::DATE AS end_date
|
||||
FROM pg_class c
|
||||
JOIN pg_namespace n ON c.relnamespace = n.oid
|
||||
JOIN pg_inherits i ON c.oid = i.inhrelid
|
||||
JOIN pg_class parent ON i.inhparent = parent.oid
|
||||
WHERE c.relkind = 'r'
|
||||
AND parent.relkind = 'p'
|
||||
AND c.relname NOT LIKE '%_default'
|
||||
),
|
||||
max_bounds AS (
|
||||
SELECT
|
||||
schema_name,
|
||||
table_name,
|
||||
MAX(end_date) AS max_partition_date
|
||||
FROM partition_bounds
|
||||
WHERE end_date IS NOT NULL
|
||||
GROUP BY schema_name, table_name
|
||||
)
|
||||
SELECT
|
||||
schema_name,
|
||||
table_name,
|
||||
max_partition_date,
|
||||
(max_partition_date - CURRENT_DATE) AS days_ahead,
|
||||
CASE
|
||||
WHEN (max_partition_date - CURRENT_DATE) < 30 THEN 'CRITICAL: Create partitions!'
|
||||
WHEN (max_partition_date - CURRENT_DATE) < 60 THEN 'WARNING: Running low'
|
||||
ELSE 'OK'
|
||||
END AS status
|
||||
FROM max_bounds
|
||||
ORDER BY days_ahead;
|
||||
|
||||
-- ============================================================================
|
||||
-- Part 4: Check for orphaned data in default partitions
|
||||
-- ============================================================================
|
||||
|
||||
\echo ''
|
||||
\echo '=== Default Partition Data (should be empty) ==='
|
||||
|
||||
DO $$
|
||||
DECLARE
|
||||
v_schema TEXT;
|
||||
v_table TEXT;
|
||||
v_count BIGINT;
|
||||
v_sql TEXT;
|
||||
BEGIN
|
||||
FOR v_schema, v_table IN
|
||||
SELECT n.nspname, c.relname
|
||||
FROM pg_class c
|
||||
JOIN pg_namespace n ON c.relnamespace = n.oid
|
||||
WHERE c.relname LIKE '%_default'
|
||||
AND n.nspname IN ('scheduler', 'notify', 'authority', 'vex', 'policy', 'unknowns', 'vuln')
|
||||
LOOP
|
||||
v_sql := format('SELECT COUNT(*) FROM %I.%I', v_schema, v_table);
|
||||
EXECUTE v_sql INTO v_count;
|
||||
|
||||
IF v_count > 0 THEN
|
||||
RAISE NOTICE 'WARNING: %.% has % rows in default partition!',
|
||||
v_schema, v_table, v_count;
|
||||
ELSE
|
||||
RAISE NOTICE 'OK: %.% is empty', v_schema, v_table;
|
||||
END IF;
|
||||
END LOOP;
|
||||
END
|
||||
$$;
|
||||
|
||||
-- ============================================================================
|
||||
-- Part 5: Index health on partitions
|
||||
-- ============================================================================
|
||||
|
||||
\echo ''
|
||||
\echo '=== Partition Index Coverage ==='
|
||||
|
||||
SELECT
|
||||
schemaname AS schema,
|
||||
tablename AS table_name,
|
||||
indexname AS index_name,
|
||||
indexdef
|
||||
FROM pg_indexes
|
||||
WHERE schemaname IN ('scheduler', 'notify', 'authority', 'vex', 'policy', 'unknowns', 'vuln')
|
||||
AND tablename LIKE '%_partitioned' OR tablename LIKE '%_202%'
|
||||
ORDER BY schemaname, tablename, indexname;
|
||||
|
||||
-- ============================================================================
|
||||
-- Part 6: BRIN index effectiveness check
|
||||
-- ============================================================================
|
||||
|
||||
\echo ''
|
||||
\echo '=== BRIN Index Statistics ==='
|
||||
|
||||
SELECT
|
||||
schemaname AS schema,
|
||||
tablename AS table_name,
|
||||
indexrelname AS index_name,
|
||||
idx_scan AS scans,
|
||||
idx_tup_read AS tuples_read,
|
||||
idx_tup_fetch AS tuples_fetched,
|
||||
pg_size_pretty(pg_relation_size(indexrelid)) AS index_size
|
||||
FROM pg_stat_user_indexes
|
||||
WHERE indexrelname LIKE 'brin_%'
|
||||
ORDER BY schemaname, tablename;
|
||||
|
||||
-- ============================================================================
|
||||
-- Part 7: Partition maintenance recommendations
|
||||
-- ============================================================================
|
||||
|
||||
\echo ''
|
||||
\echo '=== Maintenance Recommendations ==='
|
||||
|
||||
WITH partition_ages AS (
|
||||
SELECT
|
||||
n.nspname AS schema_name,
|
||||
parent.relname AS table_name,
|
||||
c.relname AS partition_name,
|
||||
(regexp_match(pg_get_expr(c.relpartbound, c.oid), 'FROM \(''([^'']+)''\)'))[1]::DATE AS start_date,
|
||||
(regexp_match(pg_get_expr(c.relpartbound, c.oid), 'TO \(''([^'']+)''\)'))[1]::DATE AS end_date
|
||||
FROM pg_class c
|
||||
JOIN pg_namespace n ON c.relnamespace = n.oid
|
||||
JOIN pg_inherits i ON c.oid = i.inhrelid
|
||||
JOIN pg_class parent ON i.inhparent = parent.oid
|
||||
WHERE c.relkind = 'r'
|
||||
AND parent.relkind = 'p'
|
||||
AND c.relname NOT LIKE '%_default'
|
||||
)
|
||||
SELECT
|
||||
schema_name,
|
||||
table_name,
|
||||
partition_name,
|
||||
start_date,
|
||||
end_date,
|
||||
(CURRENT_DATE - end_date) AS days_old,
|
||||
CASE
|
||||
WHEN (CURRENT_DATE - end_date) > 365 THEN 'Consider archiving (>1 year old)'
|
||||
WHEN (CURRENT_DATE - end_date) > 180 THEN 'Review retention policy (>6 months old)'
|
||||
ELSE 'Current'
|
||||
END AS recommendation
|
||||
FROM partition_ages
|
||||
WHERE start_date IS NOT NULL
|
||||
ORDER BY schema_name, table_name, start_date;
|
||||
|
||||
-- ============================================================================
|
||||
-- Summary
|
||||
-- ============================================================================
|
||||
|
||||
\echo ''
|
||||
\echo '=== Summary ==='
|
||||
|
||||
SELECT
|
||||
'Partitioned Tables' AS metric,
|
||||
COUNT(DISTINCT parent.relname)::TEXT AS value
|
||||
FROM pg_class c
|
||||
JOIN pg_namespace n ON c.relnamespace = n.oid
|
||||
JOIN pg_inherits i ON c.oid = i.inhrelid
|
||||
JOIN pg_class parent ON i.inhparent = parent.oid
|
||||
WHERE n.nspname IN ('scheduler', 'notify', 'authority', 'vex', 'policy', 'unknowns', 'vuln')
|
||||
AND parent.relkind = 'p'
|
||||
UNION ALL
|
||||
SELECT
|
||||
'Total Partitions',
|
||||
COUNT(*)::TEXT
|
||||
FROM pg_class c
|
||||
JOIN pg_namespace n ON c.relnamespace = n.oid
|
||||
JOIN pg_inherits i ON c.oid = i.inhrelid
|
||||
JOIN pg_class parent ON i.inhparent = parent.oid
|
||||
WHERE n.nspname IN ('scheduler', 'notify', 'authority', 'vex', 'policy', 'unknowns', 'vuln')
|
||||
AND parent.relkind = 'p'
|
||||
UNION ALL
|
||||
SELECT
|
||||
'BRIN Indexes',
|
||||
COUNT(*)::TEXT
|
||||
FROM pg_indexes
|
||||
WHERE indexname LIKE 'brin_%'
|
||||
AND schemaname IN ('scheduler', 'notify', 'authority', 'vex', 'policy', 'unknowns', 'vuln');
|
||||
@@ -1,33 +0,0 @@
|
||||
release:
|
||||
version: "2025.09.2-airgap"
|
||||
channel: "airgap"
|
||||
date: "2025-09-20T00:00:00Z"
|
||||
calendar: "2025.09"
|
||||
components:
|
||||
- name: authority
|
||||
image: registry.stella-ops.org/stellaops/authority@sha256:5551a3269b7008cd5aceecf45df018c67459ed519557ccbe48b093b926a39bcc
|
||||
- name: signer
|
||||
image: registry.stella-ops.org/stellaops/signer@sha256:ddbbd664a42846cea6b40fca6465bc679b30f72851158f300d01a8571c5478fc
|
||||
- name: attestor
|
||||
image: registry.stella-ops.org/stellaops/attestor@sha256:1ff0a3124d66d3a2702d8e421df40fbd98cc75cb605d95510598ebbae1433c50
|
||||
- name: scanner-web
|
||||
image: registry.stella-ops.org/stellaops/scanner-web@sha256:3df8ca21878126758203c1a0444e39fd97f77ddacf04a69685cda9f1e5e94718
|
||||
- name: scanner-worker
|
||||
image: registry.stella-ops.org/stellaops/scanner-worker@sha256:eea5d6cfe7835950c5ec7a735a651f2f0d727d3e470cf9027a4a402ea89c4fb5
|
||||
- name: concelier
|
||||
image: registry.stella-ops.org/stellaops/concelier@sha256:29e2e1a0972707e092cbd3d370701341f9fec2aa9316fb5d8100480f2a1c76b5
|
||||
- name: excititor
|
||||
image: registry.stella-ops.org/stellaops/excititor@sha256:65c0ee13f773efe920d7181512349a09d363ab3f3e177d276136bd2742325a68
|
||||
- name: advisory-ai-web
|
||||
image: registry.stella-ops.org/stellaops/advisory-ai-web:2025.09.2-airgap
|
||||
- name: advisory-ai-worker
|
||||
image: registry.stella-ops.org/stellaops/advisory-ai-worker:2025.09.2-airgap
|
||||
- name: web-ui
|
||||
image: registry.stella-ops.org/stellaops/web-ui@sha256:bee9668011ff414572131dc777faab4da24473fe12c230893f161cabee092a1d
|
||||
infrastructure:
|
||||
mongo:
|
||||
image: docker.io/library/mongo@sha256:c258b26dbb7774f97f52aff52231ca5f228273a84329c5f5e451c3739457db49
|
||||
minio:
|
||||
image: docker.io/minio/minio@sha256:14cea493d9a34af32f524e538b8346cf79f3321eff8e708c1e2960462bd8936e
|
||||
checksums:
|
||||
releaseManifestSha256: b787b833dddd73960c31338279daa0b0a0dce2ef32bd32ef1aaf953d66135f94
|
||||
@@ -1,49 +0,0 @@
|
||||
release:
|
||||
version: 2025.09.2
|
||||
channel: stable
|
||||
date: '2025-09-20T00:00:00Z'
|
||||
calendar: '2025.09'
|
||||
components:
|
||||
- name: authority
|
||||
image: registry.stella-ops.org/stellaops/authority@sha256:b0348bad1d0b401cc3c71cb40ba034c8043b6c8874546f90d4783c9dbfcc0bf5
|
||||
- name: signer
|
||||
image: registry.stella-ops.org/stellaops/signer@sha256:8ad574e61f3a9e9bda8a58eb2700ae46813284e35a150b1137bc7c2b92ac0f2e
|
||||
- name: attestor
|
||||
image: registry.stella-ops.org/stellaops/attestor@sha256:0534985f978b0b5d220d73c96fddd962cd9135f616811cbe3bff4666c5af568f
|
||||
- name: scanner-web
|
||||
image: registry.stella-ops.org/stellaops/scanner-web@sha256:14b23448c3f9586a9156370b3e8c1991b61907efa666ca37dd3aaed1e79fe3b7
|
||||
- name: scanner-worker
|
||||
image: registry.stella-ops.org/stellaops/scanner-worker@sha256:32e25e76386eb9ea8bee0a1ad546775db9a2df989fab61ac877e351881960dab
|
||||
- name: concelier
|
||||
image: registry.stella-ops.org/stellaops/concelier@sha256:c58cdcaee1d266d68d498e41110a589dd204b487d37381096bd61ab345a867c5
|
||||
- name: excititor
|
||||
image: registry.stella-ops.org/stellaops/excititor@sha256:59022e2016aebcef5c856d163ae705755d3f81949d41195256e935ef40a627fa
|
||||
- name: advisory-ai-web
|
||||
image: registry.stella-ops.org/stellaops/advisory-ai-web:2025.09.2
|
||||
- name: advisory-ai-worker
|
||||
image: registry.stella-ops.org/stellaops/advisory-ai-worker:2025.09.2
|
||||
- name: web-ui
|
||||
image: registry.stella-ops.org/stellaops/web-ui@sha256:10d924808c48e4353e3a241da62eb7aefe727a1d6dc830eb23a8e181013b3a23
|
||||
- name: orchestrator
|
||||
image: registry.stella-ops.org/stellaops/orchestrator@sha256:97f12856ce870bafd3328bda86833bcccbf56d255941d804966b5557f6610119
|
||||
- name: policy-registry
|
||||
image: registry.stella-ops.org/stellaops/policy-registry@sha256:c6cad8055e9827ebcbebb6ad4d6866dce4b83a0a49b0a8a6500b736a5cb26fa7
|
||||
- name: vex-lens
|
||||
image: registry.stella-ops.org/stellaops/vex-lens@sha256:b44e63ecfeebc345a70c073c1ce5ace709c58be0ffaad0e2862758aeee3092fb
|
||||
- name: issuer-directory
|
||||
image: registry.stella-ops.org/stellaops/issuer-directory@sha256:67e8ef02c97d3156741e857756994888f30c373ace8e84886762edba9dc51914
|
||||
- name: findings-ledger
|
||||
image: registry.stella-ops.org/stellaops/findings-ledger@sha256:71d4c361ba8b2f8b69d652597bc3f2efc8a64f93fab854ce25272a88506df49c
|
||||
- name: vuln-explorer-api
|
||||
image: registry.stella-ops.org/stellaops/vuln-explorer-api@sha256:7fc7e43a05cbeb0106ce7d4d634612e83de6fdc119aaab754a71c1d60b82841d
|
||||
- name: packs-registry
|
||||
image: registry.stella-ops.org/stellaops/packs-registry@sha256:1f5e9416c4dc608594ad6fad87c24d72134427f899c192b494e22b268499c791
|
||||
- name: task-runner
|
||||
image: registry.stella-ops.org/stellaops/task-runner@sha256:eb5ad992b49a41554f41516be1a6afcfa6522faf2111c08ff2b3664ad2fc954b
|
||||
infrastructure:
|
||||
mongo:
|
||||
image: docker.io/library/mongo@sha256:c258b26dbb7774f97f52aff52231ca5f228273a84329c5f5e451c3739457db49
|
||||
minio:
|
||||
image: docker.io/minio/minio@sha256:14cea493d9a34af32f524e538b8346cf79f3321eff8e708c1e2960462bd8936e
|
||||
checksums:
|
||||
releaseManifestSha256: dc3c8fe1ab83941c838ccc5a8a5862f7ddfa38c2078e580b5649db26554565b7
|
||||
@@ -1,33 +0,0 @@
|
||||
release:
|
||||
version: "2025.09.2"
|
||||
channel: "stable"
|
||||
date: "2025-09-20T00:00:00Z"
|
||||
calendar: "2025.09"
|
||||
components:
|
||||
- name: authority
|
||||
image: registry.stella-ops.org/stellaops/authority@sha256:b0348bad1d0b401cc3c71cb40ba034c8043b6c8874546f90d4783c9dbfcc0bf5
|
||||
- name: signer
|
||||
image: registry.stella-ops.org/stellaops/signer@sha256:8ad574e61f3a9e9bda8a58eb2700ae46813284e35a150b1137bc7c2b92ac0f2e
|
||||
- name: attestor
|
||||
image: registry.stella-ops.org/stellaops/attestor@sha256:0534985f978b0b5d220d73c96fddd962cd9135f616811cbe3bff4666c5af568f
|
||||
- name: scanner-web
|
||||
image: registry.stella-ops.org/stellaops/scanner-web@sha256:14b23448c3f9586a9156370b3e8c1991b61907efa666ca37dd3aaed1e79fe3b7
|
||||
- name: scanner-worker
|
||||
image: registry.stella-ops.org/stellaops/scanner-worker@sha256:32e25e76386eb9ea8bee0a1ad546775db9a2df989fab61ac877e351881960dab
|
||||
- name: concelier
|
||||
image: registry.stella-ops.org/stellaops/concelier@sha256:c58cdcaee1d266d68d498e41110a589dd204b487d37381096bd61ab345a867c5
|
||||
- name: excititor
|
||||
image: registry.stella-ops.org/stellaops/excititor@sha256:59022e2016aebcef5c856d163ae705755d3f81949d41195256e935ef40a627fa
|
||||
- name: advisory-ai-web
|
||||
image: registry.stella-ops.org/stellaops/advisory-ai-web:2025.09.2
|
||||
- name: advisory-ai-worker
|
||||
image: registry.stella-ops.org/stellaops/advisory-ai-worker:2025.09.2
|
||||
- name: web-ui
|
||||
image: registry.stella-ops.org/stellaops/web-ui@sha256:10d924808c48e4353e3a241da62eb7aefe727a1d6dc830eb23a8e181013b3a23
|
||||
infrastructure:
|
||||
mongo:
|
||||
image: docker.io/library/mongo@sha256:c258b26dbb7774f97f52aff52231ca5f228273a84329c5f5e451c3739457db49
|
||||
minio:
|
||||
image: docker.io/minio/minio@sha256:14cea493d9a34af32f524e538b8346cf79f3321eff8e708c1e2960462bd8936e
|
||||
checksums:
|
||||
releaseManifestSha256: dc3c8fe1ab83941c838ccc5a8a5862f7ddfa38c2078e580b5649db26554565b7
|
||||
@@ -1,37 +0,0 @@
|
||||
release:
|
||||
version: "2025.10.0-edge"
|
||||
channel: "edge"
|
||||
date: "2025-10-01T00:00:00Z"
|
||||
calendar: "2025.10"
|
||||
components:
|
||||
- name: authority
|
||||
image: registry.stella-ops.org/stellaops/authority@sha256:a8e8faec44a579aa5714e58be835f25575710430b1ad2ccd1282a018cd9ffcdd
|
||||
- name: signer
|
||||
image: registry.stella-ops.org/stellaops/signer@sha256:8bfef9a75783883d49fc18e3566553934e970b00ee090abee9cb110d2d5c3298
|
||||
- name: attestor
|
||||
image: registry.stella-ops.org/stellaops/attestor@sha256:5cc417948c029da01dccf36e4645d961a3f6d8de7e62fe98d845f07cd2282114
|
||||
- name: issuer-directory-web
|
||||
image: registry.stella-ops.org/stellaops/issuer-directory-web:2025.10.0-edge
|
||||
- name: scanner-web
|
||||
image: registry.stella-ops.org/stellaops/scanner-web@sha256:e0dfdb087e330585a5953029fb4757f5abdf7610820a085bd61b457dbead9a11
|
||||
- name: scanner-worker
|
||||
image: registry.stella-ops.org/stellaops/scanner-worker@sha256:92dda42f6f64b2d9522104a5c9ffb61d37b34dd193132b68457a259748008f37
|
||||
- name: concelier
|
||||
image: registry.stella-ops.org/stellaops/concelier@sha256:dafef3954eb4b837e2c424dd2d23e1e4d60fa83794840fac9cd3dea1d43bd085
|
||||
- name: excititor
|
||||
image: registry.stella-ops.org/stellaops/excititor@sha256:d9bd5cadf1eab427447ce3df7302c30ded837239771cc6433b9befb895054285
|
||||
- name: advisory-ai-web
|
||||
image: registry.stella-ops.org/stellaops/advisory-ai-web:2025.10.0-edge
|
||||
- name: advisory-ai-worker
|
||||
image: registry.stella-ops.org/stellaops/advisory-ai-worker:2025.10.0-edge
|
||||
- name: web-ui
|
||||
image: registry.stella-ops.org/stellaops/web-ui@sha256:38b225fa7767a5b94ebae4dae8696044126aac429415e93de514d5dd95748dcf
|
||||
infrastructure:
|
||||
mongo:
|
||||
image: docker.io/library/mongo@sha256:c258b26dbb7774f97f52aff52231ca5f228273a84329c5f5e451c3739457db49
|
||||
minio:
|
||||
image: docker.io/minio/minio@sha256:14cea493d9a34af32f524e538b8346cf79f3321eff8e708c1e2960462bd8936e
|
||||
rustfs:
|
||||
image: registry.stella-ops.org/stellaops/rustfs:2025.10.0-edge
|
||||
checksums:
|
||||
releaseManifestSha256: 64d5b05c864bbfaeb29dad3958f4e7ff43d13393059da558ab355cebb9aba2b7
|
||||
@@ -1,35 +0,0 @@
|
||||
image:
|
||||
repository: stellaops/signals
|
||||
tag: "local"
|
||||
pullPolicy: IfNotPresent
|
||||
|
||||
service:
|
||||
type: ClusterIP
|
||||
port: 5088
|
||||
|
||||
env:
|
||||
ASPNETCORE_URLS: "http://+:5088"
|
||||
Signals__Mongo__ConnectionString: "mongodb://signals-mongo:27017/signals"
|
||||
Signals__Mongo__Database: "signals"
|
||||
Signals__Cache__ConnectionString: "signals-valkey:6379"
|
||||
Signals__Storage__RootPath: "/data/artifacts"
|
||||
Signals__Authority__Enabled: "false"
|
||||
Signals__OpenApi__Enabled: "true"
|
||||
|
||||
persistence:
|
||||
enabled: true
|
||||
mountPath: /data/artifacts
|
||||
size: 5Gi
|
||||
storageClass: ""
|
||||
|
||||
valkey:
|
||||
enabled: true
|
||||
host: signals-valkey
|
||||
port: 6379
|
||||
|
||||
mongo:
|
||||
enabled: true
|
||||
connectionString: "mongodb://signals-mongo:27017/signals"
|
||||
|
||||
ingress:
|
||||
enabled: false
|
||||
@@ -1,26 +0,0 @@
|
||||
# StellaOps Zastava Agent Configuration
|
||||
# Copy this file to /etc/stellaops/zastava-agent.env
|
||||
|
||||
# Required: Tenant identifier for multi-tenancy
|
||||
ZASTAVA_TENANT=default
|
||||
|
||||
# Required: Scanner backend URL
|
||||
ZASTAVA_AGENT__Backend__BaseAddress=https://scanner.internal
|
||||
|
||||
# Optional: Node name (defaults to hostname)
|
||||
# ZASTAVA_NODE_NAME=
|
||||
|
||||
# Optional: Docker socket endpoint (defaults to unix:///var/run/docker.sock)
|
||||
# ZASTAVA_AGENT__DockerEndpoint=unix:///var/run/docker.sock
|
||||
|
||||
# Optional: Event buffer path (defaults to /var/lib/zastava-agent/runtime-events)
|
||||
# ZASTAVA_AGENT__EventBufferPath=/var/lib/zastava-agent/runtime-events
|
||||
|
||||
# Optional: Health check port (defaults to 8080)
|
||||
# ZASTAVA_AGENT__HealthCheck__Port=8080
|
||||
|
||||
# Optional: Allow insecure HTTP backend (NOT recommended for production)
|
||||
# ZASTAVA_AGENT__Backend__AllowInsecureHttp=false
|
||||
|
||||
# Optional: Logging level
|
||||
# Serilog__MinimumLevel__Default=Information
|
||||
@@ -1,58 +0,0 @@
|
||||
[Unit]
|
||||
Description=StellaOps Zastava Agent - Container Runtime Monitor
|
||||
Documentation=https://docs.stellaops.org/zastava/agent/
|
||||
After=network-online.target docker.service containerd.service
|
||||
Wants=network-online.target
|
||||
Requires=docker.service
|
||||
|
||||
[Service]
|
||||
Type=notify
|
||||
ExecStart=/opt/stellaops/zastava-agent/StellaOps.Zastava.Agent
|
||||
WorkingDirectory=/opt/stellaops/zastava-agent
|
||||
Restart=always
|
||||
RestartSec=5
|
||||
|
||||
# Environment configuration
|
||||
EnvironmentFile=-/etc/stellaops/zastava-agent.env
|
||||
Environment=DOTNET_ENVIRONMENT=Production
|
||||
Environment=ASPNETCORE_ENVIRONMENT=Production
|
||||
|
||||
# User and permissions
|
||||
User=zastava-agent
|
||||
Group=docker
|
||||
|
||||
# Security hardening
|
||||
NoNewPrivileges=true
|
||||
ProtectSystem=strict
|
||||
ProtectHome=true
|
||||
PrivateTmp=true
|
||||
PrivateDevices=true
|
||||
ProtectKernelTunables=true
|
||||
ProtectKernelModules=true
|
||||
ProtectControlGroups=true
|
||||
RestrictRealtime=true
|
||||
RestrictSUIDSGID=true
|
||||
|
||||
# Allow read access to Docker socket
|
||||
ReadWritePaths=/var/run/docker.sock
|
||||
ReadWritePaths=/var/lib/zastava-agent
|
||||
|
||||
# Capabilities
|
||||
CapabilityBoundingSet=
|
||||
AmbientCapabilities=
|
||||
|
||||
# Resource limits
|
||||
LimitNOFILE=65536
|
||||
LimitNPROC=4096
|
||||
MemoryMax=512M
|
||||
|
||||
# Logging
|
||||
StandardOutput=journal
|
||||
StandardError=journal
|
||||
SyslogIdentifier=zastava-agent
|
||||
|
||||
# Watchdog (5 minute timeout)
|
||||
WatchdogSec=300
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
1
deploy/telemetry/.gitignore
vendored
1
deploy/telemetry/.gitignore
vendored
@@ -1 +0,0 @@
|
||||
certs/
|
||||
@@ -1,35 +0,0 @@
|
||||
# Telemetry Collector Assets
|
||||
|
||||
These assets provision the default OpenTelemetry Collector instance required by
|
||||
`DEVOPS-OBS-50-001`. The collector acts as the secured ingest point for traces,
|
||||
metrics, and logs emitted by Stella Ops services.
|
||||
|
||||
## Contents
|
||||
|
||||
| File | Purpose |
|
||||
| ---- | ------- |
|
||||
| `otel-collector-config.yaml` | Baseline collector configuration (mutual TLS, OTLP receivers, Prometheus exporter). |
|
||||
| `storage/prometheus.yaml` | Prometheus scrape configuration tuned for the collector and service tenants. |
|
||||
| `storage/tempo.yaml` | Tempo configuration with multitenancy, WAL, and compaction settings. |
|
||||
| `storage/loki.yaml` | Loki configuration enabling multitenant log ingestion with retention policies. |
|
||||
| `storage/tenants/*.yaml` | Per-tenant overrides for Tempo and Loki rate/retention controls. |
|
||||
|
||||
## Development workflow
|
||||
|
||||
1. Generate development certificates (collector + client) using
|
||||
`ops/devops/telemetry/generate_dev_tls.sh`.
|
||||
2. Launch the collector via `docker compose -f docker-compose.telemetry.yaml up`.
|
||||
3. Launch the storage backends (Prometheus, Tempo, Loki) via
|
||||
`docker compose -f docker-compose.telemetry-storage.yaml up`.
|
||||
4. Run the smoke test: `python ops/devops/telemetry/smoke_otel_collector.py`.
|
||||
5. Explore the storage configuration (`storage/README.md`) to tune retention/limits.
|
||||
|
||||
The smoke test sends OTLP traffic over TLS and asserts the collector accepted
|
||||
traces, metrics, and logs by scraping the Prometheus metrics endpoint.
|
||||
|
||||
## Kubernetes
|
||||
|
||||
The Helm chart consumes the same configuration (see `values.yaml`). Provide TLS
|
||||
material via a secret referenced by `telemetry.collector.tls.secretName`,
|
||||
containing `ca.crt`, `tls.crt`, and `tls.key`. Client certificates are required
|
||||
for ingestion and should be issued by the same CA.
|
||||
@@ -1,164 +0,0 @@
|
||||
# ExportCenter Alert Rules
|
||||
# SLO Burn-rate alerts for export service reliability
|
||||
|
||||
groups:
|
||||
- name: export-center-slo
|
||||
interval: 30s
|
||||
rules:
|
||||
# SLO: 99.5% success rate target
|
||||
# Error budget: 0.5% (432 errors per day at 86400 requests/day)
|
||||
|
||||
# Fast burn - 2% budget consumption in 1 hour (critical)
|
||||
- alert: ExportCenterHighErrorBurnRate
|
||||
expr: |
|
||||
(
|
||||
sum(rate(export_runs_failed_total[1h]))
|
||||
/
|
||||
sum(rate(export_runs_total[1h]))
|
||||
) > (14.4 * 0.005)
|
||||
for: 2m
|
||||
labels:
|
||||
severity: critical
|
||||
service: export-center
|
||||
slo: availability
|
||||
annotations:
|
||||
summary: "ExportCenter high error burn rate"
|
||||
description: "Error rate is {{ $value | humanizePercentage }} over the last hour, consuming error budget at 14.4x the sustainable rate."
|
||||
runbook_url: "https://docs.stellaops.io/runbooks/export-center/high-error-rate"
|
||||
|
||||
# Slow burn - 10% budget consumption in 6 hours (warning)
|
||||
- alert: ExportCenterElevatedErrorBurnRate
|
||||
expr: |
|
||||
(
|
||||
sum(rate(export_runs_failed_total[6h]))
|
||||
/
|
||||
sum(rate(export_runs_total[6h]))
|
||||
) > (6 * 0.005)
|
||||
for: 5m
|
||||
labels:
|
||||
severity: warning
|
||||
service: export-center
|
||||
slo: availability
|
||||
annotations:
|
||||
summary: "ExportCenter elevated error burn rate"
|
||||
description: "Error rate is {{ $value | humanizePercentage }} over the last 6 hours, consuming error budget at 6x the sustainable rate."
|
||||
runbook_url: "https://docs.stellaops.io/runbooks/export-center/elevated-error-rate"
|
||||
|
||||
- name: export-center-latency
|
||||
interval: 30s
|
||||
rules:
|
||||
# SLO: 95% of exports complete within 120s
|
||||
# Fast burn - p95 latency exceeding threshold
|
||||
- alert: ExportCenterHighLatency
|
||||
expr: |
|
||||
histogram_quantile(0.95,
|
||||
sum(rate(export_run_duration_seconds_bucket[5m])) by (le)
|
||||
) > 120
|
||||
for: 5m
|
||||
labels:
|
||||
severity: warning
|
||||
service: export-center
|
||||
slo: latency
|
||||
annotations:
|
||||
summary: "ExportCenter high latency"
|
||||
description: "95th percentile export duration is {{ $value | humanizeDuration }}, exceeding 120s SLO target."
|
||||
runbook_url: "https://docs.stellaops.io/runbooks/export-center/high-latency"
|
||||
|
||||
# Critical latency - p99 exceeding 5 minutes
|
||||
- alert: ExportCenterCriticalLatency
|
||||
expr: |
|
||||
histogram_quantile(0.99,
|
||||
sum(rate(export_run_duration_seconds_bucket[5m])) by (le)
|
||||
) > 300
|
||||
for: 2m
|
||||
labels:
|
||||
severity: critical
|
||||
service: export-center
|
||||
slo: latency
|
||||
annotations:
|
||||
summary: "ExportCenter critical latency"
|
||||
description: "99th percentile export duration is {{ $value | humanizeDuration }}, indicating severe performance degradation."
|
||||
runbook_url: "https://docs.stellaops.io/runbooks/export-center/critical-latency"
|
||||
|
||||
- name: export-center-capacity
|
||||
interval: 60s
|
||||
rules:
|
||||
# Queue buildup warning
|
||||
- alert: ExportCenterHighConcurrency
|
||||
expr: sum(export_runs_in_progress) > 50
|
||||
for: 5m
|
||||
labels:
|
||||
severity: warning
|
||||
service: export-center
|
||||
annotations:
|
||||
summary: "ExportCenter high concurrency"
|
||||
description: "{{ $value }} exports currently in progress. Consider scaling or investigating slow exports."
|
||||
runbook_url: "https://docs.stellaops.io/runbooks/export-center/high-concurrency"
|
||||
|
||||
# Stuck exports - exports running longer than 30 minutes
|
||||
- alert: ExportCenterStuckExports
|
||||
expr: |
|
||||
histogram_quantile(0.99,
|
||||
sum(rate(export_run_duration_seconds_bucket{status!="completed"}[1h])) by (le)
|
||||
) > 1800
|
||||
for: 10m
|
||||
labels:
|
||||
severity: warning
|
||||
service: export-center
|
||||
annotations:
|
||||
summary: "ExportCenter potentially stuck exports"
|
||||
description: "Some exports may be stuck - 99th percentile duration for incomplete exports exceeds 30 minutes."
|
||||
runbook_url: "https://docs.stellaops.io/runbooks/export-center/stuck-exports"
|
||||
|
||||
- name: export-center-errors
|
||||
interval: 30s
|
||||
rules:
|
||||
# Specific error code spike
|
||||
- alert: ExportCenterErrorCodeSpike
|
||||
expr: |
|
||||
sum by (error_code) (
|
||||
rate(export_runs_failed_total[5m])
|
||||
) > 0.1
|
||||
for: 5m
|
||||
labels:
|
||||
severity: warning
|
||||
service: export-center
|
||||
annotations:
|
||||
summary: "ExportCenter error code spike: {{ $labels.error_code }}"
|
||||
description: "Error code {{ $labels.error_code }} is occurring at {{ $value | humanize }}/s rate."
|
||||
runbook_url: "https://docs.stellaops.io/runbooks/export-center/error-codes"
|
||||
|
||||
# No successful exports in 15 minutes (when there is traffic)
|
||||
- alert: ExportCenterNoSuccessfulExports
|
||||
expr: |
|
||||
(
|
||||
sum(rate(export_runs_total[15m])) > 0
|
||||
)
|
||||
and
|
||||
(
|
||||
sum(rate(export_runs_success_total[15m])) == 0
|
||||
)
|
||||
for: 10m
|
||||
labels:
|
||||
severity: critical
|
||||
service: export-center
|
||||
annotations:
|
||||
summary: "ExportCenter no successful exports"
|
||||
description: "No exports have completed successfully in the last 15 minutes despite ongoing attempts."
|
||||
runbook_url: "https://docs.stellaops.io/runbooks/export-center/no-successful-exports"
|
||||
|
||||
- name: export-center-deprecation
|
||||
interval: 5m
|
||||
rules:
|
||||
# Deprecated endpoint usage
|
||||
- alert: ExportCenterDeprecatedEndpointUsage
|
||||
expr: |
|
||||
sum(rate(export_center_deprecated_endpoint_access_total[1h])) > 0
|
||||
for: 1h
|
||||
labels:
|
||||
severity: info
|
||||
service: export-center
|
||||
annotations:
|
||||
summary: "Deprecated export endpoints still in use"
|
||||
description: "Legacy /exports endpoints are still being accessed at {{ $value | humanize }}/s. Migration to v1 API recommended."
|
||||
runbook_url: "https://docs.stellaops.io/api/export-center/migration"
|
||||
@@ -1,42 +0,0 @@
|
||||
# Scanner FN-Drift Alert Rules
|
||||
# SLO alerts for false-negative drift thresholds (30-day rolling window)
|
||||
|
||||
groups:
|
||||
- name: scanner-fn-drift
|
||||
interval: 30s
|
||||
rules:
|
||||
- alert: ScannerFnDriftWarning
|
||||
expr: scanner_fn_drift_percent > 1.0
|
||||
for: 5m
|
||||
labels:
|
||||
severity: warning
|
||||
service: scanner
|
||||
slo: fn-drift
|
||||
annotations:
|
||||
summary: "Scanner FN-Drift rate above warning threshold"
|
||||
description: "FN-Drift is {{ $value | humanizePercentage }} (> 1.0%) over the 30-day rolling window."
|
||||
runbook_url: "https://docs.stellaops.io/runbooks/scanner/fn-drift-warning"
|
||||
|
||||
- alert: ScannerFnDriftCritical
|
||||
expr: scanner_fn_drift_percent > 2.5
|
||||
for: 5m
|
||||
labels:
|
||||
severity: critical
|
||||
service: scanner
|
||||
slo: fn-drift
|
||||
annotations:
|
||||
summary: "Scanner FN-Drift rate above critical threshold"
|
||||
description: "FN-Drift is {{ $value | humanizePercentage }} (> 2.5%) over the 30-day rolling window."
|
||||
runbook_url: "https://docs.stellaops.io/runbooks/scanner/fn-drift-critical"
|
||||
|
||||
- alert: ScannerFnDriftEngineViolation
|
||||
expr: scanner_fn_drift_cause_engine > 0
|
||||
for: 1m
|
||||
labels:
|
||||
severity: page
|
||||
service: scanner
|
||||
slo: determinism
|
||||
annotations:
|
||||
summary: "Engine-caused FN drift detected (determinism violation)"
|
||||
description: "Engine-caused FN drift count is {{ $value }} (> 0). This indicates non-feed, non-policy changes affecting outcomes."
|
||||
runbook_url: "https://docs.stellaops.io/runbooks/scanner/fn-drift-engine-violation"
|
||||
@@ -1,638 +0,0 @@
|
||||
{
|
||||
"annotations": {
|
||||
"list": [
|
||||
{
|
||||
"builtIn": 1,
|
||||
"datasource": { "type": "grafana", "uid": "-- Grafana --" },
|
||||
"enable": true,
|
||||
"hide": true,
|
||||
"iconColor": "rgba(0, 211, 255, 1)",
|
||||
"name": "Annotations & Alerts",
|
||||
"type": "dashboard"
|
||||
}
|
||||
]
|
||||
},
|
||||
"description": "ExportCenter service observability dashboard",
|
||||
"editable": true,
|
||||
"fiscalYearStartMonth": 0,
|
||||
"graphTooltip": 0,
|
||||
"id": null,
|
||||
"links": [],
|
||||
"liveNow": false,
|
||||
"panels": [
|
||||
{
|
||||
"collapsed": false,
|
||||
"gridPos": { "h": 1, "w": 24, "x": 0, "y": 0 },
|
||||
"id": 1,
|
||||
"panels": [],
|
||||
"title": "Export Runs Overview",
|
||||
"type": "row"
|
||||
},
|
||||
{
|
||||
"datasource": { "type": "prometheus", "uid": "${datasource}" },
|
||||
"fieldConfig": {
|
||||
"defaults": {
|
||||
"color": { "mode": "thresholds" },
|
||||
"mappings": [],
|
||||
"thresholds": {
|
||||
"mode": "absolute",
|
||||
"steps": [
|
||||
{ "color": "green", "value": null }
|
||||
]
|
||||
},
|
||||
"unit": "short"
|
||||
},
|
||||
"overrides": []
|
||||
},
|
||||
"gridPos": { "h": 4, "w": 4, "x": 0, "y": 1 },
|
||||
"id": 2,
|
||||
"options": {
|
||||
"colorMode": "value",
|
||||
"graphMode": "area",
|
||||
"justifyMode": "auto",
|
||||
"orientation": "auto",
|
||||
"reduceOptions": {
|
||||
"calcs": ["lastNotNull"],
|
||||
"fields": "",
|
||||
"values": false
|
||||
},
|
||||
"textMode": "auto"
|
||||
},
|
||||
"pluginVersion": "10.0.0",
|
||||
"targets": [
|
||||
{
|
||||
"datasource": { "type": "prometheus", "uid": "${datasource}" },
|
||||
"editorMode": "code",
|
||||
"expr": "sum(increase(export_runs_total{tenant=~\"$tenant\"}[$__range]))",
|
||||
"legendFormat": "Total Runs",
|
||||
"range": true,
|
||||
"refId": "A"
|
||||
}
|
||||
],
|
||||
"title": "Total Export Runs",
|
||||
"type": "stat"
|
||||
},
|
||||
{
|
||||
"datasource": { "type": "prometheus", "uid": "${datasource}" },
|
||||
"fieldConfig": {
|
||||
"defaults": {
|
||||
"color": { "mode": "thresholds" },
|
||||
"mappings": [],
|
||||
"thresholds": {
|
||||
"mode": "absolute",
|
||||
"steps": [
|
||||
{ "color": "green", "value": null }
|
||||
]
|
||||
},
|
||||
"unit": "short"
|
||||
},
|
||||
"overrides": []
|
||||
},
|
||||
"gridPos": { "h": 4, "w": 4, "x": 4, "y": 1 },
|
||||
"id": 3,
|
||||
"options": {
|
||||
"colorMode": "value",
|
||||
"graphMode": "area",
|
||||
"justifyMode": "auto",
|
||||
"orientation": "auto",
|
||||
"reduceOptions": {
|
||||
"calcs": ["lastNotNull"],
|
||||
"fields": "",
|
||||
"values": false
|
||||
},
|
||||
"textMode": "auto"
|
||||
},
|
||||
"pluginVersion": "10.0.0",
|
||||
"targets": [
|
||||
{
|
||||
"datasource": { "type": "prometheus", "uid": "${datasource}" },
|
||||
"editorMode": "code",
|
||||
"expr": "sum(increase(export_runs_success_total{tenant=~\"$tenant\"}[$__range]))",
|
||||
"legendFormat": "Successful",
|
||||
"range": true,
|
||||
"refId": "A"
|
||||
}
|
||||
],
|
||||
"title": "Successful Runs",
|
||||
"type": "stat"
|
||||
},
|
||||
{
|
||||
"datasource": { "type": "prometheus", "uid": "${datasource}" },
|
||||
"fieldConfig": {
|
||||
"defaults": {
|
||||
"color": { "mode": "thresholds" },
|
||||
"mappings": [],
|
||||
"thresholds": {
|
||||
"mode": "absolute",
|
||||
"steps": [
|
||||
{ "color": "green", "value": null },
|
||||
{ "color": "yellow", "value": 1 },
|
||||
{ "color": "red", "value": 5 }
|
||||
]
|
||||
},
|
||||
"unit": "short"
|
||||
},
|
||||
"overrides": []
|
||||
},
|
||||
"gridPos": { "h": 4, "w": 4, "x": 8, "y": 1 },
|
||||
"id": 4,
|
||||
"options": {
|
||||
"colorMode": "value",
|
||||
"graphMode": "area",
|
||||
"justifyMode": "auto",
|
||||
"orientation": "auto",
|
||||
"reduceOptions": {
|
||||
"calcs": ["lastNotNull"],
|
||||
"fields": "",
|
||||
"values": false
|
||||
},
|
||||
"textMode": "auto"
|
||||
},
|
||||
"pluginVersion": "10.0.0",
|
||||
"targets": [
|
||||
{
|
||||
"datasource": { "type": "prometheus", "uid": "${datasource}" },
|
||||
"editorMode": "code",
|
||||
"expr": "sum(increase(export_runs_failed_total{tenant=~\"$tenant\"}[$__range]))",
|
||||
"legendFormat": "Failed",
|
||||
"range": true,
|
||||
"refId": "A"
|
||||
}
|
||||
],
|
||||
"title": "Failed Runs",
|
||||
"type": "stat"
|
||||
},
|
||||
{
|
||||
"datasource": { "type": "prometheus", "uid": "${datasource}" },
|
||||
"fieldConfig": {
|
||||
"defaults": {
|
||||
"color": { "mode": "thresholds" },
|
||||
"mappings": [],
|
||||
"thresholds": {
|
||||
"mode": "absolute",
|
||||
"steps": [
|
||||
{ "color": "red", "value": null },
|
||||
{ "color": "yellow", "value": 95 },
|
||||
{ "color": "green", "value": 99 }
|
||||
]
|
||||
},
|
||||
"unit": "percent"
|
||||
},
|
||||
"overrides": []
|
||||
},
|
||||
"gridPos": { "h": 4, "w": 4, "x": 12, "y": 1 },
|
||||
"id": 5,
|
||||
"options": {
|
||||
"colorMode": "value",
|
||||
"graphMode": "area",
|
||||
"justifyMode": "auto",
|
||||
"orientation": "auto",
|
||||
"reduceOptions": {
|
||||
"calcs": ["lastNotNull"],
|
||||
"fields": "",
|
||||
"values": false
|
||||
},
|
||||
"textMode": "auto"
|
||||
},
|
||||
"pluginVersion": "10.0.0",
|
||||
"targets": [
|
||||
{
|
||||
"datasource": { "type": "prometheus", "uid": "${datasource}" },
|
||||
"editorMode": "code",
|
||||
"expr": "100 * sum(increase(export_runs_success_total{tenant=~\"$tenant\"}[$__range])) / sum(increase(export_runs_total{tenant=~\"$tenant\"}[$__range]))",
|
||||
"legendFormat": "Success Rate",
|
||||
"range": true,
|
||||
"refId": "A"
|
||||
}
|
||||
],
|
||||
"title": "Success Rate",
|
||||
"type": "stat"
|
||||
},
|
||||
{
|
||||
"datasource": { "type": "prometheus", "uid": "${datasource}" },
|
||||
"fieldConfig": {
|
||||
"defaults": {
|
||||
"color": { "mode": "thresholds" },
|
||||
"mappings": [],
|
||||
"thresholds": {
|
||||
"mode": "absolute",
|
||||
"steps": [
|
||||
{ "color": "green", "value": null }
|
||||
]
|
||||
},
|
||||
"unit": "short"
|
||||
},
|
||||
"overrides": []
|
||||
},
|
||||
"gridPos": { "h": 4, "w": 4, "x": 16, "y": 1 },
|
||||
"id": 6,
|
||||
"options": {
|
||||
"colorMode": "value",
|
||||
"graphMode": "area",
|
||||
"justifyMode": "auto",
|
||||
"orientation": "auto",
|
||||
"reduceOptions": {
|
||||
"calcs": ["lastNotNull"],
|
||||
"fields": "",
|
||||
"values": false
|
||||
},
|
||||
"textMode": "auto"
|
||||
},
|
||||
"pluginVersion": "10.0.0",
|
||||
"targets": [
|
||||
{
|
||||
"datasource": { "type": "prometheus", "uid": "${datasource}" },
|
||||
"editorMode": "code",
|
||||
"expr": "sum(export_runs_in_progress{tenant=~\"$tenant\"})",
|
||||
"legendFormat": "In Progress",
|
||||
"range": true,
|
||||
"refId": "A"
|
||||
}
|
||||
],
|
||||
"title": "Runs In Progress",
|
||||
"type": "stat"
|
||||
},
|
||||
{
|
||||
"datasource": { "type": "prometheus", "uid": "${datasource}" },
|
||||
"fieldConfig": {
|
||||
"defaults": {
|
||||
"color": { "mode": "palette-classic" },
|
||||
"custom": {
|
||||
"axisCenteredZero": false,
|
||||
"axisColorMode": "text",
|
||||
"axisLabel": "",
|
||||
"axisPlacement": "auto",
|
||||
"barAlignment": 0,
|
||||
"drawStyle": "line",
|
||||
"fillOpacity": 10,
|
||||
"gradientMode": "none",
|
||||
"hideFrom": { "legend": false, "tooltip": false, "viz": false },
|
||||
"lineInterpolation": "linear",
|
||||
"lineWidth": 1,
|
||||
"pointSize": 5,
|
||||
"scaleDistribution": { "type": "linear" },
|
||||
"showPoints": "auto",
|
||||
"spanNulls": false,
|
||||
"stacking": { "group": "A", "mode": "none" },
|
||||
"thresholdsStyle": { "mode": "off" }
|
||||
},
|
||||
"mappings": [],
|
||||
"thresholds": {
|
||||
"mode": "absolute",
|
||||
"steps": [{ "color": "green", "value": null }]
|
||||
},
|
||||
"unit": "short"
|
||||
},
|
||||
"overrides": []
|
||||
},
|
||||
"gridPos": { "h": 8, "w": 12, "x": 0, "y": 5 },
|
||||
"id": 7,
|
||||
"options": {
|
||||
"legend": { "calcs": ["mean", "max"], "displayMode": "table", "placement": "bottom", "showLegend": true },
|
||||
"tooltip": { "mode": "multi", "sort": "desc" }
|
||||
},
|
||||
"targets": [
|
||||
{
|
||||
"datasource": { "type": "prometheus", "uid": "${datasource}" },
|
||||
"editorMode": "code",
|
||||
"expr": "sum by (export_type) (rate(export_runs_total{tenant=~\"$tenant\"}[5m]))",
|
||||
"legendFormat": "{{export_type}}",
|
||||
"range": true,
|
||||
"refId": "A"
|
||||
}
|
||||
],
|
||||
"title": "Export Runs by Type (rate/5m)",
|
||||
"type": "timeseries"
|
||||
},
|
||||
{
|
||||
"datasource": { "type": "prometheus", "uid": "${datasource}" },
|
||||
"fieldConfig": {
|
||||
"defaults": {
|
||||
"color": { "mode": "palette-classic" },
|
||||
"custom": {
|
||||
"axisCenteredZero": false,
|
||||
"axisColorMode": "text",
|
||||
"axisLabel": "",
|
||||
"axisPlacement": "auto",
|
||||
"barAlignment": 0,
|
||||
"drawStyle": "line",
|
||||
"fillOpacity": 10,
|
||||
"gradientMode": "none",
|
||||
"hideFrom": { "legend": false, "tooltip": false, "viz": false },
|
||||
"lineInterpolation": "linear",
|
||||
"lineWidth": 1,
|
||||
"pointSize": 5,
|
||||
"scaleDistribution": { "type": "linear" },
|
||||
"showPoints": "auto",
|
||||
"spanNulls": false,
|
||||
"stacking": { "group": "A", "mode": "none" },
|
||||
"thresholdsStyle": { "mode": "off" }
|
||||
},
|
||||
"mappings": [],
|
||||
"thresholds": {
|
||||
"mode": "absolute",
|
||||
"steps": [{ "color": "green", "value": null }]
|
||||
},
|
||||
"unit": "s"
|
||||
},
|
||||
"overrides": []
|
||||
},
|
||||
"gridPos": { "h": 8, "w": 12, "x": 12, "y": 5 },
|
||||
"id": 8,
|
||||
"options": {
|
||||
"legend": { "calcs": ["mean", "max", "p95"], "displayMode": "table", "placement": "bottom", "showLegend": true },
|
||||
"tooltip": { "mode": "multi", "sort": "desc" }
|
||||
},
|
||||
"targets": [
|
||||
{
|
||||
"datasource": { "type": "prometheus", "uid": "${datasource}" },
|
||||
"editorMode": "code",
|
||||
"expr": "histogram_quantile(0.50, sum by (le) (rate(export_run_duration_seconds_bucket{tenant=~\"$tenant\"}[5m])))",
|
||||
"legendFormat": "p50",
|
||||
"range": true,
|
||||
"refId": "A"
|
||||
},
|
||||
{
|
||||
"datasource": { "type": "prometheus", "uid": "${datasource}" },
|
||||
"editorMode": "code",
|
||||
"expr": "histogram_quantile(0.95, sum by (le) (rate(export_run_duration_seconds_bucket{tenant=~\"$tenant\"}[5m])))",
|
||||
"legendFormat": "p95",
|
||||
"range": true,
|
||||
"refId": "B"
|
||||
},
|
||||
{
|
||||
"datasource": { "type": "prometheus", "uid": "${datasource}" },
|
||||
"editorMode": "code",
|
||||
"expr": "histogram_quantile(0.99, sum by (le) (rate(export_run_duration_seconds_bucket{tenant=~\"$tenant\"}[5m])))",
|
||||
"legendFormat": "p99",
|
||||
"range": true,
|
||||
"refId": "C"
|
||||
}
|
||||
],
|
||||
"title": "Export Run Duration (latency percentiles)",
|
||||
"type": "timeseries"
|
||||
},
|
||||
{
|
||||
"collapsed": false,
|
||||
"gridPos": { "h": 1, "w": 24, "x": 0, "y": 13 },
|
||||
"id": 9,
|
||||
"panels": [],
|
||||
"title": "Artifacts & Bundle Sizes",
|
||||
"type": "row"
|
||||
},
|
||||
{
|
||||
"datasource": { "type": "prometheus", "uid": "${datasource}" },
|
||||
"fieldConfig": {
|
||||
"defaults": {
|
||||
"color": { "mode": "palette-classic" },
|
||||
"custom": {
|
||||
"axisCenteredZero": false,
|
||||
"axisColorMode": "text",
|
||||
"axisLabel": "",
|
||||
"axisPlacement": "auto",
|
||||
"barAlignment": 0,
|
||||
"drawStyle": "bars",
|
||||
"fillOpacity": 50,
|
||||
"gradientMode": "none",
|
||||
"hideFrom": { "legend": false, "tooltip": false, "viz": false },
|
||||
"lineInterpolation": "linear",
|
||||
"lineWidth": 1,
|
||||
"pointSize": 5,
|
||||
"scaleDistribution": { "type": "linear" },
|
||||
"showPoints": "never",
|
||||
"spanNulls": false,
|
||||
"stacking": { "group": "A", "mode": "normal" },
|
||||
"thresholdsStyle": { "mode": "off" }
|
||||
},
|
||||
"mappings": [],
|
||||
"thresholds": {
|
||||
"mode": "absolute",
|
||||
"steps": [{ "color": "green", "value": null }]
|
||||
},
|
||||
"unit": "short"
|
||||
},
|
||||
"overrides": []
|
||||
},
|
||||
"gridPos": { "h": 8, "w": 12, "x": 0, "y": 14 },
|
||||
"id": 10,
|
||||
"options": {
|
||||
"legend": { "calcs": ["sum"], "displayMode": "table", "placement": "bottom", "showLegend": true },
|
||||
"tooltip": { "mode": "multi", "sort": "desc" }
|
||||
},
|
||||
"targets": [
|
||||
{
|
||||
"datasource": { "type": "prometheus", "uid": "${datasource}" },
|
||||
"editorMode": "code",
|
||||
"expr": "sum by (artifact_type) (increase(export_artifacts_total{tenant=~\"$tenant\"}[1h]))",
|
||||
"legendFormat": "{{artifact_type}}",
|
||||
"range": true,
|
||||
"refId": "A"
|
||||
}
|
||||
],
|
||||
"title": "Artifacts Exported by Type (per hour)",
|
||||
"type": "timeseries"
|
||||
},
|
||||
{
|
||||
"datasource": { "type": "prometheus", "uid": "${datasource}" },
|
||||
"fieldConfig": {
|
||||
"defaults": {
|
||||
"color": { "mode": "palette-classic" },
|
||||
"custom": {
|
||||
"axisCenteredZero": false,
|
||||
"axisColorMode": "text",
|
||||
"axisLabel": "",
|
||||
"axisPlacement": "auto",
|
||||
"barAlignment": 0,
|
||||
"drawStyle": "line",
|
||||
"fillOpacity": 10,
|
||||
"gradientMode": "none",
|
||||
"hideFrom": { "legend": false, "tooltip": false, "viz": false },
|
||||
"lineInterpolation": "linear",
|
||||
"lineWidth": 1,
|
||||
"pointSize": 5,
|
||||
"scaleDistribution": { "type": "linear" },
|
||||
"showPoints": "auto",
|
||||
"spanNulls": false,
|
||||
"stacking": { "group": "A", "mode": "none" },
|
||||
"thresholdsStyle": { "mode": "off" }
|
||||
},
|
||||
"mappings": [],
|
||||
"thresholds": {
|
||||
"mode": "absolute",
|
||||
"steps": [{ "color": "green", "value": null }]
|
||||
},
|
||||
"unit": "bytes"
|
||||
},
|
||||
"overrides": []
|
||||
},
|
||||
"gridPos": { "h": 8, "w": 12, "x": 12, "y": 14 },
|
||||
"id": 11,
|
||||
"options": {
|
||||
"legend": { "calcs": ["mean", "max"], "displayMode": "table", "placement": "bottom", "showLegend": true },
|
||||
"tooltip": { "mode": "multi", "sort": "desc" }
|
||||
},
|
||||
"targets": [
|
||||
{
|
||||
"datasource": { "type": "prometheus", "uid": "${datasource}" },
|
||||
"editorMode": "code",
|
||||
"expr": "histogram_quantile(0.50, sum by (le, export_type) (rate(export_bundle_size_bytes_bucket{tenant=~\"$tenant\"}[5m])))",
|
||||
"legendFormat": "{{export_type}} p50",
|
||||
"range": true,
|
||||
"refId": "A"
|
||||
},
|
||||
{
|
||||
"datasource": { "type": "prometheus", "uid": "${datasource}" },
|
||||
"editorMode": "code",
|
||||
"expr": "histogram_quantile(0.95, sum by (le, export_type) (rate(export_bundle_size_bytes_bucket{tenant=~\"$tenant\"}[5m])))",
|
||||
"legendFormat": "{{export_type}} p95",
|
||||
"range": true,
|
||||
"refId": "B"
|
||||
}
|
||||
],
|
||||
"title": "Bundle Size Distribution by Type",
|
||||
"type": "timeseries"
|
||||
},
|
||||
{
|
||||
"collapsed": false,
|
||||
"gridPos": { "h": 1, "w": 24, "x": 0, "y": 22 },
|
||||
"id": 12,
|
||||
"panels": [],
|
||||
"title": "Error Analysis",
|
||||
"type": "row"
|
||||
},
|
||||
{
|
||||
"datasource": { "type": "prometheus", "uid": "${datasource}" },
|
||||
"fieldConfig": {
|
||||
"defaults": {
|
||||
"color": { "mode": "palette-classic" },
|
||||
"custom": {
|
||||
"hideFrom": { "legend": false, "tooltip": false, "viz": false }
|
||||
},
|
||||
"mappings": [],
|
||||
"unit": "short"
|
||||
},
|
||||
"overrides": []
|
||||
},
|
||||
"gridPos": { "h": 8, "w": 8, "x": 0, "y": 23 },
|
||||
"id": 13,
|
||||
"options": {
|
||||
"legend": { "displayMode": "table", "placement": "right", "showLegend": true },
|
||||
"pieType": "pie",
|
||||
"reduceOptions": { "calcs": ["lastNotNull"], "fields": "", "values": false },
|
||||
"tooltip": { "mode": "single", "sort": "none" }
|
||||
},
|
||||
"targets": [
|
||||
{
|
||||
"datasource": { "type": "prometheus", "uid": "${datasource}" },
|
||||
"editorMode": "code",
|
||||
"expr": "sum by (error_code) (increase(export_runs_failed_total{tenant=~\"$tenant\"}[$__range]))",
|
||||
"legendFormat": "{{error_code}}",
|
||||
"range": true,
|
||||
"refId": "A"
|
||||
}
|
||||
],
|
||||
"title": "Failures by Error Code",
|
||||
"type": "piechart"
|
||||
},
|
||||
{
|
||||
"datasource": { "type": "prometheus", "uid": "${datasource}" },
|
||||
"fieldConfig": {
|
||||
"defaults": {
|
||||
"color": { "mode": "palette-classic" },
|
||||
"custom": {
|
||||
"axisCenteredZero": false,
|
||||
"axisColorMode": "text",
|
||||
"axisLabel": "",
|
||||
"axisPlacement": "auto",
|
||||
"barAlignment": 0,
|
||||
"drawStyle": "line",
|
||||
"fillOpacity": 0,
|
||||
"gradientMode": "none",
|
||||
"hideFrom": { "legend": false, "tooltip": false, "viz": false },
|
||||
"lineInterpolation": "linear",
|
||||
"lineWidth": 2,
|
||||
"pointSize": 5,
|
||||
"scaleDistribution": { "type": "linear" },
|
||||
"showPoints": "never",
|
||||
"spanNulls": false,
|
||||
"stacking": { "group": "A", "mode": "none" },
|
||||
"thresholdsStyle": { "mode": "line" }
|
||||
},
|
||||
"mappings": [],
|
||||
"thresholds": {
|
||||
"mode": "absolute",
|
||||
"steps": [
|
||||
{ "color": "green", "value": null },
|
||||
{ "color": "red", "value": 0.01 }
|
||||
]
|
||||
},
|
||||
"unit": "percentunit"
|
||||
},
|
||||
"overrides": []
|
||||
},
|
||||
"gridPos": { "h": 8, "w": 16, "x": 8, "y": 23 },
|
||||
"id": 14,
|
||||
"options": {
|
||||
"legend": { "calcs": ["mean", "max"], "displayMode": "table", "placement": "bottom", "showLegend": true },
|
||||
"tooltip": { "mode": "multi", "sort": "desc" }
|
||||
},
|
||||
"targets": [
|
||||
{
|
||||
"datasource": { "type": "prometheus", "uid": "${datasource}" },
|
||||
"editorMode": "code",
|
||||
"expr": "sum(rate(export_runs_failed_total{tenant=~\"$tenant\"}[5m])) / sum(rate(export_runs_total{tenant=~\"$tenant\"}[5m]))",
|
||||
"legendFormat": "Error Rate",
|
||||
"range": true,
|
||||
"refId": "A"
|
||||
}
|
||||
],
|
||||
"title": "Error Rate (5m window)",
|
||||
"type": "timeseries"
|
||||
}
|
||||
],
|
||||
"refresh": "30s",
|
||||
"schemaVersion": 38,
|
||||
"style": "dark",
|
||||
"tags": ["export-center", "stellaops"],
|
||||
"templating": {
|
||||
"list": [
|
||||
{
|
||||
"current": {},
|
||||
"hide": 0,
|
||||
"includeAll": false,
|
||||
"multi": false,
|
||||
"name": "datasource",
|
||||
"options": [],
|
||||
"query": "prometheus",
|
||||
"refresh": 1,
|
||||
"regex": "",
|
||||
"skipUrlSync": false,
|
||||
"type": "datasource"
|
||||
},
|
||||
{
|
||||
"allValue": ".*",
|
||||
"current": {},
|
||||
"datasource": { "type": "prometheus", "uid": "${datasource}" },
|
||||
"definition": "label_values(export_runs_total, tenant)",
|
||||
"hide": 0,
|
||||
"includeAll": true,
|
||||
"multi": true,
|
||||
"name": "tenant",
|
||||
"options": [],
|
||||
"query": { "query": "label_values(export_runs_total, tenant)", "refId": "StandardVariableQuery" },
|
||||
"refresh": 2,
|
||||
"regex": "",
|
||||
"skipUrlSync": false,
|
||||
"sort": 1,
|
||||
"type": "query"
|
||||
}
|
||||
]
|
||||
},
|
||||
"time": { "from": "now-6h", "to": "now" },
|
||||
"timepicker": {},
|
||||
"timezone": "utc",
|
||||
"title": "ExportCenter Service",
|
||||
"uid": "export-center-overview",
|
||||
"version": 1,
|
||||
"weekStart": ""
|
||||
}
|
||||
@@ -1,92 +0,0 @@
|
||||
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}
|
||||
otlphttp/tempo:
|
||||
endpoint: ${STELLAOPS_TEMPO_ENDPOINT:https://stellaops-tempo:3200}
|
||||
compression: gzip
|
||||
tls:
|
||||
ca_file: ${STELLAOPS_TEMPO_TLS_CA_FILE:/etc/otel-collector/tls/ca.crt}
|
||||
cert_file: ${STELLAOPS_TEMPO_TLS_CERT_FILE:/etc/otel-collector/tls/client.crt}
|
||||
key_file: ${STELLAOPS_TEMPO_TLS_KEY_FILE:/etc/otel-collector/tls/client.key}
|
||||
insecure_skip_verify: false
|
||||
headers:
|
||||
"X-Scope-OrgID": ${STELLAOPS_TENANT_ID:unknown}
|
||||
loki/tenant:
|
||||
endpoint: ${STELLAOPS_LOKI_ENDPOINT:https://stellaops-loki:3100/loki/api/v1/push}
|
||||
tenant_id: ${STELLAOPS_TENANT_ID:unknown}
|
||||
tls:
|
||||
ca_file: ${STELLAOPS_LOKI_TLS_CA_FILE:/etc/otel-collector/tls/ca.crt}
|
||||
cert_file: ${STELLAOPS_LOKI_TLS_CERT_FILE:/etc/otel-collector/tls/client.crt}
|
||||
key_file: ${STELLAOPS_LOKI_TLS_KEY_FILE:/etc/otel-collector/tls/client.key}
|
||||
insecure_skip_verify: false
|
||||
default_labels_enabled:
|
||||
exporter: false
|
||||
job: false
|
||||
instance: false
|
||||
format: json
|
||||
drain_interval: 5s
|
||||
queue:
|
||||
enabled: true
|
||||
queue_size: 1024
|
||||
retry_on_failure: true
|
||||
|
||||
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, otlphttp/tempo]
|
||||
metrics:
|
||||
receivers: [otlp]
|
||||
processors: [attributes/tenant-tag, batch]
|
||||
exporters: [logging, prometheus]
|
||||
logs:
|
||||
receivers: [otlp]
|
||||
processors: [attributes/tenant-tag, batch]
|
||||
exporters: [logging, loki/tenant]
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user