ci(titan-iac): apply supply-chain waiver ledger
This commit is contained in:
parent
e6bb015ef2
commit
2ded2eb23d
18
Jenkinsfile
vendored
18
Jenkinsfile
vendored
@ -140,7 +140,7 @@ PY
|
|||||||
set -euo pipefail
|
set -euo pipefail
|
||||||
mkdir -p build
|
mkdir -p build
|
||||||
set +e
|
set +e
|
||||||
trivy fs --cache-dir "${TRIVY_CACHE_DIR}" --skip-db-update --timeout 5m --no-progress --format json --output build/trivy-fs.json --scanners vuln,secret,misconfig --severity HIGH,CRITICAL .
|
trivy fs --cache-dir "${TRIVY_CACHE_DIR}" --skip-db-update --skip-files clusters/atlas/flux-system/gotk-components.yaml --timeout 5m --no-progress --format json --output build/trivy-fs.json --scanners vuln,secret,misconfig --severity HIGH,CRITICAL .
|
||||||
trivy_rc=$?
|
trivy_rc=$?
|
||||||
set -e
|
set -e
|
||||||
if [ ! -s build/trivy-fs.json ]; then
|
if [ ! -s build/trivy-fs.json ]; then
|
||||||
@ -149,23 +149,15 @@ PY
|
|||||||
EOF
|
EOF
|
||||||
exit 0
|
exit 0
|
||||||
fi
|
fi
|
||||||
critical="$(jq '[.Results[]? | .Vulnerabilities[]? | select(.Severity=="CRITICAL")] | length' build/trivy-fs.json)"
|
|
||||||
high="$(jq '[.Results[]? | .Vulnerabilities[]? | select(.Severity=="HIGH")] | length' build/trivy-fs.json)"
|
|
||||||
secrets="$(jq '[.Results[]? | .Secrets[]?] | length' build/trivy-fs.json)"
|
|
||||||
misconfigs="$(jq '[.Results[]? | .Misconfigurations[]? | select(.Status=="FAIL" and (.Severity=="CRITICAL" or .Severity=="HIGH"))] | length' build/trivy-fs.json)"
|
|
||||||
status=ok
|
|
||||||
compliant=true
|
|
||||||
if [ "${critical}" -gt 0 ] || [ "${secrets}" -gt 0 ] || [ "${misconfigs}" -gt 0 ]; then
|
|
||||||
status=failed
|
|
||||||
compliant=false
|
|
||||||
fi
|
|
||||||
jq -n --arg status "${status}" --argjson compliant "${compliant}" --argjson critical "${critical}" --argjson high "${high}" --argjson secrets "${secrets}" --argjson misconfigs "${misconfigs}" --argjson trivy_rc "${trivy_rc}" \
|
|
||||||
'{status:$status, compliant:$compliant, category:"artifact_security", scan_type:"filesystem", scanner:"trivy", critical_vulnerabilities:$critical, high_vulnerabilities:$high, secrets:$secrets, high_or_critical_misconfigurations:$misconfigs, trivy_rc:$trivy_rc, high_vulnerability_policy:"observe"}' > build/ironbank-compliance.json
|
|
||||||
'''
|
'''
|
||||||
}
|
}
|
||||||
sh '''
|
sh '''
|
||||||
set -eu
|
set -eu
|
||||||
mkdir -p build
|
mkdir -p build
|
||||||
|
if [ -s build/trivy-fs.json ]; then
|
||||||
|
python3 ci/scripts/supply_chain_report.py --trivy-json build/trivy-fs.json --waivers ci/titan-iac-trivy-waivers.json --output build/ironbank-compliance.json
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
python3 - <<'PY'
|
python3 - <<'PY'
|
||||||
import json
|
import json
|
||||||
import os
|
import os
|
||||||
|
|||||||
@ -139,7 +139,7 @@ PY
|
|||||||
set -euo pipefail
|
set -euo pipefail
|
||||||
mkdir -p build
|
mkdir -p build
|
||||||
set +e
|
set +e
|
||||||
trivy fs --cache-dir "${TRIVY_CACHE_DIR}" --skip-db-update --timeout 5m --no-progress --format json --output build/trivy-fs.json --scanners vuln,secret,misconfig --severity HIGH,CRITICAL .
|
trivy fs --cache-dir "${TRIVY_CACHE_DIR}" --skip-db-update --skip-files clusters/atlas/flux-system/gotk-components.yaml --timeout 5m --no-progress --format json --output build/trivy-fs.json --scanners vuln,secret,misconfig --severity HIGH,CRITICAL .
|
||||||
trivy_rc=$?
|
trivy_rc=$?
|
||||||
set -e
|
set -e
|
||||||
if [ ! -s build/trivy-fs.json ]; then
|
if [ ! -s build/trivy-fs.json ]; then
|
||||||
@ -148,23 +148,15 @@ PY
|
|||||||
EOF
|
EOF
|
||||||
exit 0
|
exit 0
|
||||||
fi
|
fi
|
||||||
critical="$(jq '[.Results[]? | .Vulnerabilities[]? | select(.Severity=="CRITICAL")] | length' build/trivy-fs.json)"
|
|
||||||
high="$(jq '[.Results[]? | .Vulnerabilities[]? | select(.Severity=="HIGH")] | length' build/trivy-fs.json)"
|
|
||||||
secrets="$(jq '[.Results[]? | .Secrets[]?] | length' build/trivy-fs.json)"
|
|
||||||
misconfigs="$(jq '[.Results[]? | .Misconfigurations[]? | select(.Status=="FAIL" and (.Severity=="CRITICAL" or .Severity=="HIGH"))] | length' build/trivy-fs.json)"
|
|
||||||
status=ok
|
|
||||||
compliant=true
|
|
||||||
if [ "${critical}" -gt 0 ] || [ "${secrets}" -gt 0 ] || [ "${misconfigs}" -gt 0 ]; then
|
|
||||||
status=failed
|
|
||||||
compliant=false
|
|
||||||
fi
|
|
||||||
jq -n --arg status "${status}" --argjson compliant "${compliant}" --argjson critical "${critical}" --argjson high "${high}" --argjson secrets "${secrets}" --argjson misconfigs "${misconfigs}" --argjson trivy_rc "${trivy_rc}" \
|
|
||||||
'{status:$status, compliant:$compliant, category:"artifact_security", scan_type:"filesystem", scanner:"trivy", critical_vulnerabilities:$critical, high_vulnerabilities:$high, secrets:$secrets, high_or_critical_misconfigurations:$misconfigs, trivy_rc:$trivy_rc, high_vulnerability_policy:"observe"}' > build/ironbank-compliance.json
|
|
||||||
'''
|
'''
|
||||||
}
|
}
|
||||||
sh '''
|
sh '''
|
||||||
set -eu
|
set -eu
|
||||||
mkdir -p build
|
mkdir -p build
|
||||||
|
if [ -s build/trivy-fs.json ]; then
|
||||||
|
python3 ci/scripts/supply_chain_report.py --trivy-json build/trivy-fs.json --waivers ci/titan-iac-trivy-waivers.json --output build/ironbank-compliance.json
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
python3 - <<'PY'
|
python3 - <<'PY'
|
||||||
import json
|
import json
|
||||||
import os
|
import os
|
||||||
|
|||||||
173
ci/scripts/supply_chain_report.py
Normal file
173
ci/scripts/supply_chain_report.py
Normal file
@ -0,0 +1,173 @@
|
|||||||
|
"""Build a titan-iac supply-chain compliance report from Trivy evidence."""
|
||||||
|
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
import argparse
|
||||||
|
import datetime as dt
|
||||||
|
import json
|
||||||
|
from pathlib import Path
|
||||||
|
from typing import Any
|
||||||
|
|
||||||
|
|
||||||
|
FAIL_SEVERITIES = {"HIGH", "CRITICAL"}
|
||||||
|
|
||||||
|
|
||||||
|
def _read_json(path: Path) -> dict[str, Any]:
|
||||||
|
"""Read a JSON object from disk for use as pipeline evidence."""
|
||||||
|
payload = json.loads(path.read_text(encoding="utf-8"))
|
||||||
|
if not isinstance(payload, dict):
|
||||||
|
raise ValueError(f"{path} must contain a JSON object")
|
||||||
|
return payload
|
||||||
|
|
||||||
|
|
||||||
|
def _parse_day(raw: str | None) -> dt.date | None:
|
||||||
|
"""Parse an ISO day while letting optional waiver dates stay optional."""
|
||||||
|
if not raw:
|
||||||
|
return None
|
||||||
|
return dt.date.fromisoformat(raw)
|
||||||
|
|
||||||
|
|
||||||
|
def _today(override: str | None = None) -> dt.date:
|
||||||
|
"""Return the policy day so tests can pin expiry behavior."""
|
||||||
|
return _parse_day(override) or dt.date.today()
|
||||||
|
|
||||||
|
|
||||||
|
def _load_waiver_pairs(path: Path | None, policy_day: dt.date) -> tuple[set[tuple[str, str]], int]:
|
||||||
|
"""Return active ``(misconfiguration id, target)`` waivers and expired count."""
|
||||||
|
if path is None or not path.exists():
|
||||||
|
return set(), 0
|
||||||
|
|
||||||
|
payload = _read_json(path)
|
||||||
|
default_expires_at = payload.get("default_expires_at")
|
||||||
|
active: set[tuple[str, str]] = set()
|
||||||
|
expired = 0
|
||||||
|
|
||||||
|
for entry in payload.get("misconfigurations", []):
|
||||||
|
if not isinstance(entry, dict):
|
||||||
|
continue
|
||||||
|
misconfiguration_id = str(entry.get("id") or "").strip()
|
||||||
|
if not misconfiguration_id:
|
||||||
|
continue
|
||||||
|
expires_at = _parse_day(str(entry.get("expires_at") or default_expires_at or ""))
|
||||||
|
targets = entry.get("targets", [])
|
||||||
|
if not isinstance(targets, list):
|
||||||
|
continue
|
||||||
|
|
||||||
|
if expires_at and expires_at < policy_day:
|
||||||
|
expired += len(targets)
|
||||||
|
continue
|
||||||
|
|
||||||
|
# Waivers are target-specific so a new unsafe manifest fails until it is
|
||||||
|
# either fixed or deliberately accepted with a fresh expiration.
|
||||||
|
for target in targets:
|
||||||
|
if isinstance(target, str) and target:
|
||||||
|
active.add((misconfiguration_id, target))
|
||||||
|
|
||||||
|
return active, expired
|
||||||
|
|
||||||
|
|
||||||
|
def _iter_failed_misconfigurations(payload: dict[str, Any]):
|
||||||
|
"""Yield failed high/critical Trivy misconfiguration records."""
|
||||||
|
for result in payload.get("Results", []):
|
||||||
|
if not isinstance(result, dict):
|
||||||
|
continue
|
||||||
|
target = str(result.get("Target") or "")
|
||||||
|
for item in result.get("Misconfigurations") or []:
|
||||||
|
if not isinstance(item, dict):
|
||||||
|
continue
|
||||||
|
if item.get("Status") != "FAIL":
|
||||||
|
continue
|
||||||
|
if str(item.get("Severity") or "").upper() not in FAIL_SEVERITIES:
|
||||||
|
continue
|
||||||
|
yield target, item
|
||||||
|
|
||||||
|
|
||||||
|
def _count_vulnerabilities(payload: dict[str, Any], severity: str) -> int:
|
||||||
|
"""Count Trivy vulnerabilities at a specific severity."""
|
||||||
|
count = 0
|
||||||
|
for result in payload.get("Results", []):
|
||||||
|
if not isinstance(result, dict):
|
||||||
|
continue
|
||||||
|
for item in result.get("Vulnerabilities") or []:
|
||||||
|
if isinstance(item, dict) and str(item.get("Severity") or "").upper() == severity:
|
||||||
|
count += 1
|
||||||
|
return count
|
||||||
|
|
||||||
|
|
||||||
|
def _count_secrets(payload: dict[str, Any]) -> int:
|
||||||
|
"""Count detected secrets in the Trivy filesystem report."""
|
||||||
|
count = 0
|
||||||
|
for result in payload.get("Results", []):
|
||||||
|
if isinstance(result, dict):
|
||||||
|
count += len(result.get("Secrets") or [])
|
||||||
|
return count
|
||||||
|
|
||||||
|
|
||||||
|
def build_report(
|
||||||
|
trivy_payload: dict[str, Any],
|
||||||
|
waiver_path: Path | None = None,
|
||||||
|
today_override: str | None = None,
|
||||||
|
) -> dict[str, Any]:
|
||||||
|
"""Build the compliance summary consumed by the quality gate."""
|
||||||
|
policy_day = _today(today_override)
|
||||||
|
active_waivers, expired_waivers = _load_waiver_pairs(waiver_path, policy_day)
|
||||||
|
|
||||||
|
open_misconfigs: list[dict[str, str]] = []
|
||||||
|
waived_misconfigs = 0
|
||||||
|
for target, item in _iter_failed_misconfigurations(trivy_payload):
|
||||||
|
misconfiguration_id = str(item.get("ID") or "")
|
||||||
|
if (misconfiguration_id, target) in active_waivers:
|
||||||
|
waived_misconfigs += 1
|
||||||
|
continue
|
||||||
|
open_misconfigs.append(
|
||||||
|
{
|
||||||
|
"id": misconfiguration_id,
|
||||||
|
"target": target,
|
||||||
|
"severity": str(item.get("Severity") or ""),
|
||||||
|
"title": str(item.get("Title") or ""),
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
critical = _count_vulnerabilities(trivy_payload, "CRITICAL")
|
||||||
|
high = _count_vulnerabilities(trivy_payload, "HIGH")
|
||||||
|
secrets = _count_secrets(trivy_payload)
|
||||||
|
status = "ok" if critical == 0 and secrets == 0 and not open_misconfigs else "failed"
|
||||||
|
|
||||||
|
return {
|
||||||
|
"status": status,
|
||||||
|
"compliant": status == "ok",
|
||||||
|
"category": "artifact_security",
|
||||||
|
"scan_type": "filesystem",
|
||||||
|
"scanner": "trivy",
|
||||||
|
"critical_vulnerabilities": critical,
|
||||||
|
"high_vulnerabilities": high,
|
||||||
|
"high_vulnerability_policy": "observe",
|
||||||
|
"secrets": secrets,
|
||||||
|
"high_or_critical_misconfigurations": len(open_misconfigs),
|
||||||
|
"waived_misconfigurations": waived_misconfigs,
|
||||||
|
"expired_waivers": expired_waivers,
|
||||||
|
"waiver_file": str(waiver_path) if waiver_path else "",
|
||||||
|
"open_misconfiguration_examples": open_misconfigs[:20],
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def main(argv: list[str] | None = None) -> int:
|
||||||
|
"""CLI entrypoint used by Jenkins after the Trivy scan completes."""
|
||||||
|
parser = argparse.ArgumentParser(description=__doc__)
|
||||||
|
parser.add_argument("--trivy-json", required=True)
|
||||||
|
parser.add_argument("--waivers")
|
||||||
|
parser.add_argument("--output", required=True)
|
||||||
|
parser.add_argument("--today")
|
||||||
|
args = parser.parse_args(argv)
|
||||||
|
|
||||||
|
trivy_payload = _read_json(Path(args.trivy_json))
|
||||||
|
waiver_path = Path(args.waivers) if args.waivers else None
|
||||||
|
report = build_report(trivy_payload, waiver_path=waiver_path, today_override=args.today)
|
||||||
|
output_path = Path(args.output)
|
||||||
|
output_path.parent.mkdir(parents=True, exist_ok=True)
|
||||||
|
output_path.write_text(json.dumps(report, indent=2, sort_keys=True) + "\n", encoding="utf-8")
|
||||||
|
return 0
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__": # pragma: no cover
|
||||||
|
raise SystemExit(main())
|
||||||
401
ci/titan-iac-trivy-waivers.json
Normal file
401
ci/titan-iac-trivy-waivers.json
Normal file
@ -0,0 +1,401 @@
|
|||||||
|
{
|
||||||
|
"version": 1,
|
||||||
|
"generated_from": "Jenkins titan-iac build 225 Trivy filesystem scan",
|
||||||
|
"default_expires_at": "2026-05-22",
|
||||||
|
"ticket": "atlas-quality-wave-k8s-hardening",
|
||||||
|
"default_reason": "Existing Kubernetes manifest hardening baseline accepted only for the first quality-gate rollout; fix or renew explicitly before expiry.",
|
||||||
|
"misconfigurations": [
|
||||||
|
{
|
||||||
|
"id": "DS-0002",
|
||||||
|
"targets": [
|
||||||
|
"dockerfiles/Dockerfile.ananke-node-helper"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "KSV-0009",
|
||||||
|
"targets": [
|
||||||
|
"services/mailu/vip-controller.yaml",
|
||||||
|
"services/maintenance/k3s-agent-restart-daemonset.yaml"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "KSV-0010",
|
||||||
|
"targets": [
|
||||||
|
"services/maintenance/k3s-agent-restart-daemonset.yaml",
|
||||||
|
"services/maintenance/metis-sentinel-amd64-daemonset.yaml",
|
||||||
|
"services/maintenance/metis-sentinel-arm64-daemonset.yaml",
|
||||||
|
"services/monitoring/jetson-tegrastats-exporter.yaml"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "KSV-0014",
|
||||||
|
"targets": [
|
||||||
|
"infrastructure/cert-manager/cleanup/cert-manager-cleanup-job.yaml",
|
||||||
|
"infrastructure/core/ntp-sync-daemonset.yaml",
|
||||||
|
"infrastructure/longhorn/adopt/longhorn-helm-adopt-job.yaml",
|
||||||
|
"infrastructure/longhorn/core/longhorn-disk-tags-ensure-job.yaml",
|
||||||
|
"infrastructure/longhorn/core/longhorn-settings-ensure-job.yaml",
|
||||||
|
"infrastructure/longhorn/core/vault-sync-deployment.yaml",
|
||||||
|
"infrastructure/longhorn/ui-ingress/oauth2-proxy-longhorn.yaml",
|
||||||
|
"infrastructure/modules/profiles/components/device-plugin-jetson/daemonset.yaml",
|
||||||
|
"infrastructure/modules/profiles/components/device-plugin-minipc/daemonset.yaml",
|
||||||
|
"infrastructure/modules/profiles/components/device-plugin-tethys/daemonset.yaml",
|
||||||
|
"infrastructure/postgres/statefulset.yaml",
|
||||||
|
"infrastructure/vault-csi/vault-csi-provider.yaml",
|
||||||
|
"services/ai-llm/deployment.yaml",
|
||||||
|
"services/bstein-dev-home/backend-deployment.yaml",
|
||||||
|
"services/bstein-dev-home/chat-ai-gateway-deployment.yaml",
|
||||||
|
"services/bstein-dev-home/frontend-deployment.yaml",
|
||||||
|
"services/bstein-dev-home/oneoffs/migrations/portal-migrate-job.yaml",
|
||||||
|
"services/bstein-dev-home/oneoffs/portal-onboarding-e2e-test-job.yaml",
|
||||||
|
"services/bstein-dev-home/vault-sync-deployment.yaml",
|
||||||
|
"services/bstein-dev-home/vaultwarden-cred-sync-cronjob.yaml",
|
||||||
|
"services/comms/atlasbot-deployment.yaml",
|
||||||
|
"services/comms/coturn.yaml",
|
||||||
|
"services/comms/element-call-deployment.yaml",
|
||||||
|
"services/comms/guest-name-job.yaml",
|
||||||
|
"services/comms/guest-register-deployment.yaml",
|
||||||
|
"services/comms/livekit-token-deployment.yaml",
|
||||||
|
"services/comms/livekit.yaml",
|
||||||
|
"services/comms/mas-deployment.yaml",
|
||||||
|
"services/comms/oneoffs/bstein-force-leave-job.yaml",
|
||||||
|
"services/comms/oneoffs/comms-secrets-ensure-job.yaml",
|
||||||
|
"services/comms/oneoffs/mas-admin-client-secret-ensure-job.yaml",
|
||||||
|
"services/comms/oneoffs/mas-db-ensure-job.yaml",
|
||||||
|
"services/comms/oneoffs/mas-local-users-ensure-job.yaml",
|
||||||
|
"services/comms/oneoffs/othrys-kick-numeric-job.yaml",
|
||||||
|
"services/comms/oneoffs/synapse-admin-ensure-job.yaml",
|
||||||
|
"services/comms/oneoffs/synapse-seeder-admin-ensure-job.yaml",
|
||||||
|
"services/comms/oneoffs/synapse-signingkey-ensure-job.yaml",
|
||||||
|
"services/comms/oneoffs/synapse-user-seed-job.yaml",
|
||||||
|
"services/comms/pin-othrys-job.yaml",
|
||||||
|
"services/comms/reset-othrys-room-job.yaml",
|
||||||
|
"services/comms/seed-othrys-room.yaml",
|
||||||
|
"services/comms/vault-sync-deployment.yaml",
|
||||||
|
"services/comms/wellknown.yaml",
|
||||||
|
"services/crypto/monerod/deployment.yaml",
|
||||||
|
"services/crypto/wallet-monero-temp/deployment.yaml",
|
||||||
|
"services/crypto/xmr-miner/deployment.yaml",
|
||||||
|
"services/crypto/xmr-miner/vault-sync-deployment.yaml",
|
||||||
|
"services/crypto/xmr-miner/xmrig-daemonset.yaml",
|
||||||
|
"services/finance/actual-budget-deployment.yaml",
|
||||||
|
"services/finance/firefly-cronjob.yaml",
|
||||||
|
"services/finance/firefly-deployment.yaml",
|
||||||
|
"services/finance/firefly-user-sync-cronjob.yaml",
|
||||||
|
"services/finance/oneoffs/finance-secrets-ensure-job.yaml",
|
||||||
|
"services/gitea/deployment.yaml",
|
||||||
|
"services/harbor/vault-sync-deployment.yaml",
|
||||||
|
"services/health/wger-admin-ensure-cronjob.yaml",
|
||||||
|
"services/health/wger-deployment.yaml",
|
||||||
|
"services/health/wger-user-sync-cronjob.yaml",
|
||||||
|
"services/jellyfin/deployment.yaml",
|
||||||
|
"services/jellyfin/loader.yaml",
|
||||||
|
"services/jenkins/deployment.yaml",
|
||||||
|
"services/jenkins/vault-sync-deployment.yaml",
|
||||||
|
"services/keycloak/deployment.yaml",
|
||||||
|
"services/keycloak/oneoffs/actual-oidc-secret-ensure-job.yaml",
|
||||||
|
"services/keycloak/oneoffs/harbor-oidc-secret-ensure-job.yaml",
|
||||||
|
"services/keycloak/oneoffs/ldap-federation-job.yaml",
|
||||||
|
"services/keycloak/oneoffs/logs-oidc-secret-ensure-job.yaml",
|
||||||
|
"services/keycloak/oneoffs/mas-secrets-ensure-job.yaml",
|
||||||
|
"services/keycloak/oneoffs/metis-oidc-secret-ensure-job.yaml",
|
||||||
|
"services/keycloak/oneoffs/metis-ssh-keys-secret-ensure-job.yaml",
|
||||||
|
"services/keycloak/oneoffs/portal-admin-client-secret-ensure-job.yaml",
|
||||||
|
"services/keycloak/oneoffs/portal-e2e-client-job.yaml",
|
||||||
|
"services/keycloak/oneoffs/portal-e2e-execute-actions-email-test-job.yaml",
|
||||||
|
"services/keycloak/oneoffs/portal-e2e-target-client-job.yaml",
|
||||||
|
"services/keycloak/oneoffs/portal-e2e-token-exchange-permissions-job.yaml",
|
||||||
|
"services/keycloak/oneoffs/portal-e2e-token-exchange-test-job.yaml",
|
||||||
|
"services/keycloak/oneoffs/quality-oidc-secret-ensure-job.yaml",
|
||||||
|
"services/keycloak/oneoffs/realm-settings-job.yaml",
|
||||||
|
"services/keycloak/oneoffs/soteria-oidc-secret-ensure-job.yaml",
|
||||||
|
"services/keycloak/oneoffs/synapse-oidc-secret-ensure-job.yaml",
|
||||||
|
"services/keycloak/oneoffs/user-overrides-job.yaml",
|
||||||
|
"services/keycloak/oneoffs/vault-oidc-secret-ensure-job.yaml",
|
||||||
|
"services/keycloak/vault-sync-deployment.yaml",
|
||||||
|
"services/logging/node-image-gc-rpi4-daemonset.yaml",
|
||||||
|
"services/logging/node-image-prune-rpi5-daemonset.yaml",
|
||||||
|
"services/logging/node-log-rotation-daemonset.yaml",
|
||||||
|
"services/logging/oauth2-proxy.yaml",
|
||||||
|
"services/logging/oneoffs/opensearch-dashboards-setup-job.yaml",
|
||||||
|
"services/logging/oneoffs/opensearch-ism-job.yaml",
|
||||||
|
"services/logging/oneoffs/opensearch-observability-setup-job.yaml",
|
||||||
|
"services/logging/opensearch-prune-cronjob.yaml",
|
||||||
|
"services/logging/vault-sync-deployment.yaml",
|
||||||
|
"services/mailu/mailu-sync-cronjob.yaml",
|
||||||
|
"services/mailu/mailu-sync-listener.yaml",
|
||||||
|
"services/mailu/oneoffs/mailu-sync-job.yaml",
|
||||||
|
"services/mailu/vault-sync-deployment.yaml",
|
||||||
|
"services/mailu/vip-controller.yaml",
|
||||||
|
"services/maintenance/ariadne-deployment.yaml",
|
||||||
|
"services/maintenance/disable-k3s-traefik-daemonset.yaml",
|
||||||
|
"services/maintenance/image-sweeper-cronjob.yaml",
|
||||||
|
"services/maintenance/k3s-agent-restart-daemonset.yaml",
|
||||||
|
"services/maintenance/metis-deployment.yaml",
|
||||||
|
"services/maintenance/metis-k3s-token-sync-cronjob.yaml",
|
||||||
|
"services/maintenance/metis-sentinel-amd64-daemonset.yaml",
|
||||||
|
"services/maintenance/metis-sentinel-arm64-daemonset.yaml",
|
||||||
|
"services/maintenance/node-image-sweeper-daemonset.yaml",
|
||||||
|
"services/maintenance/node-nofile-daemonset.yaml",
|
||||||
|
"services/maintenance/oauth2-proxy-metis.yaml",
|
||||||
|
"services/maintenance/oauth2-proxy-soteria.yaml",
|
||||||
|
"services/maintenance/oneoffs/ariadne-migrate-job.yaml",
|
||||||
|
"services/maintenance/oneoffs/k3s-traefik-cleanup-job.yaml",
|
||||||
|
"services/maintenance/oneoffs/titan-24-rootfs-sweep-job.yaml",
|
||||||
|
"services/maintenance/pod-cleaner-cronjob.yaml",
|
||||||
|
"services/maintenance/soteria-deployment.yaml",
|
||||||
|
"services/maintenance/vault-sync-deployment.yaml",
|
||||||
|
"services/monitoring/dcgm-exporter.yaml",
|
||||||
|
"services/monitoring/jetson-tegrastats-exporter.yaml",
|
||||||
|
"services/monitoring/oneoffs/grafana-org-bootstrap.yaml",
|
||||||
|
"services/monitoring/oneoffs/grafana-user-dedupe-job.yaml",
|
||||||
|
"services/monitoring/platform-quality-gateway-deployment.yaml",
|
||||||
|
"services/monitoring/platform-quality-suite-probe-cronjob.yaml",
|
||||||
|
"services/monitoring/postmark-exporter-deployment.yaml",
|
||||||
|
"services/monitoring/vault-sync-deployment.yaml",
|
||||||
|
"services/nextcloud-mail-sync/cronjob.yaml",
|
||||||
|
"services/nextcloud/collabora.yaml",
|
||||||
|
"services/nextcloud/cronjob.yaml",
|
||||||
|
"services/nextcloud/deployment.yaml",
|
||||||
|
"services/nextcloud/maintenance-cronjob.yaml",
|
||||||
|
"services/oauth2-proxy/deployment.yaml",
|
||||||
|
"services/openldap/statefulset.yaml",
|
||||||
|
"services/outline/deployment.yaml",
|
||||||
|
"services/outline/redis-deployment.yaml",
|
||||||
|
"services/pegasus/deployment.yaml",
|
||||||
|
"services/pegasus/vault-sync-deployment.yaml",
|
||||||
|
"services/planka/deployment.yaml",
|
||||||
|
"services/quality/oauth2-proxy-sonarqube.yaml",
|
||||||
|
"services/quality/sonarqube-deployment.yaml",
|
||||||
|
"services/quality/sonarqube-exporter-deployment.yaml",
|
||||||
|
"services/sui-metrics/base/deployment.yaml",
|
||||||
|
"services/typhon/vault-sync-deployment.yaml",
|
||||||
|
"services/vault/k8s-auth-config-cronjob.yaml",
|
||||||
|
"services/vault/oidc-config-cronjob.yaml",
|
||||||
|
"services/vault/statefulset.yaml",
|
||||||
|
"services/vaultwarden/deployment.yaml"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "KSV-0017",
|
||||||
|
"targets": [
|
||||||
|
"infrastructure/modules/profiles/components/device-plugin-jetson/daemonset.yaml",
|
||||||
|
"infrastructure/modules/profiles/components/device-plugin-minipc/daemonset.yaml",
|
||||||
|
"infrastructure/modules/profiles/components/device-plugin-tethys/daemonset.yaml",
|
||||||
|
"services/logging/node-image-gc-rpi4-daemonset.yaml",
|
||||||
|
"services/logging/node-image-prune-rpi5-daemonset.yaml",
|
||||||
|
"services/logging/node-log-rotation-daemonset.yaml",
|
||||||
|
"services/maintenance/disable-k3s-traefik-daemonset.yaml",
|
||||||
|
"services/maintenance/image-sweeper-cronjob.yaml",
|
||||||
|
"services/maintenance/k3s-agent-restart-daemonset.yaml",
|
||||||
|
"services/maintenance/metis-deployment.yaml",
|
||||||
|
"services/maintenance/metis-sentinel-amd64-daemonset.yaml",
|
||||||
|
"services/maintenance/metis-sentinel-arm64-daemonset.yaml",
|
||||||
|
"services/maintenance/node-image-sweeper-daemonset.yaml",
|
||||||
|
"services/maintenance/node-nofile-daemonset.yaml",
|
||||||
|
"services/maintenance/oneoffs/titan-24-rootfs-sweep-job.yaml",
|
||||||
|
"services/monitoring/dcgm-exporter.yaml",
|
||||||
|
"services/monitoring/jetson-tegrastats-exporter.yaml"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "KSV-0041",
|
||||||
|
"targets": [
|
||||||
|
"infrastructure/cert-manager/cleanup/cert-manager-cleanup-rbac.yaml",
|
||||||
|
"infrastructure/longhorn/adopt/longhorn-adopt-rbac.yaml",
|
||||||
|
"infrastructure/traefik/clusterrole.yaml",
|
||||||
|
"services/bstein-dev-home/rbac.yaml",
|
||||||
|
"services/comms/comms-secrets-ensure-rbac.yaml",
|
||||||
|
"services/comms/mas-db-ensure-rbac.yaml",
|
||||||
|
"services/comms/mas-secrets-ensure-rbac.yaml",
|
||||||
|
"services/maintenance/soteria-rbac.yaml"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "KSV-0047",
|
||||||
|
"targets": [
|
||||||
|
"services/monitoring/rbac.yaml"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "KSV-0053",
|
||||||
|
"targets": [
|
||||||
|
"services/comms/comms-secrets-ensure-rbac.yaml",
|
||||||
|
"services/comms/mas-db-ensure-rbac.yaml",
|
||||||
|
"services/jenkins/serviceaccount.yaml",
|
||||||
|
"services/maintenance/ariadne-rbac.yaml"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "KSV-0056",
|
||||||
|
"targets": [
|
||||||
|
"infrastructure/cert-manager/cleanup/cert-manager-cleanup-rbac.yaml",
|
||||||
|
"infrastructure/longhorn/adopt/longhorn-adopt-rbac.yaml",
|
||||||
|
"services/jenkins/serviceaccount.yaml",
|
||||||
|
"services/maintenance/disable-k3s-traefik-rbac.yaml",
|
||||||
|
"services/maintenance/k3s-traefik-cleanup-rbac.yaml"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "KSV-0114",
|
||||||
|
"targets": [
|
||||||
|
"infrastructure/cert-manager/cleanup/cert-manager-cleanup-rbac.yaml"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "KSV-0118",
|
||||||
|
"targets": [
|
||||||
|
"infrastructure/cert-manager/cleanup/cert-manager-cleanup-job.yaml",
|
||||||
|
"infrastructure/core/coredns-deployment.yaml",
|
||||||
|
"infrastructure/core/ntp-sync-daemonset.yaml",
|
||||||
|
"infrastructure/longhorn/adopt/longhorn-helm-adopt-job.yaml",
|
||||||
|
"infrastructure/longhorn/core/longhorn-disk-tags-ensure-job.yaml",
|
||||||
|
"infrastructure/longhorn/core/longhorn-settings-ensure-job.yaml",
|
||||||
|
"infrastructure/longhorn/core/vault-sync-deployment.yaml",
|
||||||
|
"infrastructure/longhorn/ui-ingress/oauth2-proxy-longhorn.yaml",
|
||||||
|
"infrastructure/modules/profiles/components/device-plugin-jetson/daemonset.yaml",
|
||||||
|
"infrastructure/modules/profiles/components/device-plugin-minipc/daemonset.yaml",
|
||||||
|
"infrastructure/modules/profiles/components/device-plugin-tethys/daemonset.yaml",
|
||||||
|
"infrastructure/postgres/statefulset.yaml",
|
||||||
|
"infrastructure/vault-csi/vault-csi-provider.yaml",
|
||||||
|
"services/ai-llm/deployment.yaml",
|
||||||
|
"services/bstein-dev-home/backend-deployment.yaml",
|
||||||
|
"services/bstein-dev-home/chat-ai-gateway-deployment.yaml",
|
||||||
|
"services/bstein-dev-home/frontend-deployment.yaml",
|
||||||
|
"services/bstein-dev-home/oneoffs/migrations/portal-migrate-job.yaml",
|
||||||
|
"services/bstein-dev-home/oneoffs/portal-onboarding-e2e-test-job.yaml",
|
||||||
|
"services/bstein-dev-home/vault-sync-deployment.yaml",
|
||||||
|
"services/bstein-dev-home/vaultwarden-cred-sync-cronjob.yaml",
|
||||||
|
"services/comms/atlasbot-deployment.yaml",
|
||||||
|
"services/comms/coturn.yaml",
|
||||||
|
"services/comms/element-call-deployment.yaml",
|
||||||
|
"services/comms/guest-name-job.yaml",
|
||||||
|
"services/comms/livekit-token-deployment.yaml",
|
||||||
|
"services/comms/livekit.yaml",
|
||||||
|
"services/comms/mas-deployment.yaml",
|
||||||
|
"services/comms/oneoffs/bstein-force-leave-job.yaml",
|
||||||
|
"services/comms/oneoffs/comms-secrets-ensure-job.yaml",
|
||||||
|
"services/comms/oneoffs/mas-admin-client-secret-ensure-job.yaml",
|
||||||
|
"services/comms/oneoffs/mas-db-ensure-job.yaml",
|
||||||
|
"services/comms/oneoffs/mas-local-users-ensure-job.yaml",
|
||||||
|
"services/comms/oneoffs/othrys-kick-numeric-job.yaml",
|
||||||
|
"services/comms/oneoffs/synapse-admin-ensure-job.yaml",
|
||||||
|
"services/comms/oneoffs/synapse-seeder-admin-ensure-job.yaml",
|
||||||
|
"services/comms/oneoffs/synapse-signingkey-ensure-job.yaml",
|
||||||
|
"services/comms/oneoffs/synapse-user-seed-job.yaml",
|
||||||
|
"services/comms/pin-othrys-job.yaml",
|
||||||
|
"services/comms/reset-othrys-room-job.yaml",
|
||||||
|
"services/comms/seed-othrys-room.yaml",
|
||||||
|
"services/comms/vault-sync-deployment.yaml",
|
||||||
|
"services/comms/wellknown.yaml",
|
||||||
|
"services/crypto/monerod/deployment.yaml",
|
||||||
|
"services/crypto/wallet-monero-temp/deployment.yaml",
|
||||||
|
"services/crypto/xmr-miner/deployment.yaml",
|
||||||
|
"services/crypto/xmr-miner/vault-sync-deployment.yaml",
|
||||||
|
"services/crypto/xmr-miner/xmrig-daemonset.yaml",
|
||||||
|
"services/finance/firefly-cronjob.yaml",
|
||||||
|
"services/finance/firefly-deployment.yaml",
|
||||||
|
"services/finance/firefly-user-sync-cronjob.yaml",
|
||||||
|
"services/finance/oneoffs/finance-secrets-ensure-job.yaml",
|
||||||
|
"services/gitea/deployment.yaml",
|
||||||
|
"services/harbor/vault-sync-deployment.yaml",
|
||||||
|
"services/health/wger-admin-ensure-cronjob.yaml",
|
||||||
|
"services/health/wger-deployment.yaml",
|
||||||
|
"services/health/wger-user-sync-cronjob.yaml",
|
||||||
|
"services/jellyfin/loader.yaml",
|
||||||
|
"services/jenkins/deployment.yaml",
|
||||||
|
"services/jenkins/vault-sync-deployment.yaml",
|
||||||
|
"services/keycloak/oneoffs/actual-oidc-secret-ensure-job.yaml",
|
||||||
|
"services/keycloak/oneoffs/harbor-oidc-secret-ensure-job.yaml",
|
||||||
|
"services/keycloak/oneoffs/ldap-federation-job.yaml",
|
||||||
|
"services/keycloak/oneoffs/logs-oidc-secret-ensure-job.yaml",
|
||||||
|
"services/keycloak/oneoffs/mas-secrets-ensure-job.yaml",
|
||||||
|
"services/keycloak/oneoffs/metis-oidc-secret-ensure-job.yaml",
|
||||||
|
"services/keycloak/oneoffs/metis-ssh-keys-secret-ensure-job.yaml",
|
||||||
|
"services/keycloak/oneoffs/portal-admin-client-secret-ensure-job.yaml",
|
||||||
|
"services/keycloak/oneoffs/portal-e2e-client-job.yaml",
|
||||||
|
"services/keycloak/oneoffs/portal-e2e-execute-actions-email-test-job.yaml",
|
||||||
|
"services/keycloak/oneoffs/portal-e2e-target-client-job.yaml",
|
||||||
|
"services/keycloak/oneoffs/portal-e2e-token-exchange-permissions-job.yaml",
|
||||||
|
"services/keycloak/oneoffs/portal-e2e-token-exchange-test-job.yaml",
|
||||||
|
"services/keycloak/oneoffs/quality-oidc-secret-ensure-job.yaml",
|
||||||
|
"services/keycloak/oneoffs/realm-settings-job.yaml",
|
||||||
|
"services/keycloak/oneoffs/soteria-oidc-secret-ensure-job.yaml",
|
||||||
|
"services/keycloak/oneoffs/synapse-oidc-secret-ensure-job.yaml",
|
||||||
|
"services/keycloak/oneoffs/user-overrides-job.yaml",
|
||||||
|
"services/keycloak/oneoffs/vault-oidc-secret-ensure-job.yaml",
|
||||||
|
"services/keycloak/vault-sync-deployment.yaml",
|
||||||
|
"services/logging/node-image-gc-rpi4-daemonset.yaml",
|
||||||
|
"services/logging/node-image-prune-rpi5-daemonset.yaml",
|
||||||
|
"services/logging/node-log-rotation-daemonset.yaml",
|
||||||
|
"services/logging/oauth2-proxy.yaml",
|
||||||
|
"services/logging/oneoffs/opensearch-dashboards-setup-job.yaml",
|
||||||
|
"services/logging/oneoffs/opensearch-ism-job.yaml",
|
||||||
|
"services/logging/oneoffs/opensearch-observability-setup-job.yaml",
|
||||||
|
"services/logging/opensearch-prune-cronjob.yaml",
|
||||||
|
"services/logging/vault-sync-deployment.yaml",
|
||||||
|
"services/mailu/mailu-sync-cronjob.yaml",
|
||||||
|
"services/mailu/mailu-sync-listener.yaml",
|
||||||
|
"services/mailu/oneoffs/mailu-sync-job.yaml",
|
||||||
|
"services/mailu/vault-sync-deployment.yaml",
|
||||||
|
"services/mailu/vip-controller.yaml",
|
||||||
|
"services/maintenance/ariadne-deployment.yaml",
|
||||||
|
"services/maintenance/disable-k3s-traefik-daemonset.yaml",
|
||||||
|
"services/maintenance/image-sweeper-cronjob.yaml",
|
||||||
|
"services/maintenance/k3s-agent-restart-daemonset.yaml",
|
||||||
|
"services/maintenance/metis-deployment.yaml",
|
||||||
|
"services/maintenance/metis-k3s-token-sync-cronjob.yaml",
|
||||||
|
"services/maintenance/metis-sentinel-amd64-daemonset.yaml",
|
||||||
|
"services/maintenance/metis-sentinel-arm64-daemonset.yaml",
|
||||||
|
"services/maintenance/node-image-sweeper-daemonset.yaml",
|
||||||
|
"services/maintenance/node-nofile-daemonset.yaml",
|
||||||
|
"services/maintenance/oauth2-proxy-metis.yaml",
|
||||||
|
"services/maintenance/oauth2-proxy-soteria.yaml",
|
||||||
|
"services/maintenance/oneoffs/ariadne-migrate-job.yaml",
|
||||||
|
"services/maintenance/oneoffs/k3s-traefik-cleanup-job.yaml",
|
||||||
|
"services/maintenance/oneoffs/titan-24-rootfs-sweep-job.yaml",
|
||||||
|
"services/maintenance/pod-cleaner-cronjob.yaml",
|
||||||
|
"services/maintenance/soteria-deployment.yaml",
|
||||||
|
"services/maintenance/vault-sync-deployment.yaml",
|
||||||
|
"services/monitoring/dcgm-exporter.yaml",
|
||||||
|
"services/monitoring/jetson-tegrastats-exporter.yaml",
|
||||||
|
"services/monitoring/oneoffs/grafana-org-bootstrap.yaml",
|
||||||
|
"services/monitoring/oneoffs/grafana-user-dedupe-job.yaml",
|
||||||
|
"services/monitoring/platform-quality-gateway-deployment.yaml",
|
||||||
|
"services/monitoring/platform-quality-suite-probe-cronjob.yaml",
|
||||||
|
"services/monitoring/postmark-exporter-deployment.yaml",
|
||||||
|
"services/monitoring/vault-sync-deployment.yaml",
|
||||||
|
"services/nextcloud/collabora.yaml",
|
||||||
|
"services/oauth2-proxy/deployment.yaml",
|
||||||
|
"services/openldap/statefulset.yaml",
|
||||||
|
"services/outline/deployment.yaml",
|
||||||
|
"services/outline/redis-deployment.yaml",
|
||||||
|
"services/pegasus/vault-sync-deployment.yaml",
|
||||||
|
"services/quality/oauth2-proxy-sonarqube.yaml",
|
||||||
|
"services/quality/sonarqube-deployment.yaml",
|
||||||
|
"services/quality/sonarqube-exporter-deployment.yaml",
|
||||||
|
"services/sui-metrics/base/deployment.yaml",
|
||||||
|
"services/sui-metrics/overlays/atlas/patch-node-selector.yaml",
|
||||||
|
"services/typhon/deployment.yaml",
|
||||||
|
"services/typhon/vault-sync-deployment.yaml",
|
||||||
|
"services/vault/k8s-auth-config-cronjob.yaml",
|
||||||
|
"services/vault/oidc-config-cronjob.yaml",
|
||||||
|
"services/vaultwarden/deployment.yaml"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "KSV-0121",
|
||||||
|
"targets": [
|
||||||
|
"services/logging/node-image-gc-rpi4-daemonset.yaml",
|
||||||
|
"services/logging/node-image-prune-rpi5-daemonset.yaml",
|
||||||
|
"services/logging/node-log-rotation-daemonset.yaml",
|
||||||
|
"services/maintenance/disable-k3s-traefik-daemonset.yaml",
|
||||||
|
"services/maintenance/image-sweeper-cronjob.yaml",
|
||||||
|
"services/maintenance/metis-deployment.yaml",
|
||||||
|
"services/maintenance/node-image-sweeper-daemonset.yaml",
|
||||||
|
"services/maintenance/node-nofile-daemonset.yaml",
|
||||||
|
"services/maintenance/oneoffs/titan-24-rootfs-sweep-job.yaml"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
@ -2,4 +2,8 @@ FROM python:3.11-slim
|
|||||||
|
|
||||||
ENV PIP_DISABLE_PIP_VERSION_CHECK=1
|
ENV PIP_DISABLE_PIP_VERSION_CHECK=1
|
||||||
|
|
||||||
RUN pip install --no-cache-dir requests psycopg2-binary
|
RUN pip install --no-cache-dir requests psycopg2-binary \
|
||||||
|
&& groupadd --system guest-tools \
|
||||||
|
&& useradd --system --uid 65532 --gid guest-tools --home-dir /nonexistent --shell /usr/sbin/nologin guest-tools
|
||||||
|
|
||||||
|
USER guest-tools
|
||||||
|
|||||||
@ -1,10 +1,13 @@
|
|||||||
FROM ghcr.io/element-hq/lk-jwt-service:0.3.0 AS base
|
FROM ghcr.io/element-hq/lk-jwt-service:0.3.0 AS base
|
||||||
|
|
||||||
FROM alpine:3.20
|
FROM alpine:3.20
|
||||||
RUN apk add --no-cache ca-certificates
|
RUN apk add --no-cache ca-certificates \
|
||||||
|
&& addgroup -S livekit-token \
|
||||||
|
&& adduser -S -D -H -u 65532 -G livekit-token livekit-token
|
||||||
COPY --from=base /lk-jwt-service /lk-jwt-service
|
COPY --from=base /lk-jwt-service /lk-jwt-service
|
||||||
COPY dockerfiles/vault-entrypoint.sh /entrypoint.sh
|
COPY dockerfiles/vault-entrypoint.sh /entrypoint.sh
|
||||||
RUN chmod 0755 /entrypoint.sh
|
RUN chmod 0755 /entrypoint.sh
|
||||||
|
|
||||||
|
USER livekit-token
|
||||||
ENTRYPOINT ["/entrypoint.sh"]
|
ENTRYPOINT ["/entrypoint.sh"]
|
||||||
CMD ["/lk-jwt-service"]
|
CMD ["/lk-jwt-service"]
|
||||||
|
|||||||
@ -29,10 +29,12 @@ FROM ${DEBIAN_IMAGE}
|
|||||||
RUN set -eux; \
|
RUN set -eux; \
|
||||||
apt-get update; \
|
apt-get update; \
|
||||||
apt-get install -y --no-install-recommends ca-certificates; \
|
apt-get install -y --no-install-recommends ca-certificates; \
|
||||||
update-ca-certificates; rm -rf /var/lib/apt/lists/*
|
update-ca-certificates; rm -rf /var/lib/apt/lists/*; \
|
||||||
|
groupadd --system p2pool; \
|
||||||
|
useradd --system --uid 65532 --gid p2pool --home-dir /nonexistent --shell /usr/sbin/nologin p2pool
|
||||||
COPY --from=fetch /out/p2pool /usr/local/bin/p2pool
|
COPY --from=fetch /out/p2pool /usr/local/bin/p2pool
|
||||||
|
|
||||||
RUN /usr/local/bin/p2pool --version || true
|
RUN /usr/local/bin/p2pool --version || true
|
||||||
EXPOSE 3333
|
EXPOSE 3333
|
||||||
|
USER p2pool
|
||||||
ENTRYPOINT ["/usr/local/bin/p2pool"]
|
ENTRYPOINT ["/usr/local/bin/p2pool"]
|
||||||
|
|
||||||
|
|||||||
@ -26,9 +26,12 @@ RUN set -eux; \
|
|||||||
curl -fsSL "$URL" -o /opt/monero/monero.tar.bz2; \
|
curl -fsSL "$URL" -o /opt/monero/monero.tar.bz2; \
|
||||||
tar -xjf /opt/monero/monero.tar.bz2 -C /opt/monero --strip-components=1; \
|
tar -xjf /opt/monero/monero.tar.bz2 -C /opt/monero --strip-components=1; \
|
||||||
install -m 0755 /opt/monero/monero-wallet-rpc /usr/local/bin/monero-wallet-rpc; \
|
install -m 0755 /opt/monero/monero-wallet-rpc /usr/local/bin/monero-wallet-rpc; \
|
||||||
rm -f /opt/monero/monero.tar.bz2
|
rm -f /opt/monero/monero.tar.bz2; \
|
||||||
|
groupadd --system monero; \
|
||||||
|
useradd --system --uid 1000 --gid monero --home-dir /nonexistent --shell /usr/sbin/nologin monero
|
||||||
|
|
||||||
ENV PATH="/usr/local/bin:/usr/bin:/bin"
|
ENV PATH="/usr/local/bin:/usr/bin:/bin"
|
||||||
RUN /usr/local/bin/monero-wallet-rpc --version || true
|
RUN /usr/local/bin/monero-wallet-rpc --version || true
|
||||||
|
|
||||||
EXPOSE 18083
|
EXPOSE 18083
|
||||||
|
USER monero
|
||||||
|
|||||||
@ -23,10 +23,14 @@ RUN set -eux; \
|
|||||||
mkdir -p /opt/monero; \
|
mkdir -p /opt/monero; \
|
||||||
tar -xjf /tmp/monero.tar.bz2 -C /opt/monero --strip-components=1; \
|
tar -xjf /tmp/monero.tar.bz2 -C /opt/monero --strip-components=1; \
|
||||||
rm -f /tmp/monero.tar.bz2; \
|
rm -f /tmp/monero.tar.bz2; \
|
||||||
|
groupadd --system monero; \
|
||||||
|
useradd --system --uid 1000 --gid monero --home-dir /nonexistent --shell /usr/sbin/nologin monero; \
|
||||||
mkdir -p /data; \
|
mkdir -p /data; \
|
||||||
|
chown monero:monero /data; \
|
||||||
chmod 0770 /data
|
chmod 0770 /data
|
||||||
|
|
||||||
ENV LD_LIBRARY_PATH=/opt/monero:/opt/monero/lib \
|
ENV LD_LIBRARY_PATH=/opt/monero:/opt/monero/lib \
|
||||||
PATH="/opt/monero:${PATH}"
|
PATH="/opt/monero:${PATH}"
|
||||||
|
|
||||||
|
USER monero
|
||||||
CMD ["/opt/monero/monerod", "--version"]
|
CMD ["/opt/monero/monerod", "--version"]
|
||||||
|
|||||||
@ -1,10 +1,13 @@
|
|||||||
FROM quay.io/oauth2-proxy/oauth2-proxy:v7.6.0 AS base
|
FROM quay.io/oauth2-proxy/oauth2-proxy:v7.6.0 AS base
|
||||||
|
|
||||||
FROM alpine:3.20
|
FROM alpine:3.20
|
||||||
RUN apk add --no-cache ca-certificates
|
RUN apk add --no-cache ca-certificates \
|
||||||
|
&& addgroup -S oauth2-proxy \
|
||||||
|
&& adduser -S -D -H -u 65532 -G oauth2-proxy oauth2-proxy
|
||||||
COPY --from=base /bin/oauth2-proxy /bin/oauth2-proxy
|
COPY --from=base /bin/oauth2-proxy /bin/oauth2-proxy
|
||||||
COPY dockerfiles/vault-entrypoint.sh /entrypoint.sh
|
COPY dockerfiles/vault-entrypoint.sh /entrypoint.sh
|
||||||
RUN chmod 0755 /entrypoint.sh
|
RUN chmod 0755 /entrypoint.sh
|
||||||
|
|
||||||
|
USER oauth2-proxy
|
||||||
ENTRYPOINT ["/entrypoint.sh"]
|
ENTRYPOINT ["/entrypoint.sh"]
|
||||||
CMD ["/bin/oauth2-proxy"]
|
CMD ["/bin/oauth2-proxy"]
|
||||||
|
|||||||
@ -1,10 +1,13 @@
|
|||||||
FROM registry.bstein.dev/streaming/pegasus:1.2.32 AS base
|
FROM registry.bstein.dev/streaming/pegasus:1.2.32 AS base
|
||||||
|
|
||||||
FROM alpine:3.20
|
FROM alpine:3.20
|
||||||
RUN apk add --no-cache ca-certificates
|
RUN apk add --no-cache ca-certificates \
|
||||||
|
&& addgroup -S pegasus \
|
||||||
|
&& adduser -S -D -H -u 65532 -G pegasus pegasus
|
||||||
COPY --from=base /pegasus /pegasus
|
COPY --from=base /pegasus /pegasus
|
||||||
COPY dockerfiles/vault-entrypoint.sh /entrypoint.sh
|
COPY dockerfiles/vault-entrypoint.sh /entrypoint.sh
|
||||||
RUN chmod 0755 /entrypoint.sh
|
RUN chmod 0755 /entrypoint.sh
|
||||||
|
|
||||||
|
USER pegasus
|
||||||
ENTRYPOINT ["/entrypoint.sh"]
|
ENTRYPOINT ["/entrypoint.sh"]
|
||||||
CMD ["/pegasus"]
|
CMD ["/pegasus"]
|
||||||
|
|||||||
@ -15,7 +15,9 @@ RUN apt-get update \
|
|||||||
git \
|
git \
|
||||||
jq \
|
jq \
|
||||||
unzip \
|
unzip \
|
||||||
&& rm -rf /var/lib/apt/lists/*
|
&& rm -rf /var/lib/apt/lists/* \
|
||||||
|
&& groupadd --system quality-tools \
|
||||||
|
&& useradd --system --uid 65532 --gid quality-tools --home-dir /nonexistent --shell /usr/sbin/nologin quality-tools
|
||||||
|
|
||||||
RUN set -eux; \
|
RUN set -eux; \
|
||||||
scanner_zip="sonar-scanner-cli-${SONAR_SCANNER_VERSION}-linux-aarch64.zip"; \
|
scanner_zip="sonar-scanner-cli-${SONAR_SCANNER_VERSION}-linux-aarch64.zip"; \
|
||||||
@ -38,6 +40,9 @@ RUN set -eux; \
|
|||||||
RUN set -eux; \
|
RUN set -eux; \
|
||||||
mkdir -p "${TRIVY_CACHE_DIR}"; \
|
mkdir -p "${TRIVY_CACHE_DIR}"; \
|
||||||
trivy image --download-db-only --cache-dir "${TRIVY_CACHE_DIR}"; \
|
trivy image --download-db-only --cache-dir "${TRIVY_CACHE_DIR}"; \
|
||||||
chmod -R a+rX "${TRIVY_CACHE_DIR}"
|
chmod -R a+rX "${TRIVY_CACHE_DIR}"; \
|
||||||
|
mkdir -p /workspace; \
|
||||||
|
chown quality-tools:quality-tools /workspace
|
||||||
|
|
||||||
WORKDIR /workspace
|
WORKDIR /workspace
|
||||||
|
USER quality-tools
|
||||||
|
|||||||
@ -16,6 +16,7 @@
|
|||||||
"managed_modules": [
|
"managed_modules": [
|
||||||
"ci/scripts/publish_test_metrics.py",
|
"ci/scripts/publish_test_metrics.py",
|
||||||
"ci/scripts/publish_test_metrics_quality.py",
|
"ci/scripts/publish_test_metrics_quality.py",
|
||||||
|
"ci/scripts/supply_chain_report.py",
|
||||||
"testing/__init__.py",
|
"testing/__init__.py",
|
||||||
"testing/quality_contract.py",
|
"testing/quality_contract.py",
|
||||||
"testing/quality_docs.py",
|
"testing/quality_docs.py",
|
||||||
@ -24,8 +25,9 @@
|
|||||||
"testing/quality_gate.py",
|
"testing/quality_gate.py",
|
||||||
"ci/tests/glue/test_ariadne_schedules.py",
|
"ci/tests/glue/test_ariadne_schedules.py",
|
||||||
"ci/tests/glue/test_glue_metrics.py",
|
"ci/tests/glue/test_glue_metrics.py",
|
||||||
"testing/tests/test_publish_test_metrics.py",
|
"testing/tests/test_publish_test_metrics.py",
|
||||||
"testing/tests/test_quality_contract.py",
|
"testing/tests/test_supply_chain_report.py",
|
||||||
|
"testing/tests/test_quality_contract.py",
|
||||||
"testing/tests/test_quality_gate.py"
|
"testing/tests/test_quality_gate.py"
|
||||||
],
|
],
|
||||||
"lint_paths": [
|
"lint_paths": [
|
||||||
@ -160,6 +162,7 @@
|
|||||||
"tracked_files": [
|
"tracked_files": [
|
||||||
"ci/scripts/publish_test_metrics.py",
|
"ci/scripts/publish_test_metrics.py",
|
||||||
"ci/scripts/publish_test_metrics_quality.py",
|
"ci/scripts/publish_test_metrics_quality.py",
|
||||||
|
"ci/scripts/supply_chain_report.py",
|
||||||
"testing/quality_contract.py",
|
"testing/quality_contract.py",
|
||||||
"testing/quality_docs.py",
|
"testing/quality_docs.py",
|
||||||
"testing/quality_hygiene.py",
|
"testing/quality_hygiene.py",
|
||||||
|
|||||||
187
testing/tests/test_supply_chain_report.py
Normal file
187
testing/tests/test_supply_chain_report.py
Normal file
@ -0,0 +1,187 @@
|
|||||||
|
"""Tests for titan-iac supply-chain compliance report generation."""
|
||||||
|
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
import json
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
from ci.scripts import supply_chain_report
|
||||||
|
|
||||||
|
|
||||||
|
def _write_json(path: Path, payload: dict):
|
||||||
|
"""Write compact JSON fixtures for report tests."""
|
||||||
|
path.write_text(json.dumps(payload), encoding="utf-8")
|
||||||
|
|
||||||
|
|
||||||
|
def test_build_report_separates_waived_and_open_misconfigurations(tmp_path: Path):
|
||||||
|
"""Existing waivers suppress only exact target/id pairs."""
|
||||||
|
waivers = tmp_path / "waivers.json"
|
||||||
|
_write_json(
|
||||||
|
waivers,
|
||||||
|
{
|
||||||
|
"default_expires_at": "2026-05-22",
|
||||||
|
"misconfigurations": [
|
||||||
|
{
|
||||||
|
"id": "KSV-0014",
|
||||||
|
"targets": ["services/example/deployment.yaml"],
|
||||||
|
}
|
||||||
|
],
|
||||||
|
},
|
||||||
|
)
|
||||||
|
trivy_payload = {
|
||||||
|
"Results": [
|
||||||
|
{
|
||||||
|
"Target": "services/example/deployment.yaml",
|
||||||
|
"Misconfigurations": [
|
||||||
|
{
|
||||||
|
"ID": "KSV-0014",
|
||||||
|
"Status": "FAIL",
|
||||||
|
"Severity": "HIGH",
|
||||||
|
"Title": "Root file system is not read-only",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ID": "KSV-0118",
|
||||||
|
"Status": "FAIL",
|
||||||
|
"Severity": "HIGH",
|
||||||
|
"Title": "Default security context configured",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
report = supply_chain_report.build_report(trivy_payload, waivers, today_override="2026-04-22")
|
||||||
|
|
||||||
|
assert report["status"] == "failed"
|
||||||
|
assert report["waived_misconfigurations"] == 1
|
||||||
|
assert report["high_or_critical_misconfigurations"] == 1
|
||||||
|
assert report["open_misconfiguration_examples"] == [
|
||||||
|
{
|
||||||
|
"id": "KSV-0118",
|
||||||
|
"target": "services/example/deployment.yaml",
|
||||||
|
"severity": "HIGH",
|
||||||
|
"title": "Default security context configured",
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
def test_build_report_fails_expired_waivers_and_secrets(tmp_path: Path):
|
||||||
|
"""Expired waivers intentionally stop hiding old baseline debt."""
|
||||||
|
waivers = tmp_path / "waivers.json"
|
||||||
|
_write_json(
|
||||||
|
waivers,
|
||||||
|
{
|
||||||
|
"default_expires_at": "2026-04-01",
|
||||||
|
"misconfigurations": [
|
||||||
|
{
|
||||||
|
"id": "KSV-0014",
|
||||||
|
"targets": ["services/example/deployment.yaml"],
|
||||||
|
}
|
||||||
|
],
|
||||||
|
},
|
||||||
|
)
|
||||||
|
trivy_payload = {
|
||||||
|
"Results": [
|
||||||
|
{
|
||||||
|
"Target": "services/example/deployment.yaml",
|
||||||
|
"Secrets": [{"RuleID": "secret"}],
|
||||||
|
"Misconfigurations": [
|
||||||
|
{
|
||||||
|
"ID": "KSV-0014",
|
||||||
|
"Status": "FAIL",
|
||||||
|
"Severity": "CRITICAL",
|
||||||
|
"Title": "Root file system is not read-only",
|
||||||
|
}
|
||||||
|
],
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
report = supply_chain_report.build_report(trivy_payload, waivers, today_override="2026-04-22")
|
||||||
|
|
||||||
|
assert report["status"] == "failed"
|
||||||
|
assert report["compliant"] is False
|
||||||
|
assert report["secrets"] == 1
|
||||||
|
assert report["expired_waivers"] == 1
|
||||||
|
assert report["waived_misconfigurations"] == 0
|
||||||
|
|
||||||
|
|
||||||
|
def test_build_report_handles_missing_and_malformed_waiver_entries(tmp_path: Path):
|
||||||
|
"""Malformed waiver rows are ignored instead of hiding real findings."""
|
||||||
|
missing_waivers = tmp_path / "missing.json"
|
||||||
|
empty_report = supply_chain_report.build_report({"Results": []}, missing_waivers, today_override="2026-04-22")
|
||||||
|
assert empty_report["status"] == "ok"
|
||||||
|
|
||||||
|
waivers = tmp_path / "waivers.json"
|
||||||
|
_write_json(
|
||||||
|
waivers,
|
||||||
|
{
|
||||||
|
"misconfigurations": [
|
||||||
|
"bad row",
|
||||||
|
{"id": "", "targets": ["services/example/deployment.yaml"]},
|
||||||
|
{"id": "KSV-0014", "targets": "not a list"},
|
||||||
|
{"id": "KSV-0118", "expires_at": "2026-05-22", "targets": [""]},
|
||||||
|
]
|
||||||
|
},
|
||||||
|
)
|
||||||
|
trivy_payload = {
|
||||||
|
"Results": [
|
||||||
|
"bad result",
|
||||||
|
{
|
||||||
|
"Target": "services/example/deployment.yaml",
|
||||||
|
"Vulnerabilities": [
|
||||||
|
{"Severity": "HIGH"},
|
||||||
|
{"Severity": "CRITICAL"},
|
||||||
|
{"Severity": "LOW"},
|
||||||
|
],
|
||||||
|
"Misconfigurations": [
|
||||||
|
"bad misconfiguration",
|
||||||
|
{"ID": "KSV-0001", "Status": "PASS", "Severity": "CRITICAL"},
|
||||||
|
{"ID": "KSV-0002", "Status": "FAIL", "Severity": "LOW"},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
report = supply_chain_report.build_report(trivy_payload, waivers, today_override="2026-04-22")
|
||||||
|
|
||||||
|
assert report["status"] == "failed"
|
||||||
|
assert report["critical_vulnerabilities"] == 1
|
||||||
|
assert report["high_vulnerabilities"] == 1
|
||||||
|
assert report["high_or_critical_misconfigurations"] == 0
|
||||||
|
|
||||||
|
|
||||||
|
def test_read_json_rejects_non_object_payload(tmp_path: Path):
|
||||||
|
"""Pipeline evidence files must be JSON objects, not arrays or scalars."""
|
||||||
|
path = tmp_path / "array.json"
|
||||||
|
path.write_text("[]", encoding="utf-8")
|
||||||
|
|
||||||
|
try:
|
||||||
|
supply_chain_report._read_json(path)
|
||||||
|
except ValueError as exc:
|
||||||
|
assert "must contain a JSON object" in str(exc)
|
||||||
|
else: # pragma: no cover - keeps the assertion message readable on failure
|
||||||
|
raise AssertionError("expected ValueError")
|
||||||
|
|
||||||
|
|
||||||
|
def test_main_writes_compliance_report(tmp_path: Path):
|
||||||
|
"""The Jenkins CLI path writes the exact report artifact it publishes."""
|
||||||
|
trivy_json = tmp_path / "trivy.json"
|
||||||
|
output = tmp_path / "ironbank-compliance.json"
|
||||||
|
_write_json(trivy_json, {"Results": []})
|
||||||
|
|
||||||
|
rc = supply_chain_report.main(
|
||||||
|
[
|
||||||
|
"--trivy-json",
|
||||||
|
str(trivy_json),
|
||||||
|
"--output",
|
||||||
|
str(output),
|
||||||
|
"--today",
|
||||||
|
"2026-04-22",
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|
||||||
|
assert rc == 0
|
||||||
|
payload = json.loads(output.read_text(encoding="utf-8"))
|
||||||
|
assert payload["status"] == "ok"
|
||||||
|
assert payload["compliant"] is True
|
||||||
Loading…
x
Reference in New Issue
Block a user