Compare commits

...
11 Commits
Author SHA1 Message Date
Cédric Verstraeten caab6f6f55 Merge pull request #239 from kerberos-io/feat/hub-kyverno-missing-images
feat(hub): Kyverno policies for every image, trust only ghcr.io/uug-ai, hardened Admin default; remove hub-proxy and vault-forwarder (0.184.0)
2026-11-11 21:55:02 +01:00
Cédric VerstraetenandClaude Opus 5.5 3949cb4bac feat(hub): default Admin to signed, hardened ghcr.io/uug-ai/admin v1.4.5
Only ghcr.io/uug-ai images are trusted, so Admin now defaults to the
signed GHCR release with the hardened runtime production already uses
(8080, 65532 non-root, read-only root, memory /tmp, /healthz probes).
A legacy image can be restored with the documented opt-out values.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-11 20:52:01 +00:00
Cédric VerstraetenandClaude Opus 5.5 1fe8fe9727 feat(hub): trust only ghcr.io/uug-ai images
- admin and hub-reactivatesubscriptions signature/hardening policies
  match ghcr.io/uug-ai only (Docker Hub references removed).
- Remove the oauth2-proxy (quay.io) signature policy.
- Add trusted-registry.yaml (category "Image registry", Audit): reports
  every container, init and ephemeral container image that is not from
  ghcr.io/uug-ai/. It flags the remaining non-GHCR images the chart can
  deploy: uugai/admin and uugai/hub-reactivatesubscriptions (Docker Hub)
  and quay.io/oauth2-proxy/oauth2-proxy.
- README updated.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-11 20:46:34 +00:00
Cédric VerstraetenandClaude Opus 5.5 5eb0d41aa7 feat(hub): keep the reactivate-subscriptions service
hub-reactivate-subscription is still needed: restore its template,
kerberoshub.reactivate values, README rows and its Kyverno signature and
hardening policies (Audit until the chart uses the signed
ghcr.io/uug-ai/hub-reactivatesubscriptions image). Only hub-proxy and
vault-forwarder are removed. The reactivate output is unchanged from main.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-11 20:40:03 +00:00
Cédric VerstraetenandClaude Opus 5.5 5a445e0179 feat(hub): remove unused hub-proxy, reactivate-subscriptions and vault-forwarder
These services are no longer used. Remove their templates
(kerberos-vault/vault-proxy.yaml, kerberos-vault/vault-forwarder.yaml,
kerberos-hub/hub-reactivate-subscription.yaml), their values
(kerberoshub.proxy, kerberoshub.forwarder, kerberoshub.reactivate), their
README sections, and the Kyverno policies added for them in this change.

Installs that still set these values keep rendering; the keys are ignored.
Upgrading removes the hub-reactivate-subscription Deployment (and the
vault-proxy / vault-forwarder ones where enabled).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-11 20:37:09 +00:00
Cédric Verstraeten a34a82138a Merge pull request #238 from kerberos-io/feat/hub-frontend-v1.19.35-default
feat(hub): default hub-frontend v1.19.35, the first attested hardened release (0.183.1)
2026-11-11 21:36:15 +01:00
Cédric VerstraetenandClaude Opus 5.5 714e59f6fe feat(hub): Kyverno policies for every container image the chart deploys (0.184.0)
A scan of every container and init container the chart can render (all
modes and optional components) found 26 images; 21 had a signature
policy and 11 a hardening policy. Add the missing ones so Policy
Reporter shows every gap instead of "no policy":

- Hardening policies for the 10 ghcr.io/uug-ai images without a hardened
  release yet (audit, objecttracking, vlm, dominantcolors, event, export,
  notification, notification-test, sprite, thumbnail).
- Signature and hardening policies for the Docker Hub images uugai/admin,
  uugai/hub-proxy, uugai/hub-reactivatesubscriptions (also matching their
  ghcr.io/uug-ai releases) and the legacy kerberos/vault-forwarder.
- A visibility-only signature policy for the third-party oauth2-proxy.

All new policies stay in Audit regardless of the configured mode, so
they report gaps without ever blocking. README tables updated.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-11 20:31:32 +00:00
Cédric VerstraetenandClaude Opus 5.5 73106bfa10 feat(hub): default hub-frontend v1.19.35, the first attested hardened release (0.183.1)
hub-frontend v1.19.35 is a hardened release with the signed
image-hardening attestation (v1.19.34 was hardened before attestations
existed). With it, every chart default with a hardening policy is an
attested hardened release. Frontend runtime check and README updated.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-11 20:17:49 +00:00
Cédric Verstraeten 284765c401 Merge pull request #237 from kerberos-io/feat/hub-signed-image-defaults
feat(hub): default to signed and hardened image releases (0.183.0)
2026-11-11 19:18:58 +01:00
Cédric VerstraetenandClaude Opus 5.5 90be00011d Update frontend runtime check and README defaults for the new image tags
check-frontend-runtime.sh asserted the old default hub-frontend tag
(v1.19.28); README parameter table defaults were stale.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-11 18:14:58 +00:00
Cédric VerstraetenandClaude Opus 5.5 2d0ad37170 feat(hub): default to signed and hardened image releases (0.183.0)
Update every ghcr.io/uug-ai default image tag to the release running in
production: all signed by the UUG.AI release workflow for their own
repository, and hardened releases with the image-hardening attestation
for every image that has a hardening policy except hub-frontend. Older
defaults (e.g. hub-api v1.11.31, hub-workflows v1.0.0) were unsigned and
failed the chart's own Kyverno policies. Commented examples (loitering,
objecttracking, vlm) updated too.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-11 18:10:44 +00:00
23 changed files with 1177 additions and 370 deletions
+1 -1
View File
@@ -16,7 +16,7 @@ type: application
# This is the chart version. This version number should be incremented each time you make changes
# to the chart and its templates, including the app version.
# Versions are expected to follow Semantic Versioning (https://semver.org/)
version: 0.182.1
version: 0.184.0
# This is the version number of the application being deployed. This version number should be
# incremented each time you make changes to the application. Versions are not expected to
+71 -94
View File
@@ -58,7 +58,7 @@ legacy opt-out, TLS/configuration mounts and deployment modes.
### Hardened frontend images
Starting with chart **`0.170.0`**, both frontends default to shell-free
`ghcr.io/uug-ai/hub-frontend:v1.19.28`, running as `65532:65532` on port `8080`
`ghcr.io/uug-ai/hub-frontend:v1.19.35`, running as `65532:65532` on port `8080`
with a read-only root filesystem and writable `/tmp`. The Service and ingress
remain on port `80`. Admin retains its legacy image and port `80`; its hardened
runtime remains opt-in.
@@ -122,61 +122,35 @@ instructions below if the existing Deployment cannot be patched to `8080`.
Run `bash scripts/check-frontend-runtime.sh` for default, demo, legacy override,
and deployment-values regression coverage.
### Hardened Admin image (opt-in, chart 0.167.3)
### Hardened Admin image (default since chart 0.184.0)
`charts/hub` deploys Admin in `all` and `ui` modes. Shell-free Admin `v1.4.3`
runs as `65532:65532` and listens on `8080`, unlike the legacy image on `80`.
Set these values together; the chart does not upgrade the image automatically:
`charts/hub` deploys Admin in `all` and `ui` modes. Since chart **`0.184.0`** the
default is the signed, shell-free `ghcr.io/uug-ai/admin` (`v1.4.5`): it runs as
`65532:65532` on `8080` with a read-only root filesystem, a memory-backed `/tmp`
(`admin-tmp`, the only writable path) and `/healthz` probes. These settings are
the defaults in `values.yaml`; keep them together with the image. Append extra
volumes and mounts to the `admin.volumes` / `admin.volumeMounts` lists (Helm
replaces lists in overrides). Memory-backed scratch counts against the pod memory
limit. The `admin-svc` Service and Admin ingress use port `80`; the Service
targets the named `http` container port. OAuth2-proxy is unchanged.
Only `ghcr.io/uug-ai` images are trusted (see *Image signature verification*).
To run a legacy image on port `80` instead, restore all of these together:
```yaml
admin:
repository: ghcr.io/uug-ai/admin
tag: v1.4.3
containerPort: 8080
securityContext:
runAsNonRoot: true
runAsUser: 65532
runAsGroup: 65532
readOnlyRootFilesystem: true
allowPrivilegeEscalation: false
capabilities:
drop: ["ALL"]
seccompProfile:
type: RuntimeDefault
volumes:
- name: admin-tmp
emptyDir:
medium: Memory
sizeLimit: 16Mi # Example; size for your runtime configuration.
volumeMounts:
- name: admin-tmp
mountPath: /tmp
readinessProbe:
httpGet:
path: /healthz
port: http
periodSeconds: 10
livenessProbe:
httpGet:
path: /healthz
port: http
initialDelaySeconds: 10
periodSeconds: 10
repository: uugai/admin
tag: v1.3.0
containerPort: 80
securityContext: null
readinessProbe: null
livenessProbe: null
volumes: null
volumeMounts: null
```
Merge the scratch volume with any existing mounts. Only `/tmp` is writable;
application files remain read-only. Memory-backed scratch counts against the
pod memory limit. The `admin-svc` Service and Admin ingress still use port `80`;
the Service targets the named `http` container port. OAuth2-proxy is unchanged.
Defaults remain port `80` with no security context, added volumes, or probes. Coordinate
the image, values and a chart revision containing these settings: published
`0.167.2` does not contain Admin runtime support.
Rollbacks to legacy images must restore port `80`, remove the hardened
security context, and disable `/healthz` probes together. Run
`bash scripts/check-admin-runtime.sh` from the repository root to verify
legacy defaults, hardened runtime/probes, and unchanged OAuth2 routing.
Run `bash scripts/check-admin-runtime.sh` from the repository root to verify the
hardened defaults, the legacy opt-out and unchanged OAuth2 routing.
### Recovering a duplicate HTTP port during upgrades
Chart `0.169.1` publishes this recovery guidance. The helper is available in the
@@ -327,14 +301,6 @@ Optional dataset mode also requires its own writable `ANPR_DATASET_DIR` mount.
Models and application directories stay read-only.
This repository has **no Vault server or design-system chart**. The files named
`vault-proxy` and `vault-forwarder` deploy different legacy applications; their
ports are not the Vault server's port. Do not change them for `uug-ai/vault#119`.
That proposed Vault image requires port `8080` (legacy `80`), UID/GID `65532`,
read-only `/home/vault`, workload-sized writable `/run/vault`, and compatible
ownership on existing optional `LOCAL_CACHE_DIRECTORY` mounts. Its liveness
endpoint is `GET /api/health`. Wire those settings in the actual Vault deployment
only when a compatible image release is selected; no migration is required.
### Image signature verification (Kyverno)
Starting with chart **`0.179.0`**, the chart can verify that UUG.AI images are
@@ -383,18 +349,29 @@ signed for its own `uug-ai/<image>` repository. "Mode" is the
| `hub-pipeline-notification-test-signed-images.yaml` | `ghcr.io/uug-ai/hub-pipeline-notification-test` | ✅ signed (from v1.2.7) | value |
| `hub-pipeline-sprite-signed-images.yaml` | `ghcr.io/uug-ai/hub-pipeline-sprite` | ✅ signed (from v1.1.28) | value |
| `hub-pipeline-thumbnail-signed-images.yaml` | `ghcr.io/uug-ai/hub-pipeline-thumbnail` | ✅ signed (from v1.3.24) | value |
| `admin-signed-images.yaml` | `ghcr.io/uug-ai/admin` | ✅ signed (from v1.4.5) | always `Audit` |
| `hub-reactivatesubscriptions-signed-images.yaml` | `ghcr.io/uug-ai/hub-reactivatesubscriptions` | ❌ not on GHCR yet; the chart uses Docker Hub `uugai/hub-reactivatesubscriptions` | always `Audit` |
Since chart **`0.182.0`** every `ghcr.io/uug-ai` image's releases are signed, so
every policy follows `imageVerification.validationFailureAction`, except
`hub-objecttracking`: its GPU image (`<tag>-gpu`) is not signed yet, so that
policy stays in `Audit` and enabling `Enforce` never blocks it. Images are signed
from the release noted in the table; **older tags are unsigned and are rejected
in `Enforce`**, so check the tags you run (including this chart's defaults)
before enforcing.
in `Enforce`**, so check the tags you run before enforcing. Since chart
**`0.183.0`** the default image tags are signed releases, and since **`0.183.1`** hardened
releases (with the attestation) for every image that has a hardening policy.
Not covered: `uugai/admin`, `uugai/hub-proxy` and
`uugai/hub-reactivatesubscriptions` are pulled from Docker Hub rather than the
signed `ghcr.io/uug-ai` releases, and `oauth2-proxy` is a third-party image.
Since chart **`0.184.0`** only `ghcr.io/uug-ai` images are trusted:
- every UUG.AI image has a signature and a hardening policy, matching its
`ghcr.io/uug-ai/<image>` repository only. Images that are not signed or
hardened yet stay in `Audit` (the tables mark them), so they show up as
failures in Policy Reporter without ever being blocked;
- `trusted-registry.yaml` (category **`Image registry`**, `Audit`) reports every
container image from any other registry or organisation. The chart can still
deploy two: `uugai/hub-reactivatesubscriptions` (Docker Hub; not released to
GHCR yet) and the third-party `quay.io/oauth2-proxy/oauth2-proxy` (pin it to
a version or digest rather than `:latest`).
To change a policy, edit its file. To add an image, copy a policy file and
change the image and repository.
@@ -472,6 +449,18 @@ image whose repository makes hardened releases, in `templates/kyverno/`:
| `hub-pipeline-monitor-hardened-images.yaml` | `ghcr.io/uug-ai/hub-pipeline-monitor` |
| `hub-pipeline-sequence-hardened-images.yaml` | `ghcr.io/uug-ai/hub-pipeline-sequence` |
| `hub-pipeline-throttler-hardened-images.yaml` | `ghcr.io/uug-ai/hub-pipeline-throttler` |
| `hub-audit-hardened-images.yaml` | `ghcr.io/uug-ai/hub-audit` (not hardened yet; always `Audit`) |
| `hub-objecttracking-hardened-images.yaml` | `ghcr.io/uug-ai/hub-objecttracking` (not hardened yet; always `Audit`) |
| `hub-vlm-hardened-images.yaml` | `ghcr.io/uug-ai/hub-vlm` (not hardened yet; always `Audit`) |
| `hub-pipeline-dominantcolors-hardened-images.yaml` | `ghcr.io/uug-ai/hub-pipeline-dominantcolors` (not hardened yet; always `Audit`) |
| `hub-pipeline-event-hardened-images.yaml` | `ghcr.io/uug-ai/hub-pipeline-event` (not hardened yet; always `Audit`) |
| `hub-pipeline-export-hardened-images.yaml` | `ghcr.io/uug-ai/hub-pipeline-export` (not hardened yet; always `Audit`) |
| `hub-pipeline-notification-hardened-images.yaml` | `ghcr.io/uug-ai/hub-pipeline-notification` (not hardened yet; always `Audit`) |
| `hub-pipeline-notification-test-hardened-images.yaml` | `ghcr.io/uug-ai/hub-pipeline-notification-test` (not hardened yet; always `Audit`) |
| `hub-pipeline-sprite-hardened-images.yaml` | `ghcr.io/uug-ai/hub-pipeline-sprite` (not hardened yet; always `Audit`) |
| `hub-pipeline-thumbnail-hardened-images.yaml` | `ghcr.io/uug-ai/hub-pipeline-thumbnail` (not hardened yet; always `Audit`) |
| `admin-hardened-images.yaml` | `ghcr.io/uug-ai/admin` (not hardened yet; always `Audit`) |
| `hub-reactivatesubscriptions-hardened-images.yaml` | `ghcr.io/uug-ai/hub-reactivatesubscriptions` (not hardened yet; always `Audit`) |
Each requires the attestation to be signed by the UUG.AI release workflow for
the image's own repository, and its `result` and `repository` to be `passed`
@@ -843,9 +832,9 @@ kerberospipeline:
| `kerberosvault.sprite.provider` | Configuration value for `kerberosvault.sprite.provider`. | `"a-sprite-provider"` |
| `kerberosvault.sprite.accessKey` | Access key for `kerberosvault.sprite`. | `"xxx"` |
| `kerberosvault.sprite.secretKey` | Secret key for `kerberosvault.sprite`. | `"xxx"` |
| `admin.repository` | Container image repository for `admin`. | `"uugai/admin"` |
| `admin.repository` | Container image repository for `admin`. | `"ghcr.io/uug-ai/admin"` |
| `admin.pullPolicy` | Image pull policy for `admin`. | `"IfNotPresent"` |
| `admin.tag` | Container image tag/version for `admin`. | `"v1.3.0"` |
| `admin.tag` | Container image tag/version for `admin`. | `"v1.4.5"` |
| `admin.replicas` | Number of replicas for `admin`. | `2` |
| `admin.logLevel` | Log verbosity level for `admin`. | `"info"` |
| `admin.resources.requests.memory` | Memory request for `admin`. | `"100Mi"` |
@@ -865,7 +854,7 @@ kerberospipeline:
| `kerberoshub.serviceAccount.labels` | Labels applied to `kerberoshub.serviceAccount` resources. | `""` |
| `kerberoshub.api.repository` | The Docker registry where the Kerberos Hub API container is hosted. | `"ghcr.io/uug-ai/hub-api"` |
| `kerberoshub.api.pullPolicy` | The Docker registry pull policy. | `"IfNotPresent"` |
| `kerberoshub.api.tag` | The Docker image tag/version. | `"v1.9.8"` |
| `kerberoshub.api.tag` | The Docker image tag/version. | `"v1.11.41"` |
| `kerberoshub.api.replicas` | The number of pods/replicas running for the Kerberos Hub API deployment. | `2` |
| `kerberoshub.api.audit.enabled` | Enable audit publishing from Hub API when global auditing is enabled. | `true` |
| `kerberoshub.api.logLevel` | Log verbosity level for `kerberoshub.api`. | `"info"` |
@@ -923,7 +912,7 @@ kerberospipeline:
| `kerberoshub.api.sso.extraHeaders.value` | Header value for each configured SSO extra header entry. | `""` |
| `kerberoshub.frontend.repository` | The Docker registry where the Kerberos Hub frontend is hosted. | `"ghcr.io/uug-ai/hub-frontend"` |
| `kerberoshub.frontend.pullPolicy` | The Docker registry pull policy. | `"IfNotPresent"` |
| `kerberoshub.frontend.tag` | The Docker image tag/version. | `"v1.9.11"` |
| `kerberoshub.frontend.tag` | The Docker image tag/version. | `"v1.19.35"` |
| `kerberoshub.frontend.replicas` | The number of pods/replicas running for the Kerberos Hub frontend deployment. | `2` |
| `kerberoshub.frontend.logLevel` | Log verbosity level for `kerberoshub.frontend`. | `"info"` |
| `kerberoshub.frontend.schema` | The protocol to serve the Kerberos Hub frontend, `'http'` or `'https'`. | `"https"` |
@@ -1047,7 +1036,7 @@ kerberospipeline:
| `kerberoshub.oauth2Proxy.github.team` | Team value used by `kerberoshub.oauth2Proxy.github`. | `"github-team"` |
| `kerberoshub.cleanup.repository` | The Docker container that is responsible for cleaning up the Kerberos Hub API content and related MongoDB collections. | `"ghcr.io/uug-ai/hub-cleanup"` |
| `kerberoshub.cleanup.pullPolicy` | The Docker registry pull policy. | `"IfNotPresent"` |
| `kerberoshub.cleanup.tag` | The Docker image tag/version. | `"v1.4.13"` |
| `kerberoshub.cleanup.tag` | The Docker image tag/version. | `"v1.4.27"` |
| `kerberoshub.cleanup.replicas` | Number of replicas for `kerberoshub.cleanup`. | `1` |
| `kerberoshub.cleanup.mode` | Cleanup service mode: `serve`, `dry-run`, or `version`. | `"serve"` |
| `kerberoshub.cleanup.logLevel` | Log verbosity level for `kerberoshub.cleanup`. | `"info"` |
@@ -1075,7 +1064,7 @@ kerberospipeline:
| `kerberoshub.cleanup.resources.requests.cpu` | CPU request for `kerberoshub.cleanup`. | `"10m"` |
| `kerberoshub.audit.repository` | Hub audit service container image repository. | `"ghcr.io/uug-ai/hub-audit"` |
| `kerberoshub.audit.pullPolicy` | Hub audit service image pull policy. | `"IfNotPresent"` |
| `kerberoshub.audit.tag` | Hub audit service image tag. S3 destinations need v1.0.9 or later, and `s3.allowUnlockedBucket` needs v1.0.10. | `"v1.0.10"` |
| `kerberoshub.audit.tag` | Hub audit service image tag. S3 destinations need v1.0.9 or later, and `s3.allowUnlockedBucket` needs v1.0.10. | `"v1.0.11"` |
| `kerberoshub.audit.replicas` | Number of audit service replicas. Per-destination MongoDB leases prevent concurrent delivery. | `1` |
| `kerberoshub.audit.dispatchInterval` | How often the mounted destination configuration is reloaded and eligible destinations are polled. | `"5s"` |
| `kerberoshub.audit.leaseDuration` | Per-destination lease duration. It must exceed every destination timeout by at least 30 seconds. | `"2m"` |
@@ -1113,7 +1102,7 @@ kerberospipeline:
| `kerberoshub.audit.topologySpreadConstraints` | Topology spread constraints for audit service pods. | `[]` |
| `kerberoshub.monitordevice.repository` | The monitoring microservice, following up the status of your cameras and Kerberos Agents. | `"ghcr.io/uug-ai/hub-monitor-device"` |
| `kerberoshub.monitordevice.pullPolicy` | The Docker registry pull policy. | `"IfNotPresent"` |
| `kerberoshub.monitordevice.tag` | The Docker image tag/version. | `"v1.4.0"` |
| `kerberoshub.monitordevice.tag` | The Docker image tag/version. | `"v1.4.15"` |
| `kerberoshub.monitordevice.replicas` | Number of replicas for `kerberoshub.monitordevice`. | `1` |
| `kerberoshub.monitordevice.logLevel` | Log verbosity level for `kerberoshub.monitordevice`. | `"info"` |
| `kerberoshub.monitordevice.scanIntervalSeconds` | Seconds between device status scans. Sets how quickly a camera going offline or online is detected. For accounts with "Group notifications" on, `hub-monitor-device` v1.4.10 and later then hold a change 20 seconds (`DEVICE_GROUPING_HOLD_SECONDS`) to collect other cameras that change status at the same time; older releases hold it one scan. | `60` |
@@ -1126,45 +1115,36 @@ kerberospipeline:
| `kerberoshub.reactivate.logLevel` | Log verbosity level for `kerberoshub.reactivate`. | `"info"` |
| `kerberoshub.reactivate.resources.requests.memory` | Memory request for `kerberoshub.reactivate`. | `"10Mi"` |
| `kerberoshub.reactivate.resources.requests.cpu` | CPU request for `kerberoshub.reactivate`. | `"10m"` |
| `kerberoshub.forwarder.enabled` | Enable or disable the Hub forwarder component. | `false` |
| `kerberoshub.proxy.enabled` | Enable or disable the legacy Hub proxy Deployment and LoadBalancer Service. | `false` |
| `kerberoshub.proxy.repository` | Container image repository for `kerberoshub.proxy`. | `"uugai/hub-proxy"` |
| `kerberoshub.proxy.pullPolicy` | Image pull policy for `kerberoshub.proxy`. | `"IfNotPresent"` |
| `kerberoshub.proxy.tag` | Container image tag/version for `kerberoshub.proxy`. | `"v1.0.0"` |
| `kerberoshub.proxy.replicas` | Number of replicas for `kerberoshub.proxy` when enabled. | `0` |
| `kerberoshub.proxy.logLevel` | Log verbosity level for `kerberoshub.proxy`. | `"info"` |
| `kerberoshub.proxy.resources.requests.memory` | Memory request for `kerberoshub.proxy`. | `"10Mi"` |
| `kerberoshub.proxy.resources.requests.cpu` | CPU request for `kerberoshub.proxy`. | `"10m"` |
| `kerberospipeline.event.repository` | The [event orchestration](https://doc.kerberos.io/hub/pipeline/#orchestrator) microservice. | `"ghcr.io/uug-ai/hub-pipeline-event"` |
| `kerberospipeline.event.pullPolicy` | The Docker registry pull policy. | `"IfNotPresent"` |
| `kerberospipeline.event.tag` | The Docker image tag/version. | `"v1.3.0"` |
| `kerberospipeline.event.tag` | The Docker image tag/version. | `"v1.3.10"` |
| `kerberospipeline.event.replicas` | Number of replicas for `kerberospipeline.event`. | `1` |
| `kerberospipeline.event.logLevel` | Log verbosity level for `kerberospipeline.event`. | `"info"` |
| `kerberospipeline.event.resources.requests.memory` | Memory request for `kerberospipeline.event`. | `"10Mi"` |
| `kerberospipeline.event.resources.requests.cpu` | CPU request for `kerberospipeline.event`. | `"10m"` |
| `kerberospipeline.monitor.repository` | The [monitoring microservice](https://doc.kerberos.io/hub/pipeline/#monitoring), calculating metrics of incoming messages. | `"ghcr.io/uug-ai/hub-pipeline-monitor"` |
| `kerberospipeline.monitor.pullPolicy` | The Docker registry pull policy. | `"IfNotPresent"` |
| `kerberospipeline.monitor.tag` | The Docker image tag/version. | `"v1.3.9"` |
| `kerberospipeline.monitor.tag` | The Docker image tag/version. | `"v1.3.30"` |
| `kerberospipeline.monitor.replicas` | Number of replicas for `kerberospipeline.monitor`. | `1` |
| `kerberospipeline.monitor.logLevel` | Monitor log level. Set to `debug` for per-event processing checkpoints. | `"info"` |
| `kerberospipeline.monitor.resources.requests.memory` | Memory request for `kerberospipeline.monitor`. | `"10Mi"` |
| `kerberospipeline.monitor.resources.requests.cpu` | CPU request for `kerberospipeline.monitor`. | `"10m"` |
| `kerberospipeline.sequence.repository` | The [sequencer microservice](https://doc.kerberos.io/hub/pipeline/#sequencer), grouping recordings in chunks/groups. | `"ghcr.io/uug-ai/hub-pipeline-sequence"` |
| `kerberospipeline.sequence.pullPolicy` | The Docker registry pull policy. | `"IfNotPresent"` |
| `kerberospipeline.sequence.tag` | The Docker image tag/version. | `"v1.6.18"` |
| `kerberospipeline.sequence.tag` | The Docker image tag/version. | `"v1.7.15"` |
| `kerberospipeline.sequence.replicas` | Number of replicas for `kerberospipeline.sequence`. | `1` |
| `kerberospipeline.sequence.resources.requests.memory` | Memory request for `kerberospipeline.sequence`. | `"10Mi"` |
| `kerberospipeline.sequence.resources.requests.cpu` | CPU request for `kerberospipeline.sequence`. | `"10m"` |
| `kerberospipeline.throttler.repository` | The [throttler microservice](https://doc.kerberos.io/hub/pipeline/#throttler), throttling events. | `"uugai/hub-pipeline-throttler"` |
| `kerberospipeline.throttler.pullPolicy` | The Docker registry pull policy. | `"IfNotPresent"` |
| `kerberospipeline.throttler.tag` | The Docker image tag/version. | `"v1.2.0"` |
| `kerberospipeline.throttler.tag` | The Docker image tag/version. | `"v1.2.11"` |
| `kerberospipeline.throttler.replicas` | Number of replicas for `kerberospipeline.throttler`. | `1` |
| `kerberospipeline.throttler.logLevel` | Log verbosity level for `kerberospipeline.throttler`. | `"info"` |
| `kerberospipeline.throttler.resources.requests.memory` | Memory request for `kerberospipeline.throttler`. | `"10Mi"` |
| `kerberospipeline.throttler.resources.requests.cpu` | CPU request for `kerberospipeline.throttler`. | `"10m"` |
| `kerberospipeline.notify.repository` | The [notification microservice](https://doc.kerberos.io/hub/pipeline/#notification), sending notifications on events. | `"ghcr.io/uug-ai/hub-pipeline-notification"` |
| `kerberospipeline.notify.pullPolicy` | The Docker registry pull policy. | `"IfNotPresent"` |
| `kerberospipeline.notify.tag` | The Docker image tag/version. | `"v1.3.9"` |
| `kerberospipeline.notify.tag` | The Docker image tag/version. | `"v1.3.48"` |
| `kerberospipeline.notify.replicas` | Number of replicas for `kerberospipeline.notify`. | `1` |
| `kerberospipeline.notify.audit.enabled` | Enable audit publishing from the notification worker when global auditing is enabled. | `true` |
| `kerberospipeline.notify.logLevel` | Log verbosity level for `kerberospipeline.notify`. | `"info"` |
@@ -1173,13 +1153,13 @@ kerberospipeline:
| `kerberospipeline.notify.resources.requests.cpu` | CPU request for `kerberospipeline.notify`. | `"10m"` |
| `kerberospipeline.notifyTest.repository` | The notification service for testing, the different channels. | `"uugai/hub-pipeline-notification-test"` |
| `kerberospipeline.notifyTest.pullPolicy` | The Docker registry pull policy. | `"IfNotPresent"` |
| `kerberospipeline.notifyTest.tag` | The Docker image tag/version. | `"v1.2.1"` |
| `kerberospipeline.notifyTest.tag` | The Docker image tag/version. | `"v1.2.7"` |
| `kerberospipeline.notifyTest.replicas` | Number of replicas for `kerberospipeline.notifyTest`. | `1` |
| `kerberospipeline.notifyTest.resources.requests.memory` | Memory request for `kerberospipeline.notifyTest`. | `"10Mi"` |
| `kerberospipeline.notifyTest.resources.requests.cpu` | CPU request for `kerberospipeline.notifyTest`. | `"10m"` |
| `kerberospipeline.analysis.repository` | The [analysis microservices](https://doc.kerberos.io/hub/pipeline/#analyser) which executed specific analysis in parallel. | `"ghcr.io/uug-ai/hub-pipeline-analysis"` |
| `kerberospipeline.analysis.pullPolicy` | The Docker registry pull policy. | `"IfNotPresent"` |
| `kerberospipeline.analysis.tag` | The Docker image tag/version. | `"v1.7.8"` |
| `kerberospipeline.analysis.tag` | The Docker image tag/version. | `"v1.8.31"` |
| `kerberospipeline.analysis.replicas` | Number of replicas for `kerberospipeline.analysis`. | `1` |
| `kerberospipeline.analysis.logLevel` | Log verbosity level for `kerberospipeline.analysis`. | `"info"` |
| `kerberospipeline.analysis.thumbnailRegeneration.enabled` | Regenerate thumbnails from the first frame of a classified moving object (`THUMBNAIL_REGENERATION_ENABLED`). Adds up to one thumbnail job per classified recording. Requires an analysis image that reads the flag. | `false` |
@@ -1191,7 +1171,7 @@ kerberospipeline:
| `kerberospipeline.dominantColor.enabled` | Deploy `pipe-dominantcolor` and let the analysis stage schedule it (`DOMINANTCOLOR_ENABLED`). Requires an analysis image that reads the flag. | `false` |
| `kerberospipeline.dominantColor.repository` | The dominant color microservices is computing a top 3 color histogram. | `"ghcr.io/uug-ai/hub-pipeline-dominantcolors"` |
| `kerberospipeline.dominantColor.pullPolicy` | The Docker registry pull policy. | `"IfNotPresent"` |
| `kerberospipeline.dominantColor.tag` | The Docker image tag/version. | `"v2.0.2"` |
| `kerberospipeline.dominantColor.tag` | The Docker image tag/version. | `"v2.0.10"` |
| `kerberospipeline.dominantColor.replicas` | Number of replicas for `kerberospipeline.dominantColor`. | `3` |
| `kerberospipeline.dominantColor.logLevel` | Log verbosity level for `kerberospipeline.dominantColor`. | `"info"` |
| `kerberospipeline.dominantColor.resources.requests.memory` | Memory request for `kerberospipeline.dominantColor`. | `"512Mi"` |
@@ -1200,7 +1180,7 @@ kerberospipeline:
| `kerberospipeline.dominantColor.resources.limits.cpu` | CPU limit for `kerberospipeline.dominantColor`. | `"1000m"` |
| `kerberospipeline.thumbnail.repository` | The thumbnail microservices generated a thumbnail for a recordings. | `"ghcr.io/uug-ai/hub-pipeline-thumbnail"` |
| `kerberospipeline.thumbnail.pullPolicy` | The Docker registry pull policy. | `"IfNotPresent"` |
| `kerberospipeline.thumbnail.tag` | The Docker image tag/version. | `"v1.3.4"` |
| `kerberospipeline.thumbnail.tag` | The Docker image tag/version. | `"v1.3.24"` |
| `kerberospipeline.thumbnail.replicas` | Number of replicas for `kerberospipeline.thumbnail`. | `2` |
| `kerberospipeline.thumbnail.prefetchCount` | Max unacknowledged RabbitMQ messages per pod (`RABBITMQ_PREFETCH_COUNT`); `0` keeps the service default of 5. Requires hub-pipeline-thumbnail ≥ v1.3.15. | `0` |
| `kerberospipeline.sprite.prefetchCount` | Max unacknowledged RabbitMQ messages per pod (`RABBITMQ_PREFETCH_COUNT`); `0` keeps the service default of 5. Requires hub-pipeline-sprite ≥ v1.1.21. | `0` |
@@ -1215,7 +1195,7 @@ kerberospipeline:
| `kerberospipeline.thumbnail.resources.limits.cpu` | CPU limit for `kerberospipeline.thumbnail`. | `"1000m"` |
| `kerberospipeline.counting.repository` | The counting microservices computes objects passing different line segments. | `"uugai/hub-pipeline-counting"` |
| `kerberospipeline.counting.pullPolicy` | The Docker registry pull policy. | `"IfNotPresent"` |
| `kerberospipeline.counting.tag` | The Docker image tag/version. | `"v1.6.3"` |
| `kerberospipeline.counting.tag` | The Docker image tag/version. | `"v2.0.7"` |
| `kerberospipeline.counting.replicas` | Number of replicas for `kerberospipeline.counting`. | `1` |
| `kerberospipeline.counting.logLevel` | Log verbosity level for `kerberospipeline.counting`. | `"info"` |
| `kerberospipeline.counting.resources.requests.memory` | Memory request for `kerberospipeline.counting`. | `"10Mi"` |
@@ -1223,7 +1203,7 @@ kerberospipeline:
| `kerberospipeline.sprite.enabled` | Enable or disable `kerberospipeline.sprite`. | `false` |
| `kerberospipeline.sprite.repository` | Container image repository for `kerberospipeline.sprite`. | `"ghcr.io/uug-ai/hub-pipeline-sprite"` |
| `kerberospipeline.sprite.pullPolicy` | Image pull policy for `kerberospipeline.sprite`. | `"IfNotPresent"` |
| `kerberospipeline.sprite.tag` | Container image tag/version for `kerberospipeline.sprite`. | `"v1.1.12"` |
| `kerberospipeline.sprite.tag` | Container image tag/version for `kerberospipeline.sprite`. | `"v1.1.28"` |
| `kerberospipeline.sprite.replicas` | Number of replicas for `kerberospipeline.sprite`. | `5` |
| `kerberospipeline.sprite.logLevel` | Log verbosity level for `kerberospipeline.sprite`. | `"info"` |
| `kerberospipeline.sprite.interval` | Configuration value for `kerberospipeline.sprite.interval`. | `"1"` |
@@ -1235,7 +1215,7 @@ kerberospipeline:
| `kerberospipeline.sprite.resources.limits.cpu` | CPU limit for `kerberospipeline.sprite`. | `"1000m"` |
| `kerberospipeline.export.repository` | Container image repository for `kerberospipeline.export`. | `"ghcr.io/uug-ai/hub-pipeline-export"` |
| `kerberospipeline.export.pullPolicy` | Image pull policy for `kerberospipeline.export`. | `"IfNotPresent"` |
| `kerberospipeline.export.tag` | Container image tag/version for `kerberospipeline.export`. | `"v1.2.4"` |
| `kerberospipeline.export.tag` | Container image tag/version for `kerberospipeline.export`. | `"v1.2.22"` |
| `kerberospipeline.export.replicas` | Number of replicas for `kerberospipeline.export`. | `2` |
| `kerberospipeline.export.logLevel` | Log verbosity level for `kerberospipeline.export`. | `"info"` |
| `kerberospipeline.export.resources.requests.memory` | Memory request for `kerberospipeline.export`. | `"10Mi"` |
@@ -1271,9 +1251,6 @@ kerberospipeline:
| `email.templates.recordingTitle` | Email subject for recording check alerts. Empty uses "[Device] A camera stopped recording", "[Device] A camera is recording again" and their forms for several cameras. | `""` |
| `email.mailgun.apiKey` | The Mailgun API key linked to your Mailgun domain. | `""` |
| `imagePullSecrets.name` | Docker registry secret name, which is also granted with the license. This allows you to download the Docker images. | `""` |
| `kerberoshub.forwarder.pullPolicy` | The Docker registry pull policy. | `""` |
| `kerberoshub.forwarder.repository` | The Docker container which orchestrates forwarding coming from different Kerberos Vaults. | `""` |
| `kerberoshub.forwarder.tag` | The Docker image tag/version. | `""` |
| `kerberoshub.frontend.ssoDomain` | The domain that's being used to activate SSO from the login page. | `""` |
| `kerberoshub.frontend.stripe.apikey` | If using the public version, `stripe` can be used for automated billing and subscriptions. | `""` |
@@ -1,76 +0,0 @@
# If .Values.kerberoshub.forwarder.enabled is set to true
{{- if and (eq .Values.mode "all") .Values.kerberoshub.forwarder.enabled }}
apiVersion: apps/v1
kind: Deployment
metadata:
name: vault-forwarder
namespace: {{ .Release.Namespace }}
spec:
replicas: 1
selector:
matchLabels:
app: vault-forwarder
minReadySeconds: 10
strategy:
type: RollingUpdate
rollingUpdate:
maxUnavailable: 1
maxSurge: 1
template:
metadata:
annotations:
checksum/config: {{ include (print $.Template.BasePath "/configMaps/configmap-mongodb.yaml") . | sha256sum }}
labels:
app: vault-forwarder
spec:
{{- with .Values.imagePullSecrets }}
imagePullSecrets:
{{- toYaml . | nindent 8 }}
{{- end }}
{{- $mongodbTLS := .Values.mongodb.tls }}
{{- if or .Values.kerberoshub.forwarder.volumes (and $mongodbTLS.enabled $mongodbTLS.existingSecret) }}
volumes:
{{- with .Values.kerberoshub.forwarder.volumes }}
{{- toYaml . | nindent 8 }}
{{- end }}
{{- if and $mongodbTLS.enabled $mongodbTLS.existingSecret }}
{{- include "hub.mongodb.tlsVolume" . | nindent 8 }}
{{- end }}
{{- end }}
{{- with .Values.kerberoshub.forwarder.topologySpreadConstraints }}
topologySpreadConstraints:
{{- toYaml . | nindent 8 }}
{{- end }}
containers:
- name: vault-forwarder
image: "{{ .Values.global.imageRegistry }}{{ .Values.kerberoshub.forwarder.repository }}:{{ .Values.kerberoshub.forwarder.tag }}"
imagePullPolicy: {{ .Values.kerberoshub.forwarder.pullPolicy }}
resources:
requests:
memory: 10Mi
cpu: 10m
{{- if or .Values.kerberoshub.forwarder.volumeMounts (and $mongodbTLS.enabled $mongodbTLS.existingSecret) }}
volumeMounts:
{{- with .Values.kerberoshub.forwarder.volumeMounts }}
{{- toYaml . | nindent 12 }}
{{- end }}
{{- if and $mongodbTLS.enabled $mongodbTLS.existingSecret }}
{{- include "hub.mongodb.tlsVolumeMount" . | nindent 12 }}
{{- end }}
{{- end }}
envFrom:
- configMapRef:
name: mongodb-config
env:
{{- include "hub.mongodb.appUriEnv" (dict "root" $ "app" "vault-forwarder") | nindent 10 }}
- name: ITERATION_SPEED
value: "5"
- name: BUFFER_TIME
value: "3"
- name: MQTT_URI
value: "{{ .Values.mqtt.host }}"
- name: MQTT_USERNAME
value: "{{ .Values.mqtt.username }}"
- name: MQTT_PASSWORD
value: "{{ .Values.mqtt.password }}"
{{- end }}
@@ -1,78 +0,0 @@
{{- if and (eq .Values.mode "all") .Values.kerberoshub.proxy.enabled -}}
apiVersion: apps/v1
kind: Deployment
metadata:
name: vault-proxy
namespace: {{ .Release.Namespace }}
spec:
replicas: {{ .Values.kerberoshub.proxy.replicas }}
selector:
matchLabels:
app: vault-proxy
minReadySeconds: 10
strategy:
type: RollingUpdate
rollingUpdate:
maxUnavailable: 1
maxSurge: 1
template:
metadata:
labels:
app: vault-proxy
spec:
{{- with .Values.imagePullSecrets }}
imagePullSecrets:
{{- toYaml . | nindent 8 }}
{{- end }}
{{- with .Values.kerberoshub.proxy.volumes }}
volumes:
{{- toYaml . | nindent 8 }}
{{- end }}
{{- with .Values.kerberoshub.proxy.topologySpreadConstraints }}
topologySpreadConstraints:
{{- toYaml . | nindent 8 }}
{{- end }}
containers:
- name: vault-proxy
image: "{{ .Values.global.imageRegistry }}{{ .Values.kerberoshub.proxy.repository }}:{{ .Values.kerberoshub.proxy.tag }}"
imagePullPolicy: {{ .Values.kerberoshub.proxy.pullPolicy }}
{{- with .Values.kerberoshub.proxy.volumeMounts }}
volumeMounts:
{{- toYaml . | nindent 12 }}
{{- end }}
ports:
- containerPort: 8080
name: http
env:
- name: LOG_LEVEL
value: "{{ .Values.kerberoshub.proxy.logLevel }}"
# Kerberos Hub API
- name: KERBEROS_API_CHECK_SUBSCRIPTION
value: "{{ .Values.kerberoshub.api.schema }}://{{ .Values.kerberoshub.api.url }}/user/has-subscription"
# Kerberos Vault
- name: KSTORAGE_URI
value: "{{ .Values.kerberosvault.uri }}/storage"
- name: KSTORAGE_ACCESSKEY
value: "{{ .Values.kerberosvault.accesskey }}"
- name: KSTORAGE_SECRET
value: "{{ .Values.kerberosvault.secretkey }}"
- name: KSTORAGE_PROVIDER
value: "{{ .Values.kerberosvault.provider }}"
---
apiVersion: v1
kind: Service
metadata:
name: vault-proxy-svc
namespace: {{ .Release.Namespace }}
labels:
app: vault-proxy-svc
spec:
type: LoadBalancer
ports:
- protocol: TCP
port: 80
targetPort: 8080
name: http
selector:
app: vault-proxy
{{- end }}
@@ -0,0 +1,68 @@
{{- /*
admin images must come from a hardened release: they carry the signed
image-hardening attestation (result "passed") that the UUG.AI release workflow
adds after all hardening gates pass, for uug-ai/admin.
The signature itself is checked by admin-signed-images.yaml.
A namespaced Policy, so it applies only to the release namespace.
Rendered only when imageHardening.enabled is true and Kyverno is installed.
*/ -}}
{{- if and .Values.imageHardening.enabled (.Capabilities.APIVersions.Has "kyverno.io/v1") }}
apiVersion: kyverno.io/v1
kind: Policy
metadata:
name: admin-hardened-images
annotations:
policies.kyverno.io/title: admin images must come from a hardened UUG.AI release
policies.kyverno.io/category: Image hardening
policies.kyverno.io/severity: medium
policies.kyverno.io/subject: Pod
# Kyverno defaults apply: background scans of running pods, attestation required.
# Only settings whose Kyverno default would change behaviour are set below.
spec:
# Not hardened yet: uug-ai/admin has no hardened release with the
# image-hardening attestation. Only ghcr.io/uug-ai/admin is trusted.
# This policy reports that gap and stays in Audit, even when
# imageHardening.validationFailureAction is Enforce.
validationFailureAction: Audit
# Kyverno's default (Fail) would stop admin pods starting while Kyverno is down.
failurePolicy: Ignore
# Verifying against GHCR and Rekor can exceed the 10s default.
webhookTimeoutSeconds: 30
rules:
- name: verify-admin-hardened
match:
any:
- resources:
kinds:
- Pod
verifyImages:
- imageReferences:
- "ghcr.io/uug-ai/admin:*"
- "ghcr.io/uug-ai/admin@*"
# Kyverno's defaults (true) would rewrite pod images to digests and
# report every tag-based image; enable together with Enforce.
mutateDigest: false
verifyDigest: false
attestations:
- type: https://github.com/uug-ai/workflows/attestations/image-hardening/v1
attestors:
- entries:
- keyless:
issuer: https://token.actions.githubusercontent.com
# The UUG.AI release workflow, at a branch/tag ref or a commit.
subjectRegExp: '^https://github\.com/uug-ai/workflows/\.github/workflows/release-create\.yml@(refs/.+|[0-9a-f]{40})$'
additionalExtensions:
githubWorkflowRepository: uug-ai/admin
rekor:
url: https://rekor.sigstore.dev
# Fields of the attestation's predicate. {{`{{ ... }}`}} is Kyverno
# syntax, escaped so Helm leaves it alone.
conditions:
- all:
- key: "{{`{{ result }}`}}"
operator: Equals
value: passed
- key: "{{`{{ repository }}`}}"
operator: Equals
value: uug-ai/admin
{{- end }}
@@ -0,0 +1,57 @@
{{- /*
admin images must be signed by UUG.AI: a keyless cosign signature issued by
GitHub Actions, made by the UUG.AI release workflow, for uug-ai/admin.
A namespaced Policy, so it applies only to the release namespace.
Rendered only when imageVerification.enabled is true and Kyverno is installed.
*/ -}}
{{- if and .Values.imageVerification.enabled (.Capabilities.APIVersions.Has "kyverno.io/v1") }}
apiVersion: kyverno.io/v1
kind: Policy
metadata:
name: admin-signed-images
annotations:
policies.kyverno.io/title: admin images must be signed by UUG.AI
policies.kyverno.io/category: Image signing
policies.kyverno.io/severity: high
policies.kyverno.io/subject: Pod
# Kyverno defaults apply: background scans of running pods, signature required.
# Only settings whose Kyverno default would change behaviour are set below.
spec:
# Only ghcr.io/uug-ai/admin is trusted. The chart's default image comes from
# Docker Hub (not matched here; reported by trusted-registry.yaml); switch it to
# the signed ghcr.io/uug-ai/admin release.
# This policy reports that gap and stays in Audit, even when
# imageVerification.validationFailureAction is Enforce.
validationFailureAction: Audit
# Kyverno's default (Fail) would stop admin pods starting while Kyverno is down.
failurePolicy: Ignore
# Verifying against GHCR and Rekor can exceed the 10s default.
webhookTimeoutSeconds: 30
rules:
- name: verify-admin
match:
any:
- resources:
kinds:
- Pod
verifyImages:
- imageReferences:
- "ghcr.io/uug-ai/admin:*"
- "ghcr.io/uug-ai/admin@*"
# Kyverno's defaults (true) would rewrite pod images to digests and
# report every tag-based image; enable together with Enforce.
mutateDigest: false
verifyDigest: false
attestors:
- entries:
- keyless:
issuer: https://token.actions.githubusercontent.com
# The UUG.AI release workflow, at a branch/tag ref or a commit.
subjectRegExp: '^https://github\.com/uug-ai/workflows/\.github/workflows/release-create\.yml@(refs/.+|[0-9a-f]{40})$'
additionalExtensions:
# That workflow signs for every UUG.AI repository; this
# binds the signature to uug-ai/admin.
githubWorkflowRepository: uug-ai/admin
rekor:
url: https://rekor.sigstore.dev
{{- end }}
@@ -0,0 +1,69 @@
{{- /*
hub-audit images must come from a hardened release: they carry the signed
image-hardening attestation (result "passed") that the UUG.AI release workflow
adds after all hardening gates pass, for uug-ai/hub-audit.
The signature itself is checked by hub-audit-signed-images.yaml.
A namespaced Policy, so it applies only to the release namespace.
Rendered only when imageHardening.enabled is true and Kyverno is installed.
*/ -}}
{{- if and .Values.imageHardening.enabled (.Capabilities.APIVersions.Has "kyverno.io/v1") }}
apiVersion: kyverno.io/v1
kind: Policy
metadata:
name: hub-audit-hardened-images
annotations:
policies.kyverno.io/title: hub-audit images must come from a hardened UUG.AI release
policies.kyverno.io/category: Image hardening
policies.kyverno.io/severity: medium
policies.kyverno.io/subject: Pod
# Kyverno defaults apply: background scans of running pods, attestation required.
# Only settings whose Kyverno default would change behaviour are set below.
spec:
# Not hardened yet: uug-ai/hub-audit has no hardened release with the
# image-hardening attestation (the image does not meet the hardened contract
# yet). This policy reports that gap and stays in Audit, even when
# imageHardening.validationFailureAction is Enforce. Once its releases are
# hardened, use the same line as hub-api-hardened-images.yaml.
validationFailureAction: Audit
# Kyverno's default (Fail) would stop hub-audit pods starting while Kyverno is down.
failurePolicy: Ignore
# Verifying against GHCR and Rekor can exceed the 10s default.
webhookTimeoutSeconds: 30
rules:
- name: verify-hub-audit-hardened
match:
any:
- resources:
kinds:
- Pod
verifyImages:
- imageReferences:
- "ghcr.io/uug-ai/hub-audit:*"
- "ghcr.io/uug-ai/hub-audit@*"
# Kyverno's defaults (true) would rewrite pod images to digests and
# report every tag-based image; enable together with Enforce.
mutateDigest: false
verifyDigest: false
attestations:
- type: https://github.com/uug-ai/workflows/attestations/image-hardening/v1
attestors:
- entries:
- keyless:
issuer: https://token.actions.githubusercontent.com
# The UUG.AI release workflow, at a branch/tag ref or a commit.
subjectRegExp: '^https://github\.com/uug-ai/workflows/\.github/workflows/release-create\.yml@(refs/.+|[0-9a-f]{40})$'
additionalExtensions:
githubWorkflowRepository: uug-ai/hub-audit
rekor:
url: https://rekor.sigstore.dev
# Fields of the attestation's predicate. {{`{{ ... }}`}} is Kyverno
# syntax, escaped so Helm leaves it alone.
conditions:
- all:
- key: "{{`{{ result }}`}}"
operator: Equals
value: passed
- key: "{{`{{ repository }}`}}"
operator: Equals
value: uug-ai/hub-audit
{{- end }}
@@ -0,0 +1,69 @@
{{- /*
hub-objecttracking images must come from a hardened release: they carry the signed
image-hardening attestation (result "passed") that the UUG.AI release workflow
adds after all hardening gates pass, for uug-ai/hub-objecttracking.
The signature itself is checked by hub-objecttracking-signed-images.yaml.
A namespaced Policy, so it applies only to the release namespace.
Rendered only when imageHardening.enabled is true and Kyverno is installed.
*/ -}}
{{- if and .Values.imageHardening.enabled (.Capabilities.APIVersions.Has "kyverno.io/v1") }}
apiVersion: kyverno.io/v1
kind: Policy
metadata:
name: hub-objecttracking-hardened-images
annotations:
policies.kyverno.io/title: hub-objecttracking images must come from a hardened UUG.AI release
policies.kyverno.io/category: Image hardening
policies.kyverno.io/severity: medium
policies.kyverno.io/subject: Pod
# Kyverno defaults apply: background scans of running pods, attestation required.
# Only settings whose Kyverno default would change behaviour are set below.
spec:
# Not hardened yet: uug-ai/hub-objecttracking has no hardened release with the
# image-hardening attestation (the image does not meet the hardened contract
# yet). This policy reports that gap and stays in Audit, even when
# imageHardening.validationFailureAction is Enforce. Once its releases are
# hardened, use the same line as hub-api-hardened-images.yaml.
validationFailureAction: Audit
# Kyverno's default (Fail) would stop hub-objecttracking pods starting while Kyverno is down.
failurePolicy: Ignore
# Verifying against GHCR and Rekor can exceed the 10s default.
webhookTimeoutSeconds: 30
rules:
- name: verify-hub-objecttracking-hardened
match:
any:
- resources:
kinds:
- Pod
verifyImages:
- imageReferences:
- "ghcr.io/uug-ai/hub-objecttracking:*"
- "ghcr.io/uug-ai/hub-objecttracking@*"
# Kyverno's defaults (true) would rewrite pod images to digests and
# report every tag-based image; enable together with Enforce.
mutateDigest: false
verifyDigest: false
attestations:
- type: https://github.com/uug-ai/workflows/attestations/image-hardening/v1
attestors:
- entries:
- keyless:
issuer: https://token.actions.githubusercontent.com
# The UUG.AI release workflow, at a branch/tag ref or a commit.
subjectRegExp: '^https://github\.com/uug-ai/workflows/\.github/workflows/release-create\.yml@(refs/.+|[0-9a-f]{40})$'
additionalExtensions:
githubWorkflowRepository: uug-ai/hub-objecttracking
rekor:
url: https://rekor.sigstore.dev
# Fields of the attestation's predicate. {{`{{ ... }}`}} is Kyverno
# syntax, escaped so Helm leaves it alone.
conditions:
- all:
- key: "{{`{{ result }}`}}"
operator: Equals
value: passed
- key: "{{`{{ repository }}`}}"
operator: Equals
value: uug-ai/hub-objecttracking
{{- end }}
@@ -0,0 +1,69 @@
{{- /*
hub-pipeline-dominantcolors images must come from a hardened release: they carry the signed
image-hardening attestation (result "passed") that the UUG.AI release workflow
adds after all hardening gates pass, for uug-ai/hub-pipeline-dominantcolors.
The signature itself is checked by hub-pipeline-dominantcolors-signed-images.yaml.
A namespaced Policy, so it applies only to the release namespace.
Rendered only when imageHardening.enabled is true and Kyverno is installed.
*/ -}}
{{- if and .Values.imageHardening.enabled (.Capabilities.APIVersions.Has "kyverno.io/v1") }}
apiVersion: kyverno.io/v1
kind: Policy
metadata:
name: hub-pipeline-dominantcolors-hardened-images
annotations:
policies.kyverno.io/title: hub-pipeline-dominantcolors images must come from a hardened UUG.AI release
policies.kyverno.io/category: Image hardening
policies.kyverno.io/severity: medium
policies.kyverno.io/subject: Pod
# Kyverno defaults apply: background scans of running pods, attestation required.
# Only settings whose Kyverno default would change behaviour are set below.
spec:
# Not hardened yet: uug-ai/hub-pipeline-dominantcolors has no hardened release with the
# image-hardening attestation (the image does not meet the hardened contract
# yet). This policy reports that gap and stays in Audit, even when
# imageHardening.validationFailureAction is Enforce. Once its releases are
# hardened, use the same line as hub-api-hardened-images.yaml.
validationFailureAction: Audit
# Kyverno's default (Fail) would stop hub-pipeline-dominantcolors pods starting while Kyverno is down.
failurePolicy: Ignore
# Verifying against GHCR and Rekor can exceed the 10s default.
webhookTimeoutSeconds: 30
rules:
- name: verify-hub-pipeline-dominantcolors-hardened
match:
any:
- resources:
kinds:
- Pod
verifyImages:
- imageReferences:
- "ghcr.io/uug-ai/hub-pipeline-dominantcolors:*"
- "ghcr.io/uug-ai/hub-pipeline-dominantcolors@*"
# Kyverno's defaults (true) would rewrite pod images to digests and
# report every tag-based image; enable together with Enforce.
mutateDigest: false
verifyDigest: false
attestations:
- type: https://github.com/uug-ai/workflows/attestations/image-hardening/v1
attestors:
- entries:
- keyless:
issuer: https://token.actions.githubusercontent.com
# The UUG.AI release workflow, at a branch/tag ref or a commit.
subjectRegExp: '^https://github\.com/uug-ai/workflows/\.github/workflows/release-create\.yml@(refs/.+|[0-9a-f]{40})$'
additionalExtensions:
githubWorkflowRepository: uug-ai/hub-pipeline-dominantcolors
rekor:
url: https://rekor.sigstore.dev
# Fields of the attestation's predicate. {{`{{ ... }}`}} is Kyverno
# syntax, escaped so Helm leaves it alone.
conditions:
- all:
- key: "{{`{{ result }}`}}"
operator: Equals
value: passed
- key: "{{`{{ repository }}`}}"
operator: Equals
value: uug-ai/hub-pipeline-dominantcolors
{{- end }}
@@ -0,0 +1,69 @@
{{- /*
hub-pipeline-event images must come from a hardened release: they carry the signed
image-hardening attestation (result "passed") that the UUG.AI release workflow
adds after all hardening gates pass, for uug-ai/hub-pipeline-event.
The signature itself is checked by hub-pipeline-event-signed-images.yaml.
A namespaced Policy, so it applies only to the release namespace.
Rendered only when imageHardening.enabled is true and Kyverno is installed.
*/ -}}
{{- if and .Values.imageHardening.enabled (.Capabilities.APIVersions.Has "kyverno.io/v1") }}
apiVersion: kyverno.io/v1
kind: Policy
metadata:
name: hub-pipeline-event-hardened-images
annotations:
policies.kyverno.io/title: hub-pipeline-event images must come from a hardened UUG.AI release
policies.kyverno.io/category: Image hardening
policies.kyverno.io/severity: medium
policies.kyverno.io/subject: Pod
# Kyverno defaults apply: background scans of running pods, attestation required.
# Only settings whose Kyverno default would change behaviour are set below.
spec:
# Not hardened yet: uug-ai/hub-pipeline-event has no hardened release with the
# image-hardening attestation (the image does not meet the hardened contract
# yet). This policy reports that gap and stays in Audit, even when
# imageHardening.validationFailureAction is Enforce. Once its releases are
# hardened, use the same line as hub-api-hardened-images.yaml.
validationFailureAction: Audit
# Kyverno's default (Fail) would stop hub-pipeline-event pods starting while Kyverno is down.
failurePolicy: Ignore
# Verifying against GHCR and Rekor can exceed the 10s default.
webhookTimeoutSeconds: 30
rules:
- name: verify-hub-pipeline-event-hardened
match:
any:
- resources:
kinds:
- Pod
verifyImages:
- imageReferences:
- "ghcr.io/uug-ai/hub-pipeline-event:*"
- "ghcr.io/uug-ai/hub-pipeline-event@*"
# Kyverno's defaults (true) would rewrite pod images to digests and
# report every tag-based image; enable together with Enforce.
mutateDigest: false
verifyDigest: false
attestations:
- type: https://github.com/uug-ai/workflows/attestations/image-hardening/v1
attestors:
- entries:
- keyless:
issuer: https://token.actions.githubusercontent.com
# The UUG.AI release workflow, at a branch/tag ref or a commit.
subjectRegExp: '^https://github\.com/uug-ai/workflows/\.github/workflows/release-create\.yml@(refs/.+|[0-9a-f]{40})$'
additionalExtensions:
githubWorkflowRepository: uug-ai/hub-pipeline-event
rekor:
url: https://rekor.sigstore.dev
# Fields of the attestation's predicate. {{`{{ ... }}`}} is Kyverno
# syntax, escaped so Helm leaves it alone.
conditions:
- all:
- key: "{{`{{ result }}`}}"
operator: Equals
value: passed
- key: "{{`{{ repository }}`}}"
operator: Equals
value: uug-ai/hub-pipeline-event
{{- end }}
@@ -0,0 +1,69 @@
{{- /*
hub-pipeline-export images must come from a hardened release: they carry the signed
image-hardening attestation (result "passed") that the UUG.AI release workflow
adds after all hardening gates pass, for uug-ai/hub-pipeline-export.
The signature itself is checked by hub-pipeline-export-signed-images.yaml.
A namespaced Policy, so it applies only to the release namespace.
Rendered only when imageHardening.enabled is true and Kyverno is installed.
*/ -}}
{{- if and .Values.imageHardening.enabled (.Capabilities.APIVersions.Has "kyverno.io/v1") }}
apiVersion: kyverno.io/v1
kind: Policy
metadata:
name: hub-pipeline-export-hardened-images
annotations:
policies.kyverno.io/title: hub-pipeline-export images must come from a hardened UUG.AI release
policies.kyverno.io/category: Image hardening
policies.kyverno.io/severity: medium
policies.kyverno.io/subject: Pod
# Kyverno defaults apply: background scans of running pods, attestation required.
# Only settings whose Kyverno default would change behaviour are set below.
spec:
# Not hardened yet: uug-ai/hub-pipeline-export has no hardened release with the
# image-hardening attestation (the image does not meet the hardened contract
# yet). This policy reports that gap and stays in Audit, even when
# imageHardening.validationFailureAction is Enforce. Once its releases are
# hardened, use the same line as hub-api-hardened-images.yaml.
validationFailureAction: Audit
# Kyverno's default (Fail) would stop hub-pipeline-export pods starting while Kyverno is down.
failurePolicy: Ignore
# Verifying against GHCR and Rekor can exceed the 10s default.
webhookTimeoutSeconds: 30
rules:
- name: verify-hub-pipeline-export-hardened
match:
any:
- resources:
kinds:
- Pod
verifyImages:
- imageReferences:
- "ghcr.io/uug-ai/hub-pipeline-export:*"
- "ghcr.io/uug-ai/hub-pipeline-export@*"
# Kyverno's defaults (true) would rewrite pod images to digests and
# report every tag-based image; enable together with Enforce.
mutateDigest: false
verifyDigest: false
attestations:
- type: https://github.com/uug-ai/workflows/attestations/image-hardening/v1
attestors:
- entries:
- keyless:
issuer: https://token.actions.githubusercontent.com
# The UUG.AI release workflow, at a branch/tag ref or a commit.
subjectRegExp: '^https://github\.com/uug-ai/workflows/\.github/workflows/release-create\.yml@(refs/.+|[0-9a-f]{40})$'
additionalExtensions:
githubWorkflowRepository: uug-ai/hub-pipeline-export
rekor:
url: https://rekor.sigstore.dev
# Fields of the attestation's predicate. {{`{{ ... }}`}} is Kyverno
# syntax, escaped so Helm leaves it alone.
conditions:
- all:
- key: "{{`{{ result }}`}}"
operator: Equals
value: passed
- key: "{{`{{ repository }}`}}"
operator: Equals
value: uug-ai/hub-pipeline-export
{{- end }}
@@ -0,0 +1,69 @@
{{- /*
hub-pipeline-notification images must come from a hardened release: they carry the signed
image-hardening attestation (result "passed") that the UUG.AI release workflow
adds after all hardening gates pass, for uug-ai/hub-pipeline-notification.
The signature itself is checked by hub-pipeline-notification-signed-images.yaml.
A namespaced Policy, so it applies only to the release namespace.
Rendered only when imageHardening.enabled is true and Kyverno is installed.
*/ -}}
{{- if and .Values.imageHardening.enabled (.Capabilities.APIVersions.Has "kyverno.io/v1") }}
apiVersion: kyverno.io/v1
kind: Policy
metadata:
name: hub-pipeline-notification-hardened-images
annotations:
policies.kyverno.io/title: hub-pipeline-notification images must come from a hardened UUG.AI release
policies.kyverno.io/category: Image hardening
policies.kyverno.io/severity: medium
policies.kyverno.io/subject: Pod
# Kyverno defaults apply: background scans of running pods, attestation required.
# Only settings whose Kyverno default would change behaviour are set below.
spec:
# Not hardened yet: uug-ai/hub-pipeline-notification has no hardened release with the
# image-hardening attestation (the image does not meet the hardened contract
# yet). This policy reports that gap and stays in Audit, even when
# imageHardening.validationFailureAction is Enforce. Once its releases are
# hardened, use the same line as hub-api-hardened-images.yaml.
validationFailureAction: Audit
# Kyverno's default (Fail) would stop hub-pipeline-notification pods starting while Kyverno is down.
failurePolicy: Ignore
# Verifying against GHCR and Rekor can exceed the 10s default.
webhookTimeoutSeconds: 30
rules:
- name: verify-hub-pipeline-notification-hardened
match:
any:
- resources:
kinds:
- Pod
verifyImages:
- imageReferences:
- "ghcr.io/uug-ai/hub-pipeline-notification:*"
- "ghcr.io/uug-ai/hub-pipeline-notification@*"
# Kyverno's defaults (true) would rewrite pod images to digests and
# report every tag-based image; enable together with Enforce.
mutateDigest: false
verifyDigest: false
attestations:
- type: https://github.com/uug-ai/workflows/attestations/image-hardening/v1
attestors:
- entries:
- keyless:
issuer: https://token.actions.githubusercontent.com
# The UUG.AI release workflow, at a branch/tag ref or a commit.
subjectRegExp: '^https://github\.com/uug-ai/workflows/\.github/workflows/release-create\.yml@(refs/.+|[0-9a-f]{40})$'
additionalExtensions:
githubWorkflowRepository: uug-ai/hub-pipeline-notification
rekor:
url: https://rekor.sigstore.dev
# Fields of the attestation's predicate. {{`{{ ... }}`}} is Kyverno
# syntax, escaped so Helm leaves it alone.
conditions:
- all:
- key: "{{`{{ result }}`}}"
operator: Equals
value: passed
- key: "{{`{{ repository }}`}}"
operator: Equals
value: uug-ai/hub-pipeline-notification
{{- end }}
@@ -0,0 +1,69 @@
{{- /*
hub-pipeline-notification-test images must come from a hardened release: they carry the signed
image-hardening attestation (result "passed") that the UUG.AI release workflow
adds after all hardening gates pass, for uug-ai/hub-pipeline-notification-test.
The signature itself is checked by hub-pipeline-notification-test-signed-images.yaml.
A namespaced Policy, so it applies only to the release namespace.
Rendered only when imageHardening.enabled is true and Kyverno is installed.
*/ -}}
{{- if and .Values.imageHardening.enabled (.Capabilities.APIVersions.Has "kyverno.io/v1") }}
apiVersion: kyverno.io/v1
kind: Policy
metadata:
name: hub-pipeline-notification-test-hardened-images
annotations:
policies.kyverno.io/title: hub-pipeline-notification-test images must come from a hardened UUG.AI release
policies.kyverno.io/category: Image hardening
policies.kyverno.io/severity: medium
policies.kyverno.io/subject: Pod
# Kyverno defaults apply: background scans of running pods, attestation required.
# Only settings whose Kyverno default would change behaviour are set below.
spec:
# Not hardened yet: uug-ai/hub-pipeline-notification-test has no hardened release with the
# image-hardening attestation (the image does not meet the hardened contract
# yet). This policy reports that gap and stays in Audit, even when
# imageHardening.validationFailureAction is Enforce. Once its releases are
# hardened, use the same line as hub-api-hardened-images.yaml.
validationFailureAction: Audit
# Kyverno's default (Fail) would stop hub-pipeline-notification-test pods starting while Kyverno is down.
failurePolicy: Ignore
# Verifying against GHCR and Rekor can exceed the 10s default.
webhookTimeoutSeconds: 30
rules:
- name: verify-hub-pipeline-notification-test-hardened
match:
any:
- resources:
kinds:
- Pod
verifyImages:
- imageReferences:
- "ghcr.io/uug-ai/hub-pipeline-notification-test:*"
- "ghcr.io/uug-ai/hub-pipeline-notification-test@*"
# Kyverno's defaults (true) would rewrite pod images to digests and
# report every tag-based image; enable together with Enforce.
mutateDigest: false
verifyDigest: false
attestations:
- type: https://github.com/uug-ai/workflows/attestations/image-hardening/v1
attestors:
- entries:
- keyless:
issuer: https://token.actions.githubusercontent.com
# The UUG.AI release workflow, at a branch/tag ref or a commit.
subjectRegExp: '^https://github\.com/uug-ai/workflows/\.github/workflows/release-create\.yml@(refs/.+|[0-9a-f]{40})$'
additionalExtensions:
githubWorkflowRepository: uug-ai/hub-pipeline-notification-test
rekor:
url: https://rekor.sigstore.dev
# Fields of the attestation's predicate. {{`{{ ... }}`}} is Kyverno
# syntax, escaped so Helm leaves it alone.
conditions:
- all:
- key: "{{`{{ result }}`}}"
operator: Equals
value: passed
- key: "{{`{{ repository }}`}}"
operator: Equals
value: uug-ai/hub-pipeline-notification-test
{{- end }}
@@ -0,0 +1,69 @@
{{- /*
hub-pipeline-sprite images must come from a hardened release: they carry the signed
image-hardening attestation (result "passed") that the UUG.AI release workflow
adds after all hardening gates pass, for uug-ai/hub-pipeline-sprite.
The signature itself is checked by hub-pipeline-sprite-signed-images.yaml.
A namespaced Policy, so it applies only to the release namespace.
Rendered only when imageHardening.enabled is true and Kyverno is installed.
*/ -}}
{{- if and .Values.imageHardening.enabled (.Capabilities.APIVersions.Has "kyverno.io/v1") }}
apiVersion: kyverno.io/v1
kind: Policy
metadata:
name: hub-pipeline-sprite-hardened-images
annotations:
policies.kyverno.io/title: hub-pipeline-sprite images must come from a hardened UUG.AI release
policies.kyverno.io/category: Image hardening
policies.kyverno.io/severity: medium
policies.kyverno.io/subject: Pod
# Kyverno defaults apply: background scans of running pods, attestation required.
# Only settings whose Kyverno default would change behaviour are set below.
spec:
# Not hardened yet: uug-ai/hub-pipeline-sprite has no hardened release with the
# image-hardening attestation (the image does not meet the hardened contract
# yet). This policy reports that gap and stays in Audit, even when
# imageHardening.validationFailureAction is Enforce. Once its releases are
# hardened, use the same line as hub-api-hardened-images.yaml.
validationFailureAction: Audit
# Kyverno's default (Fail) would stop hub-pipeline-sprite pods starting while Kyverno is down.
failurePolicy: Ignore
# Verifying against GHCR and Rekor can exceed the 10s default.
webhookTimeoutSeconds: 30
rules:
- name: verify-hub-pipeline-sprite-hardened
match:
any:
- resources:
kinds:
- Pod
verifyImages:
- imageReferences:
- "ghcr.io/uug-ai/hub-pipeline-sprite:*"
- "ghcr.io/uug-ai/hub-pipeline-sprite@*"
# Kyverno's defaults (true) would rewrite pod images to digests and
# report every tag-based image; enable together with Enforce.
mutateDigest: false
verifyDigest: false
attestations:
- type: https://github.com/uug-ai/workflows/attestations/image-hardening/v1
attestors:
- entries:
- keyless:
issuer: https://token.actions.githubusercontent.com
# The UUG.AI release workflow, at a branch/tag ref or a commit.
subjectRegExp: '^https://github\.com/uug-ai/workflows/\.github/workflows/release-create\.yml@(refs/.+|[0-9a-f]{40})$'
additionalExtensions:
githubWorkflowRepository: uug-ai/hub-pipeline-sprite
rekor:
url: https://rekor.sigstore.dev
# Fields of the attestation's predicate. {{`{{ ... }}`}} is Kyverno
# syntax, escaped so Helm leaves it alone.
conditions:
- all:
- key: "{{`{{ result }}`}}"
operator: Equals
value: passed
- key: "{{`{{ repository }}`}}"
operator: Equals
value: uug-ai/hub-pipeline-sprite
{{- end }}
@@ -0,0 +1,69 @@
{{- /*
hub-pipeline-thumbnail images must come from a hardened release: they carry the signed
image-hardening attestation (result "passed") that the UUG.AI release workflow
adds after all hardening gates pass, for uug-ai/hub-pipeline-thumbnail.
The signature itself is checked by hub-pipeline-thumbnail-signed-images.yaml.
A namespaced Policy, so it applies only to the release namespace.
Rendered only when imageHardening.enabled is true and Kyverno is installed.
*/ -}}
{{- if and .Values.imageHardening.enabled (.Capabilities.APIVersions.Has "kyverno.io/v1") }}
apiVersion: kyverno.io/v1
kind: Policy
metadata:
name: hub-pipeline-thumbnail-hardened-images
annotations:
policies.kyverno.io/title: hub-pipeline-thumbnail images must come from a hardened UUG.AI release
policies.kyverno.io/category: Image hardening
policies.kyverno.io/severity: medium
policies.kyverno.io/subject: Pod
# Kyverno defaults apply: background scans of running pods, attestation required.
# Only settings whose Kyverno default would change behaviour are set below.
spec:
# Not hardened yet: uug-ai/hub-pipeline-thumbnail has no hardened release with the
# image-hardening attestation (the image does not meet the hardened contract
# yet). This policy reports that gap and stays in Audit, even when
# imageHardening.validationFailureAction is Enforce. Once its releases are
# hardened, use the same line as hub-api-hardened-images.yaml.
validationFailureAction: Audit
# Kyverno's default (Fail) would stop hub-pipeline-thumbnail pods starting while Kyverno is down.
failurePolicy: Ignore
# Verifying against GHCR and Rekor can exceed the 10s default.
webhookTimeoutSeconds: 30
rules:
- name: verify-hub-pipeline-thumbnail-hardened
match:
any:
- resources:
kinds:
- Pod
verifyImages:
- imageReferences:
- "ghcr.io/uug-ai/hub-pipeline-thumbnail:*"
- "ghcr.io/uug-ai/hub-pipeline-thumbnail@*"
# Kyverno's defaults (true) would rewrite pod images to digests and
# report every tag-based image; enable together with Enforce.
mutateDigest: false
verifyDigest: false
attestations:
- type: https://github.com/uug-ai/workflows/attestations/image-hardening/v1
attestors:
- entries:
- keyless:
issuer: https://token.actions.githubusercontent.com
# The UUG.AI release workflow, at a branch/tag ref or a commit.
subjectRegExp: '^https://github\.com/uug-ai/workflows/\.github/workflows/release-create\.yml@(refs/.+|[0-9a-f]{40})$'
additionalExtensions:
githubWorkflowRepository: uug-ai/hub-pipeline-thumbnail
rekor:
url: https://rekor.sigstore.dev
# Fields of the attestation's predicate. {{`{{ ... }}`}} is Kyverno
# syntax, escaped so Helm leaves it alone.
conditions:
- all:
- key: "{{`{{ result }}`}}"
operator: Equals
value: passed
- key: "{{`{{ repository }}`}}"
operator: Equals
value: uug-ai/hub-pipeline-thumbnail
{{- end }}
@@ -0,0 +1,68 @@
{{- /*
hub-reactivatesubscriptions images must come from a hardened release: they carry the signed
image-hardening attestation (result "passed") that the UUG.AI release workflow
adds after all hardening gates pass, for uug-ai/hub-reactivatesubscriptions.
The signature itself is checked by hub-reactivatesubscriptions-signed-images.yaml.
A namespaced Policy, so it applies only to the release namespace.
Rendered only when imageHardening.enabled is true and Kyverno is installed.
*/ -}}
{{- if and .Values.imageHardening.enabled (.Capabilities.APIVersions.Has "kyverno.io/v1") }}
apiVersion: kyverno.io/v1
kind: Policy
metadata:
name: hub-reactivatesubscriptions-hardened-images
annotations:
policies.kyverno.io/title: hub-reactivatesubscriptions images must come from a hardened UUG.AI release
policies.kyverno.io/category: Image hardening
policies.kyverno.io/severity: medium
policies.kyverno.io/subject: Pod
# Kyverno defaults apply: background scans of running pods, attestation required.
# Only settings whose Kyverno default would change behaviour are set below.
spec:
# Not hardened yet: uug-ai/hub-reactivatesubscriptions has no hardened release with the
# image-hardening attestation. Only ghcr.io/uug-ai/hub-reactivatesubscriptions is trusted.
# This policy reports that gap and stays in Audit, even when
# imageHardening.validationFailureAction is Enforce.
validationFailureAction: Audit
# Kyverno's default (Fail) would stop hub-reactivatesubscriptions pods starting while Kyverno is down.
failurePolicy: Ignore
# Verifying against GHCR and Rekor can exceed the 10s default.
webhookTimeoutSeconds: 30
rules:
- name: verify-hub-reactivatesubscriptions-hardened
match:
any:
- resources:
kinds:
- Pod
verifyImages:
- imageReferences:
- "ghcr.io/uug-ai/hub-reactivatesubscriptions:*"
- "ghcr.io/uug-ai/hub-reactivatesubscriptions@*"
# Kyverno's defaults (true) would rewrite pod images to digests and
# report every tag-based image; enable together with Enforce.
mutateDigest: false
verifyDigest: false
attestations:
- type: https://github.com/uug-ai/workflows/attestations/image-hardening/v1
attestors:
- entries:
- keyless:
issuer: https://token.actions.githubusercontent.com
# The UUG.AI release workflow, at a branch/tag ref or a commit.
subjectRegExp: '^https://github\.com/uug-ai/workflows/\.github/workflows/release-create\.yml@(refs/.+|[0-9a-f]{40})$'
additionalExtensions:
githubWorkflowRepository: uug-ai/hub-reactivatesubscriptions
rekor:
url: https://rekor.sigstore.dev
# Fields of the attestation's predicate. {{`{{ ... }}`}} is Kyverno
# syntax, escaped so Helm leaves it alone.
conditions:
- all:
- key: "{{`{{ result }}`}}"
operator: Equals
value: passed
- key: "{{`{{ repository }}`}}"
operator: Equals
value: uug-ai/hub-reactivatesubscriptions
{{- end }}
@@ -0,0 +1,57 @@
{{- /*
hub-reactivatesubscriptions images must be signed by UUG.AI: a keyless cosign signature issued by
GitHub Actions, made by the UUG.AI release workflow, for uug-ai/hub-reactivatesubscriptions.
A namespaced Policy, so it applies only to the release namespace.
Rendered only when imageVerification.enabled is true and Kyverno is installed.
*/ -}}
{{- if and .Values.imageVerification.enabled (.Capabilities.APIVersions.Has "kyverno.io/v1") }}
apiVersion: kyverno.io/v1
kind: Policy
metadata:
name: hub-reactivatesubscriptions-signed-images
annotations:
policies.kyverno.io/title: hub-reactivatesubscriptions images must be signed by UUG.AI
policies.kyverno.io/category: Image signing
policies.kyverno.io/severity: high
policies.kyverno.io/subject: Pod
# Kyverno defaults apply: background scans of running pods, signature required.
# Only settings whose Kyverno default would change behaviour are set below.
spec:
# Only ghcr.io/uug-ai/hub-reactivatesubscriptions is trusted. The chart's default image comes from
# Docker Hub (not matched here; reported by trusted-registry.yaml); switch it to
# the signed ghcr.io/uug-ai/hub-reactivatesubscriptions release.
# This policy reports that gap and stays in Audit, even when
# imageVerification.validationFailureAction is Enforce.
validationFailureAction: Audit
# Kyverno's default (Fail) would stop hub-reactivatesubscriptions pods starting while Kyverno is down.
failurePolicy: Ignore
# Verifying against GHCR and Rekor can exceed the 10s default.
webhookTimeoutSeconds: 30
rules:
- name: verify-hub-reactivatesubscriptions
match:
any:
- resources:
kinds:
- Pod
verifyImages:
- imageReferences:
- "ghcr.io/uug-ai/hub-reactivatesubscriptions:*"
- "ghcr.io/uug-ai/hub-reactivatesubscriptions@*"
# Kyverno's defaults (true) would rewrite pod images to digests and
# report every tag-based image; enable together with Enforce.
mutateDigest: false
verifyDigest: false
attestors:
- entries:
- keyless:
issuer: https://token.actions.githubusercontent.com
# The UUG.AI release workflow, at a branch/tag ref or a commit.
subjectRegExp: '^https://github\.com/uug-ai/workflows/\.github/workflows/release-create\.yml@(refs/.+|[0-9a-f]{40})$'
additionalExtensions:
# That workflow signs for every UUG.AI repository; this
# binds the signature to uug-ai/hub-reactivatesubscriptions.
githubWorkflowRepository: uug-ai/hub-reactivatesubscriptions
rekor:
url: https://rekor.sigstore.dev
{{- end }}
@@ -0,0 +1,69 @@
{{- /*
hub-vlm images must come from a hardened release: they carry the signed
image-hardening attestation (result "passed") that the UUG.AI release workflow
adds after all hardening gates pass, for uug-ai/hub-vlm.
The signature itself is checked by hub-vlm-signed-images.yaml.
A namespaced Policy, so it applies only to the release namespace.
Rendered only when imageHardening.enabled is true and Kyverno is installed.
*/ -}}
{{- if and .Values.imageHardening.enabled (.Capabilities.APIVersions.Has "kyverno.io/v1") }}
apiVersion: kyverno.io/v1
kind: Policy
metadata:
name: hub-vlm-hardened-images
annotations:
policies.kyverno.io/title: hub-vlm images must come from a hardened UUG.AI release
policies.kyverno.io/category: Image hardening
policies.kyverno.io/severity: medium
policies.kyverno.io/subject: Pod
# Kyverno defaults apply: background scans of running pods, attestation required.
# Only settings whose Kyverno default would change behaviour are set below.
spec:
# Not hardened yet: uug-ai/hub-vlm has no hardened release with the
# image-hardening attestation (the image does not meet the hardened contract
# yet). This policy reports that gap and stays in Audit, even when
# imageHardening.validationFailureAction is Enforce. Once its releases are
# hardened, use the same line as hub-api-hardened-images.yaml.
validationFailureAction: Audit
# Kyverno's default (Fail) would stop hub-vlm pods starting while Kyverno is down.
failurePolicy: Ignore
# Verifying against GHCR and Rekor can exceed the 10s default.
webhookTimeoutSeconds: 30
rules:
- name: verify-hub-vlm-hardened
match:
any:
- resources:
kinds:
- Pod
verifyImages:
- imageReferences:
- "ghcr.io/uug-ai/hub-vlm:*"
- "ghcr.io/uug-ai/hub-vlm@*"
# Kyverno's defaults (true) would rewrite pod images to digests and
# report every tag-based image; enable together with Enforce.
mutateDigest: false
verifyDigest: false
attestations:
- type: https://github.com/uug-ai/workflows/attestations/image-hardening/v1
attestors:
- entries:
- keyless:
issuer: https://token.actions.githubusercontent.com
# The UUG.AI release workflow, at a branch/tag ref or a commit.
subjectRegExp: '^https://github\.com/uug-ai/workflows/\.github/workflows/release-create\.yml@(refs/.+|[0-9a-f]{40})$'
additionalExtensions:
githubWorkflowRepository: uug-ai/hub-vlm
rekor:
url: https://rekor.sigstore.dev
# Fields of the attestation's predicate. {{`{{ ... }}`}} is Kyverno
# syntax, escaped so Helm leaves it alone.
conditions:
- all:
- key: "{{`{{ result }}`}}"
operator: Equals
value: passed
- key: "{{`{{ repository }}`}}"
operator: Equals
value: uug-ai/hub-vlm
{{- end }}
@@ -0,0 +1,45 @@
{{- /*
Only images from ghcr.io/uug-ai are trusted: report every container, init
container and ephemeral container image from any other registry or
organisation (Docker Hub, quay.io, ...). Signature and hardening are checked per
image by the *-signed-images / *-hardened-images policies, which match
ghcr.io/uug-ai images only.
A namespaced Policy, so it applies only to the release namespace.
Rendered only when imageVerification.enabled is true and Kyverno is installed.
*/ -}}
{{- if and .Values.imageVerification.enabled (.Capabilities.APIVersions.Has "kyverno.io/v1") }}
apiVersion: kyverno.io/v1
kind: Policy
metadata:
name: trusted-registry
annotations:
policies.kyverno.io/title: Images must come from ghcr.io/uug-ai
policies.kyverno.io/category: Image registry
policies.kyverno.io/severity: high
policies.kyverno.io/subject: Pod
spec:
# Reports images from other registries without blocking them, even when
# imageVerification.validationFailureAction is Enforce: some images the chart
# can deploy are not on ghcr.io/uug-ai yet (see README). Switch to the
# configured value once every image is.
validationFailureAction: Audit
# Kyverno's default (Fail) would stop pods starting while Kyverno is down.
failurePolicy: Ignore
rules:
- name: images-from-ghcr-uug-ai
match:
any:
- resources:
kinds:
- Pod
validate:
message: "Every container image must come from the trusted registry ghcr.io/uug-ai/."
foreach:
- list: "request.object.spec.[containers, initContainers, ephemeralContainers][]"
deny:
conditions:
all:
- key: "{{`{{ element.image }}`}}"
operator: NotEquals
value: "ghcr.io/uug-ai/*"
{{- end }}
+58 -72
View File
@@ -286,14 +286,34 @@ kerberosvault:
# For now it's used to create, edit users for Hub.
###########################################################################
admin:
repository: uugai/admin
# Opt in to 8080 and a securityContext only with a compatible hardened image.
containerPort: 80
securityContext: {}
readinessProbe: {}
livenessProbe: {}
# Signed release from the UUG.AI release workflow (only ghcr.io/uug-ai is trusted).
# It runs shell-free as 65532:65532 on 8080 with a read-only root filesystem:
# keep the runtime settings below together with the image (see README).
repository: ghcr.io/uug-ai/admin
containerPort: 8080
securityContext:
runAsNonRoot: true
runAsUser: 65532
runAsGroup: 65532
readOnlyRootFilesystem: true
allowPrivilegeEscalation: false
capabilities:
drop: ["ALL"]
seccompProfile:
type: RuntimeDefault
readinessProbe:
httpGet:
path: /healthz
port: http
periodSeconds: 10
livenessProbe:
httpGet:
path: /healthz
port: http
initialDelaySeconds: 10
periodSeconds: 10
pullPolicy: IfNotPresent
tag: "v1.3.0"
tag: "v1.4.5"
replicas: 2
# Optional pod topology spread constraints for this deployment. Empty by
# default. Example:
@@ -305,13 +325,16 @@ admin:
# matchLabels:
# app: admin
topologySpreadConstraints: []
# Optional extra volumes / volumeMounts for this deployment (empty = none).
#volumes:
# - name: extra
# emptyDir: {}
#volumeMounts:
# - name: extra
# mountPath: /data
# The only writable path: memory-backed /tmp (counts against the pod memory
# limit). Append extra volumes / volumeMounts to these lists.
volumes:
- name: admin-tmp
emptyDir:
medium: Memory
sizeLimit: 16Mi
volumeMounts:
- name: admin-tmp
mountPath: /tmp
logLevel: "info" # possible values: trace, debug, info, warn, error
resources:
requests:
@@ -358,7 +381,7 @@ kerberoshub:
api:
repository: ghcr.io/uug-ai/hub-api
pullPolicy: IfNotPresent
tag: "v1.11.31"
tag: "v1.11.41"
replicas: 2
podSecurityContext:
fsGroup: 65532
@@ -527,7 +550,7 @@ kerberoshub:
frontend:
repository: ghcr.io/uug-ai/hub-frontend
pullPolicy: IfNotPresent
tag: "v1.19.28"
tag: "v1.19.35"
replicas: 2
containerPort: 8080
securityContext:
@@ -839,7 +862,7 @@ kerberoshub:
podSecurityContext: {}
repository: ghcr.io/uug-ai/hub-cleanup
pullPolicy: IfNotPresent
tag: "v1.4.26"
tag: "v1.4.27"
replicas: 1 # Number of pods for the service.
topologySpreadConstraints: [] # Optional pod topology spread constraints (empty = none).
# Optional extra volumes / volumeMounts for this deployment (empty = none).
@@ -893,7 +916,7 @@ kerberoshub:
audit:
repository: ghcr.io/uug-ai/hub-audit
pullPolicy: IfNotPresent
tag: "v1.0.10"
tag: "v1.0.11"
replicas: 1
resources: {}
# resources:
@@ -1092,7 +1115,7 @@ kerberoshub:
securityContext: {}
podSecurityContext: {}
pullPolicy: IfNotPresent
tag: "v1.0.0"
tag: "v1.0.49"
replicas: 1 # Number of pods for the service.
topologySpreadConstraints: [] # Optional pod topology spread constraints (empty = none).
# Optional extra volumes / volumeMounts for this deployment (empty = none).
@@ -1122,7 +1145,7 @@ kerberoshub:
# enabled: true
# repository: ghcr.io/uug-ai/hub-loitering
# pullPolicy: IfNotPresent
# tag: "v1.0.0"
# tag: "v1.0.11"
# replicas: 1 # Number of pods for the worker.
# topologySpreadConstraints: [] # Optional pod topology spread constraints (empty = none).
# #volumes:
@@ -1151,7 +1174,7 @@ kerberoshub:
# enabled: true
# repository: ghcr.io/uug-ai/hub-objecttracking
# pullPolicy: IfNotPresent
# tag: "v1.0.0"
# tag: "v1.0.10"
# replicas: 1 # Number of pods for the worker.
# topologySpreadConstraints: [] # Optional pod topology spread constraints (empty = none).
# logLevel: "info" # possible values: trace, debug, info, warn, error
@@ -1176,7 +1199,7 @@ kerberoshub:
# enabled: true
# repository: ghcr.io/uug-ai/hub-vlm
# pullPolicy: IfNotPresent
# tag: "v1.0.0"
# tag: "v1.0.8"
# replicas: 1 # Number of pods for the worker.
# topologySpreadConstraints: [] # Optional pod topology spread constraints (empty = none).
# logLevel: "info" # possible values: trace, debug, info, warn, error
@@ -1203,7 +1226,7 @@ kerberoshub:
podSecurityContext: {}
repository: ghcr.io/uug-ai/hub-monitor-device
pullPolicy: IfNotPresent
tag: "v1.4.10"
tag: "v1.4.15"
replicas: 1 # Number of pods for the service.
topologySpreadConstraints: [] # Optional pod topology spread constraints (empty = none).
logLevel: "info" # possible values: trace, debug, info, warn, error
@@ -1242,43 +1265,6 @@ kerberoshub:
requests:
memory: 10Mi
cpu: 10m
forwarder:
enabled: false
topologySpreadConstraints: [] # Optional pod topology spread constraints (empty = none).
# Optional extra volumes / volumeMounts for this deployment (empty = none).
#volumes:
# - name: extra
# emptyDir: {}
#volumeMounts:
# - name: extra
# mountPath: /data
#repository: kerberos/vault-forwarder
#pullPolicy: IfNotPresent
#tag: "1.0.2732389692"
#resources:
# requests:
# memory: 10Mi
# cpu: 10m
# This proxy is legacy for the old agent, will be migrated in the new Hub API.
proxy:
enabled: false
repository: uugai/hub-proxy
pullPolicy: IfNotPresent
tag: "v1.0.0"
replicas: 0 # Number of pods for the service when enabled.
topologySpreadConstraints: [] # Optional pod topology spread constraints (empty = none).
# Optional extra volumes / volumeMounts for this deployment (empty = none).
#volumes:
# - name: extra
# emptyDir: {}
#volumeMounts:
# - name: extra
# mountPath: /data
logLevel: "info" # possible values: trace, debug, info, warn, error
resources:
requests:
memory: 10Mi
cpu: 10m
# The Kerberos Hub pipeline is a series of microservices that process the recordings.
# Each microservice is responsible for a specific task, like counting objects, generating thumbnails, etc.
# The pipeline is orchestrated through Kafka topics or RabbitMQ queues.
@@ -1291,7 +1277,7 @@ kerberospipeline:
# argocd.argoproj.io/sync-wave: "10"
repository: ghcr.io/uug-ai/hub-pipeline-event
pullPolicy: IfNotPresent
tag: "v1.3.9"
tag: "v1.3.10"
replicas: 1 # Number of pods for the service.
topologySpreadConstraints: [] # Optional pod topology spread constraints (empty = none).
# Optional extra volumes / volumeMounts for this deployment (empty = none).
@@ -1312,7 +1298,7 @@ kerberospipeline:
# deploymentAnnotations:
# argocd.argoproj.io/sync-wave: "70"
pullPolicy: IfNotPresent
tag: "v1.3.29"
tag: "v1.3.30"
replicas: 1 # Number of pods for the service.
topologySpreadConstraints: [] # Optional pod topology spread constraints (empty = none).
# Optional extra volumes / volumeMounts for this deployment (empty = none).
@@ -1333,7 +1319,7 @@ kerberospipeline:
# deploymentAnnotations:
# argocd.argoproj.io/sync-wave: "60"
pullPolicy: IfNotPresent
tag: "v1.7.14"
tag: "v1.7.15"
replicas: 1 # Number of pods for the service.
topologySpreadConstraints: [] # Optional pod topology spread constraints (empty = none).
# Optional extra volumes / volumeMounts for this deployment (empty = none).
@@ -1356,7 +1342,7 @@ kerberospipeline:
# deploymentAnnotations:
# argocd.argoproj.io/sync-wave: "30"
pullPolicy: IfNotPresent
tag: "v1.2.10"
tag: "v1.2.11"
replicas: 1 # Number of pods for the service.
topologySpreadConstraints: [] # Optional pod topology spread constraints (empty = none).
# Optional extra volumes / volumeMounts for this deployment (empty = none).
@@ -1379,7 +1365,7 @@ kerberospipeline:
# deploymentAnnotations:
# argocd.argoproj.io/sync-wave: "20"
pullPolicy: IfNotPresent
tag: "v1.3.46"
tag: "v1.3.48"
replicas: 1 # Number of pods for the service.
audit:
enabled: true
@@ -1401,7 +1387,7 @@ kerberospipeline:
notifyTest:
repository: ghcr.io/uug-ai/hub-pipeline-notification-test
pullPolicy: IfNotPresent
tag: "v1.2.6"
tag: "v1.2.7"
replicas: 1 # Number of pods for the service.
topologySpreadConstraints: [] # Optional pod topology spread constraints (empty = none).
resources:
@@ -1422,7 +1408,7 @@ kerberospipeline:
# deploymentAnnotations:
# argocd.argoproj.io/sync-wave: "40"
pullPolicy: IfNotPresent
tag: "v1.8.29"
tag: "v1.8.31"
replicas: 1 # Number of pods for the service.
topologySpreadConstraints: [] # Optional pod topology spread constraints (empty = none).
# Optional extra volumes / volumeMounts for this deployment (empty = none).
@@ -1464,7 +1450,7 @@ kerberospipeline:
# deploymentAnnotations:
# argocd.argoproj.io/sync-wave: "50"
pullPolicy: IfNotPresent
tag: "v2.0.9"
tag: "v2.0.10"
replicas: 3 # Number of pods for the service.
topologySpreadConstraints: [] # Optional pod topology spread constraints (empty = none).
# Optional extra volumes / volumeMounts for this deployment (empty = none).
@@ -1490,7 +1476,7 @@ kerberospipeline:
# deploymentAnnotations:
# argocd.argoproj.io/sync-wave: "50"
pullPolicy: IfNotPresent
tag: "v1.3.22"
tag: "v1.3.24"
replicas: 2 # Number of pods for the service.
prefetchCount: 0 # Max unacknowledged RabbitMQ messages per pod; 0 = service default (5).
topologySpreadConstraints: [] # Optional pod topology spread constraints (empty = none).
@@ -1523,7 +1509,7 @@ kerberospipeline:
# deploymentAnnotations:
# argocd.argoproj.io/sync-wave: "50"
pullPolicy: IfNotPresent
tag: "v2.0.6"
tag: "v2.0.7"
replicas: 1 # Number of pods for the service.
topologySpreadConstraints: [] # Optional pod topology spread constraints (empty = none).
# Optional extra volumes / volumeMounts for this deployment (empty = none).
@@ -1545,7 +1531,7 @@ kerberospipeline:
# argocd.argoproj.io/sync-wave: "50"
repository: ghcr.io/uug-ai/hub-pipeline-sprite
pullPolicy: IfNotPresent
tag: "v1.1.27"
tag: "v1.1.28"
replicas: 5 # Number of pods for the service.
prefetchCount: 0 # Max unacknowledged RabbitMQ messages per pod; 0 = service default (5).
topologySpreadConstraints: [] # Optional pod topology spread constraints (empty = none).
@@ -1572,7 +1558,7 @@ kerberospipeline:
export:
repository: ghcr.io/uug-ai/hub-pipeline-export
pullPolicy: IfNotPresent
tag: "v1.2.20"
tag: "v1.2.22"
replicas: 2 # Number of pods for the service.
topologySpreadConstraints: [] # Optional pod topology spread constraints (empty = none).
logLevel: "info" # possible values: trace, debug, info, warn, error
+30 -25
View File
@@ -28,28 +28,26 @@ assert_absent() {
fi
}
HARDENED_FLAGS=(
--set admin.containerPort=8080
--set-json 'admin.securityContext={"runAsNonRoot":true,"runAsUser":65532,"runAsGroup":65532,"readOnlyRootFilesystem":true,"allowPrivilegeEscalation":false,"capabilities":{"drop":["ALL"]},"seccompProfile":{"type":"RuntimeDefault"}}'
--set-json 'admin.volumes=[{"name":"admin-tmp","emptyDir":{"medium":"Memory","sizeLimit":"16Mi"}}]'
--set-json 'admin.volumeMounts=[{"name":"admin-tmp","mountPath":"/tmp"}]'
--set-json 'admin.readinessProbe={"httpGet":{"path":"/healthz","port":"http"},"periodSeconds":10}'
--set-json 'admin.livenessProbe={"httpGet":{"path":"/healthz","port":"http"},"initialDelaySeconds":10,"periodSeconds":10}'
# Since chart 0.184.0 the hardened ghcr.io/uug-ai/admin runtime is the default;
# LEGACY_FLAGS opts back into a legacy image on port 80.
LEGACY_FLAGS=(
--set admin.repository=uugai/admin
--set admin.tag=v1.3.0
--set admin.containerPort=80
--set admin.securityContext=null
--set admin.readinessProbe=null
--set admin.livenessProbe=null
--set admin.volumes=null
--set admin.volumeMounts=null
)
for mode in all ui; do
default_render="$(helm template hub "$CHART_DIR" --set "mode=$mode" --set admin.oauth2Proxy.enabled=true)"
default_deployment="$(resource deployment <<< "$default_render")"
default_service="$(resource service <<< "$default_render")"
default_ingress="$(resource ingress <<< "$default_render")"
default_oauth="$(resource oauth2-proxy <<< "$default_render")"
assert_contains "$default_deployment" 'containerPort: 80$'
assert_absent "$default_deployment" 'securityContext:|readinessProbe:|livenessProbe:'
assert_contains "$default_service" 'port: 80$'
assert_contains "$default_service" 'targetPort: http$'
hardened_render="$(helm template hub "$CHART_DIR" --set "mode=$mode" --set admin.oauth2Proxy.enabled=true "${HARDENED_FLAGS[@]}")"
hardened_render="$(helm template hub "$CHART_DIR" --set "mode=$mode" --set admin.oauth2Proxy.enabled=true)"
hardened_deployment="$(resource deployment <<< "$hardened_render")"
hardened_service="$(resource service <<< "$hardened_render")"
hardened_ingress="$(resource ingress <<< "$hardened_render")"
hardened_oauth="$(resource oauth2-proxy <<< "$hardened_render")"
assert_contains "$hardened_deployment" 'image: "ghcr.io/uug-ai/admin:'
assert_contains "$hardened_deployment" 'containerPort: 8080$'
assert_absent "$hardened_deployment" 'containerPort: 80$'
for setting in 'runAsNonRoot: true' 'runAsUser: 65532' 'runAsGroup: 65532' \
@@ -66,17 +64,24 @@ for mode in all ui; do
assert_contains "$probe_render" 'path: /healthz$'
assert_contains "$probe_render" 'port: http$'
done
assert_contains "$hardened_service" 'port: 80$'
assert_contains "$hardened_service" 'targetPort: http$'
[[ "$(resource service <<< "$hardened_render")" == "$default_service" ]]
[[ "$(resource ingress <<< "$hardened_render")" == "$default_ingress" ]]
[[ "$(resource oauth2-proxy <<< "$hardened_render")" == "$default_oauth" ]]
assert_contains "$default_ingress" 'nginx.ingress.kubernetes.io/auth-url:'
assert_contains "$default_ingress" 'number: 80$'
legacy_render="$(helm template hub "$CHART_DIR" --set "mode=$mode" --set admin.oauth2Proxy.enabled=true "${LEGACY_FLAGS[@]}")"
legacy_deployment="$(resource deployment <<< "$legacy_render")"
assert_contains "$legacy_deployment" 'containerPort: 80$'
assert_absent "$legacy_deployment" 'securityContext:|readinessProbe:|livenessProbe:|admin-tmp'
echo "OK ($mode): legacy defaults; hardened runtime/probes; stable Service, ingress and OAuth2"
[[ "$(resource service <<< "$legacy_render")" == "$hardened_service" ]]
[[ "$(resource ingress <<< "$legacy_render")" == "$hardened_ingress" ]]
[[ "$(resource oauth2-proxy <<< "$legacy_render")" == "$hardened_oauth" ]]
assert_contains "$hardened_ingress" 'nginx.ingress.kubernetes.io/auth-url:'
assert_contains "$hardened_ingress" 'number: 80$'
echo "OK ($mode): hardened ghcr.io defaults; legacy opt-out; stable Service, ingress and OAuth2"
done
pipeline_render="$(helm template hub "$CHART_DIR" --set mode=pipeline "${HARDENED_FLAGS[@]}")"
pipeline_render="$(helm template hub "$CHART_DIR" --set mode=pipeline)"
assert_absent "$pipeline_render" '^# Source: hub/templates/admin/'
echo "All Admin runtime checks passed."
+2 -2
View File
@@ -29,7 +29,7 @@ for mode in all ui; do
--set kerberoshub.frontend.demoEnabled=true)"
for name in hub-frontend hub-frontend-demo; do
deployment="$(resource Deployment "$name" <<< "$rendered")"
assert_contains "$deployment" 'image: "ghcr.io/uug-ai/hub-frontend:v1.19.28"$'
assert_contains "$deployment" 'image: "ghcr.io/uug-ai/hub-frontend:v1.19.35"$'
assert_contains "$deployment" 'containerPort: 8080$'
[[ "$(grep -c 'containerPort:' <<< "$deployment")" == 1 ]]
for setting in 'name: http' 'runAsNonRoot: true' 'runAsUser: 65532' \
@@ -44,7 +44,7 @@ for mode in all ui; do
echo "OK ($mode): $name hardened image, security, scratch and named routing"
done
admin="$(resource Deployment admin <<< "$rendered")"
assert_contains "$admin" 'containerPort: 80$'
assert_contains "$admin" 'containerPort: 8080$'
legacy="$(helm template hub "$CHART_DIR" "${values[@]}" --set "mode=$mode" \
--set kerberoshub.frontend.demoEnabled=true \
+30 -22
View File
@@ -60,6 +60,14 @@ assert_line() {
fi
}
without_admin() {
awk '
/^---$/ { skip=0 }
/^# Source: hub\/templates\/admin\/deployment\.yaml$/ { skip=1 }
!skip { print }
'
}
without_frontends() {
awk '
/^---$/ { skip=0 }
@@ -70,7 +78,8 @@ without_frontends() {
for mode in all pipeline ui; do
defaults="$(helm template hub "$CHART_DIR" --set "mode=$mode")"
worker_defaults="$(without_frontends <<< "$defaults")"
# Frontends, hub-api and Admin (since 0.184.0) are hardened by default.
worker_defaults="$(without_frontends <<< "$defaults" | without_admin)"
if grep -q 'securityContext:' <<< "$worker_defaults"; then
echo "Default $mode mode unexpectedly enables worker security settings" >&2
exit 1
@@ -120,8 +129,8 @@ for mode in all pipeline ui; do
fi
done
expected="${#names[@]}"
[[ "$(without_frontends <<< "$hardened" | grep -c 'runAsUser: 65532')" == "$expected" ]]
[[ "$(without_frontends <<< "$hardened" | grep -c 'fsGroup: 65532')" == "$expected" ]]
[[ "$(without_frontends <<< "$hardened" | without_admin | grep -c 'runAsUser: 65532')" == "$expected" ]]
[[ "$(without_frontends <<< "$hardened" | without_admin | grep -c 'fsGroup: 65532')" == "$expected" ]]
# Image selection, Services, env and TLS mounts must not change.
for pattern in '^[ ]+image:' '^[ ]+(port|targetPort|containerPort):' 'mongodb-tls'; do
@@ -137,26 +146,23 @@ isolated="$(helm template hub "$CHART_DIR" --set mode=pipeline \
assert_line "$(resource Deployment pipe-counting <<< "$isolated")" '^[ ]+runAsUser: 65532$'
echo "All hardened worker checks passed."
admin_flags=(
--set admin.containerPort=8080
--set admin.securityContext.runAsNonRoot=true
--set admin.securityContext.runAsUser=65532
--set admin.securityContext.runAsGroup=65532
--set admin.securityContext.readOnlyRootFilesystem=true
--set admin.securityContext.allowPrivilegeEscalation=false
--set admin.securityContext.capabilities.drop[0]=ALL
--set admin.securityContext.seccompProfile.type=RuntimeDefault
--set admin.volumes[0].name=admin-tmp
--set admin.volumes[0].emptyDir.medium=Memory
--set admin.volumes[0].emptyDir.sizeLimit=16Mi
--set admin.volumeMounts[0].name=admin-tmp
--set admin.volumeMounts[0].mountPath=/tmp
# Since chart 0.184.0 the hardened Admin runtime is the default; these flags
# opt back into a legacy image on port 80.
legacy_admin_flags=(
--set admin.repository=uugai/admin
--set admin.tag=v1.3.0
--set admin.containerPort=80
--set admin.securityContext=null
--set admin.readinessProbe=null
--set admin.livenessProbe=null
--set admin.volumes=null
--set admin.volumeMounts=null
--set admin.oauth2Proxy.enabled=true
)
for mode in all ui pipeline; do
legacy="$(helm template hub "$CHART_DIR" --set "mode=$mode" --set admin.oauth2Proxy.enabled=true)"
configured="$(helm template hub "$CHART_DIR" --set "mode=$mode" "${admin_flags[@]}")"
helm lint "$CHART_DIR" --quiet --set "mode=$mode" "${admin_flags[@]}"
legacy="$(helm template hub "$CHART_DIR" --set "mode=$mode" "${legacy_admin_flags[@]}")"
configured="$(helm template hub "$CHART_DIR" --set "mode=$mode" --set admin.oauth2Proxy.enabled=true)"
helm lint "$CHART_DIR" --quiet --set "mode=$mode" "${legacy_admin_flags[@]}"
if [[ "$mode" == pipeline ]]; then
[[ -z "$(resource Deployment admin <<< "$configured")" ]]
[[ -z "$(resource Service admin-svc <<< "$configured")" ]]
@@ -186,9 +192,11 @@ for mode in all ui pipeline; do
[[ "$(resource Ingress admin-ingress <<< "$legacy")" == "$(resource Ingress admin-ingress <<< "$configured")" ]]
[[ "$(resource Deployment oauth2-proxy-admin <<< "$legacy")" == "$(resource Deployment oauth2-proxy-admin <<< "$configured")" ]]
[[ "$(resource Service oauth2-proxy-admin <<< "$legacy")" == "$(resource Service oauth2-proxy-admin <<< "$configured")" ]]
[[ "$(grep 'image:' <<< "$legacy")" == "$(grep 'image:' <<< "$configured")" ]]
[[ "$(without_admin <<< "$legacy" | grep 'image:')" == "$(without_admin <<< "$configured" | grep 'image:')" ]]
assert_line "$old" 'image: "uugai/admin:v1.3.0"$'
assert_line "$block" 'image: "ghcr.io/uug-ai/admin:v1.4.5"$'
# No other workload inherits Admin's container port or security settings.
[[ "$(without_frontends <<< "$configured" | grep -c 'runAsUser: 65532')" == 1 ]]
echo "OK ($mode): Admin opt-in port/security/tmpfs; legacy image, Service port, ingress and OAuth2-proxy preserved"
echo "OK ($mode): Admin hardened defaults; legacy opt-out; Service port, ingress and OAuth2-proxy preserved"
done
echo "All hardened Admin checks passed."