diff --git a/.claude/skills/educates-release-notes/SKILL.md b/.claude/skills/educates-release-notes/SKILL.md new file mode 100644 index 000000000..d314cde55 --- /dev/null +++ b/.claude/skills/educates-release-notes/SKILL.md @@ -0,0 +1,151 @@ +--- +name: educates-release-notes +description: Create release notes for an Educates version. Invoke when asked to "create release notes", "prepare for a release", "generate release notes", or "document changes for version X.Y.Z". Creates a versioned markdown file in project-docs/release-notes/ and updates project-docs/index.rst. +argument-hint: " (e.g. 4.1.0)" +allowed-tools: "Read, Glob, Bash" +--- + +# Educates Release Notes Creation + +Create release notes for version `$ARGUMENTS` of the educates-training-platform. + +If no version is specified in `$ARGUMENTS`, check `project-docs/release-notes/` for the latest `version-*.md` file and increment the patch version. + +## Step 1: Determine the Version + +Use the version from `$ARGUMENTS` (e.g. `4.1.0`). If not provided: + +```bash +ls project-docs/release-notes/version-*.md | sort -V | tail -1 +``` + +Increment the patch version (or minor/major as appropriate). + +## Step 2: Find the Previous Release + +```bash +ls project-docs/release-notes/version-*.md | sort -V +``` + +Identify the version immediately before the target version. Then find its git tag or the commit where it was merged. Educates release tags are plain `X.Y.Z` (and `X.Y.Z-alpha.N`/`-beta.N`/`-rc.N` pre-releases) with **no `v` prefix**: + +```bash +git tag --sort=-version:refname | grep -E '^[0-9]' | head +git log --oneline --grep="version-" -- project-docs/release-notes/ +``` + +## Step 3: Analyze Git Changes + +Get all commits since the previous release: + +```bash +git log --oneline ..HEAD +``` + +Get changed files: + +```bash +git diff --name-only ..HEAD +git diff --stat ..HEAD +``` + +Get commit messages formatted for analysis: + +```bash +git log --pretty=format:"%s" ..HEAD +``` + +Check for merge commits (feature branches): + +```bash +git log --merges ..HEAD +``` + +## Step 4: Categorize Changes + +Map changes to sections by scanning commits and file diffs: + +| Category | What to look for | +|---|---| +| **New Features** | New files, new commands, new config options; commit keywords: "add", "new", "feature", "support for" | +| **Features Changed** | Modified existing files, version bumps, config changes; keywords: "update", "change", "modify", "improve", "refactor" | +| **Bugs Fixed** | Error handling, corrections; keywords: "fix", "bug", "error", "issue", "correct" | +| **Deprecations** | Things still supported but on the way out; keywords: "deprecate", "deprecated". Note the removal timeline (and any upstream timeline it tracks). | +| **Known Issues** | Manual entry — from issue tracker or known limitations | + +A user-facing change is only "done" when it has a release-notes entry — this is a +project norm (see `CLAUDE.md`), so the running `version-*.md` may already carry +many entries. Treat your job as filling gaps and tidying, not writing from scratch. + +Common patterns: +- `go.mod`/`go.sum` changes → dependency updates (Features Changed) +- `Dockerfile` changes → base image or tool version updates (Features Changed) +- New files in `project-docs/` → documentation (New Features or Features Changed) +- kubectl version blocks in `workshop-images/base-environment/Dockerfile` → Kubernetes version support change + +## Step 5: Create the Release Notes File + +Create `project-docs/release-notes/version-{x.y.z}.md` using this exact format: + +```markdown +Version {x.y.z} +============= + +New Features +------------ + +* Description of new feature. + +Features Changed +---------------- + +* Description of changed feature. + +Bugs Fixed +---------- + +* Description of bug fix. + +Deprecations +------------ + +* Description of a feature that still works but is slated for removal, with the + removal timeline (if any). + +Known Issues +------------ + +* Description of known issue (if any). +``` + +Formatting rules: +- Main heading uses `=` underline (same length as the heading text) +- Section headings use `-` underline +- Bullet points use `*` +- Omit sections that have no entries +- Write in third person, concise, specific +- Include version numbers for dependency updates +- Clearly flag breaking changes + +## Step 6: Update `project-docs/index.rst` + +Read `project-docs/index.rst` and find the `Release Notes:` toctree section (around line 80–82). Add the new entry at the **top** of the list (newest first): + +```rst +.. toctree:: + :maxdepth: 2 + :caption: Release Notes: + + release-notes/version-{x.y.z} + release-notes/version-{previous} + ... +``` + +Maintain 2-space indentation and keep entries sorted newest first. + +## Step 7: Review + +- Verify version number is correct and consistent in filename and heading +- Confirm all major changes from git log are covered +- Check formatting matches existing release notes files (read one for comparison) +- Verify the `index.rst` entry was added correctly and the file renders as valid RST diff --git a/.claude/skills/educates-upgrade-cluster-services/SKILL.md b/.claude/skills/educates-upgrade-cluster-services/SKILL.md new file mode 100644 index 000000000..8c978ec69 --- /dev/null +++ b/.claude/skills/educates-upgrade-cluster-services/SKILL.md @@ -0,0 +1,211 @@ +--- +name: educates-upgrade-cluster-services +description: Upgrade a vendored upstream cluster-service Helm chart the Educates operator installs for EducatesClusterConfig — cert-manager, Contour, Kyverno, or external-dns. Invoke when asked to "upgrade cert-manager / contour / kyverno / external-dns", "bump a vendored cluster-service chart", or "update the operator's bundled charts". +argument-hint: "[cert-manager|contour|kyverno|external-dns] (omit to check all four)" +allowed-tools: "Read, Edit, Bash, WebFetch, Glob" +--- + +# Educates Cluster-Service Chart Upgrade Protocol + +The operator installs four upstream cluster services for `EducatesClusterConfig` +(Managed mode) from Helm chart tarballs vendored at +`installer/operator/vendored-charts/`: **cert-manager**, **Contour**, +**Kyverno**, **external-dns**. The bytes are checked into the repo and embedded +into the operator binary via `//go:embed`. This skill bumps one (or checks all) +to a new upstream version. + +`installer/operator/vendored-charts/README.md` is the canonical reference for +this workflow — keep it and this skill in agreement. + +If `$ARGUMENTS` names a service, upgrade only that one. With no argument, check +all four for newer upstream versions and report before changing anything. + +> The same directory also holds the in-repo runtime subcharts (secrets-manager, +> lookup-service, session-manager, node-ca-injector, remote-access). Those are +> **not** in scope here — they are repackaged from source via +> `make package-local-charts`, not downloaded. + +## Where each piece of version state lives + +A version is pinned in **four** places that must stay in lockstep (a +consistency test enforces it — see Verification): + +1. `installer/operator/Makefile` → `VENDORED_CHARTS` list: `name=version=url`. +2. `installer/operator/vendored-charts/SHA256SUMS`: ` -.tgz`. +3. `installer/operator/vendored-charts/embed.go`: the `//go:embed -.tgz` + directive, the `ChartVersion` constant, and (Contour / external-dns / + Kyverno) the `AppVersion` constant. cert-manager has a single + `CertManagerVersion` (its chart version equals its appVersion). +4. The tarball file itself on disk. + +## Upstream sources and version semantics + +| Service | Upstream releases | Chart URL pattern | App version | +|---|---|---|---| +| cert-manager | `https://github.com/cert-manager/cert-manager/releases` | `https://charts.jetstack.io/charts/cert-manager-v.tgz` | == chart version (`v`) | +| contour | `https://github.com/projectcontour/helm-charts/releases` | `https://github.com/projectcontour/helm-charts/releases/download/contour-/contour-.tgz` | Contour binary version (e.g. `1.33.5`) | +| external-dns | `https://github.com/kubernetes-sigs/external-dns/releases` | `https://github.com/kubernetes-sigs/external-dns/releases/download/external-dns-helm-chart-/external-dns-.tgz` | external-dns binary version | +| kyverno | `https://github.com/kyverno/kyverno/releases` | `https://kyverno.github.io/kyverno/kyverno-.tgz` | Kyverno binary version (e.g. `v1.18.1`) | + +Use WebFetch on the releases page to find the latest stable chart version (not a +pre-release). The chart version and the bundled app version differ for Contour, +external-dns, and Kyverno — read the new app version from the tarball's +`Chart.yaml` (`appVersion:`) after downloading. + +**Kyverno is the awkward one: its chart version and binary version are on +different numbering tracks and live in different places.** The +`github.com/kyverno/kyverno/releases` page lists the **binary** version +(`appVersion`, e.g. `v1.18.1`); the **chart** version (`` in the URL above, +e.g. `3.8.1`) only exists in the Helm repo's `index.yaml`. They are *not* +aligned and you cannot derive one from the other by inspection — you must resolve +the chart version that ships a given Kyverno binary from the repo index: + +```bash +# What chart version ships Kyverno binary v1.18.1? (stable, non-rc rows only) +curl -sSfL https://kyverno.github.io/kyverno/index.yaml \ + | yq -r '.entries.kyverno[] + | select(.appVersion | test("rc")|not) + | .version + " => " + .appVersion' \ + | grep ' v1.18.1$' # → 3.8.1 => v1.18.1 +``` + +To browse the newest stable charts and the binary each one bundles (the first +row is the latest stable chart), drop the `grep`: + +```bash +curl -sSfL https://kyverno.github.io/kyverno/index.yaml \ + | yq -r '.entries.kyverno[] + | select(.appVersion | test("rc")|not) + | .version + " => " + .appVersion' \ + | head +``` + +Equivalently with the Helm CLI (`helm repo add kyverno +https://kyverno.github.io/kyverno/ && helm repo update kyverno && helm search +repo kyverno/kyverno --versions`), whose `CHART VERSION` / `APP VERSION` columns +are the same two fields. Either way, that chart version is what goes in +`` for the download URL, the Makefile, `SHA256SUMS`, and the `embed.go` +filename + `KyvernoChartVersion`; the matching `appVersion` is +`KyvernoAppVersion` (still confirm it from the downloaded tarball's `Chart.yaml` +per step 5). + +Current versions: read them from the Makefile `VENDORED_CHARTS` line and the +`embed.go` constants. + +## Update process (per chart) + +Worked example: contour `0.6.0` → ``. Other charts are identical except +cert-manager has no separate `AppVersion` constant. + +1. **Compute the new tarball's SHA256** from the upstream URL (the "I am + deliberately trusting these bytes" step — `make vendor-charts` refuses to + download anything whose hash isn't already recorded): + ```bash + curl -sSfL "https://github.com/projectcontour/helm-charts/releases/download/contour-/contour-.tgz" | shasum -a 256 + ``` + +2. **`installer/operator/Makefile`** — update the chart's `VENDORED_CHARTS` + entry (version and URL). + +3. **`SHA256SUMS`** — replace the chart's line with the new filename + hash. + +4. **`make -C installer/operator vendor-charts`** — downloads, verifies against + SHA256SUMS, and writes the new tarball into place. Then `git rm` the old + tarball (nothing prunes it automatically). + +5. **`embed.go`** — update the `//go:embed` filename, the `ChartVersion` + constant, and the `AppVersion` constant. Read the new appVersion from the + tarball: + ```bash + tar -xzOf installer/operator/vendored-charts/contour-.tgz contour/Chart.yaml | grep -E '^(version|appVersion):' + ``` + +6. **Re-verify reconciler assumptions** (the load-bearing step — see next + section). The per-service reconciler gates readiness on specific workload + names / webhook behaviour verified against a chart version. + +7. **`installer/operator/vendored-charts/README.md`** — update the "Current + contents" version table. + +8. **Kyverno only — also re-vendor the bundled policies.** See "Kyverno + special case" below. + +## Re-verify reconciler assumptions + +Each cluster service has a reconciler in `installer/operator/internal/controller/config/` +that gates readiness on workload names and, sometimes, CRD/webhook behaviour. +A chart bump can rename a Deployment, change a values key, or move a CRD API +version and silently break the gate. Render the new chart and confirm: + +```bash +# extract + template the new chart with the operator's values shape +helm template [--set ...] | grep -E 'kind: (Deployment|DaemonSet)' -A2 +``` + +| Service | Reconciler | What it asserts (verify still true) | +|---|---|---| +| cert-manager | `certmanager.go` | `cert-manager`, `cert-manager-cainjector`, `cert-manager-webhook` Deployments ready; `cert-manager.io` API discovery responds; CRDs present (deferred watch) | +| contour | `contour.go` | `contour-contour` Deployment + `contour-envoy` DaemonSet (names from the chart fullname helper); no admission webhook; `envoy.useHostPort` / `envoy.service.type` values still honoured | +| external-dns | `externaldns.go` | the external-dns Deployment is ready; provider value keys (Route53 / CloudDNS) unchanged | +| kyverno | `kyverno.go` | the four controller Deployments (`kyverno-{admission,background,cleanup,reports}-controller`) ready; `validatingpolicies.policies.kyverno.io` CRD still installed; RBAC role names unchanged | + +If a name or values key changed, update the reconciler constant and its +"verified against " comment in the same change. + +## Kyverno special case + +Bumping the Kyverno **chart** usually means bumping the Kyverno **binary** +(`KyvernoAppVersion`), and the bundled Kyverno security policies are pinned to a +matching `kyverno/policies` release branch. When `KyvernoAppVersion` changes +(e.g. `v1.18.x` → `v1.19.x`): + +1. Re-vendor the policies from the matching `release-1.NN` branch — follow + `installer/charts/educates-training-platform/charts/session-manager/files/kyverno-policies/README.md`. +2. Repackage the session-manager subchart so the operator ships the refreshed + policies: + ```bash + make -C installer/operator package-local-charts + ``` + (then restore any subchart tarball that only changed by gzip timestamp). +3. Re-check that `kyverno.go`'s RBAC / CRD assumptions and the session-manager + `validatingpolicies` ClusterRole still match the new Kyverno. + +## Verification + +```bash +make -C installer/operator verify-vendored-charts # SHA256 of every on-disk tarball +make -C installer/operator test # runs the consistency + load tests +``` + +`make test` includes: +- `TestVendoredCharts_DirectoryConsistent` — ties the Makefile `VENDORED_CHARTS` + list, `SHA256SUMS`, `embed.go` constants, and the on-disk tarballs together; a + half-finished bump (or a leftover old tarball) fails here. +- `Test_Embedded` — asserts each embedded chart's name/version/appVersion + match the `embed.go` constants. + +The operator image `//go:embed`s these tarballs, so to test on a cluster rebuild +the operator (`make image-operator`) and redeploy. For a real upgrade, also +deploy `EducatesClusterConfig` in Managed mode and confirm the service reaches +Ready and its reconciler condition flips (`CertificatesReady`, `IngressReady`, +`DNSReady`, `PolicyEnforcementReady`). + +## Notes + +- Never edit a vendored tarball or unpack-and-repack it — ship the upstream + chart unmodified. Configuration is applied through the operator's Helm values + (the per-service `renderValues` in the reconcilers), not by patching + the bytes. +- Major-version bumps: read the upstream chart's changelog for renamed values, + workload names, or CRD API-version moves, and flag breaking changes. + +## Post-upgrade checklist + +- [ ] `VENDORED_CHARTS` (Makefile), `SHA256SUMS`, and `embed.go` all updated to the new version +- [ ] New tarball downloaded via `make vendor-charts` (hash-verified); old tarball `git rm`'d +- [ ] `embed.go` `AppVersion` read from the new tarball's `Chart.yaml` +- [ ] Reconciler workload-name / values / CRD assumptions re-verified; constants + comments updated if changed +- [ ] Kyverno: bundled policies re-vendored + session-manager subchart repackaged (if appVersion changed) +- [ ] README "Current contents" table updated +- [ ] `make verify-vendored-charts` and `make test` pass +- [ ] Major-version bumps: changelog reviewed for breaking changes and flagged diff --git a/.claude/skills/educates-upgrade-go/SKILL.md b/.claude/skills/educates-upgrade-go/SKILL.md new file mode 100644 index 000000000..27fc3498e --- /dev/null +++ b/.claude/skills/educates-upgrade-go/SKILL.md @@ -0,0 +1,137 @@ +--- +name: educates-upgrade-go +description: Upgrade the Go version across the entire educates-training-platform project. Invoke when asked to "upgrade go version", "bump golang", "update go", or "use go 1.xx". Updates go.work, all go.mod files, all Dockerfiles, and CI/CD workflow files. +argument-hint: " (e.g. 1.24)" +allowed-tools: "Read, Edit, Glob, Bash" +--- + +# Educates Go Version Upgrade Protocol + +Upgrade the Go version to `$ARGUMENTS` (e.g. `1.24`) across all files in the project. + +## Step 1: Find the Current Version + +Check the current Go version before making changes: + +```bash +grep -rn "^go 1\." go.work client-programs/go.mod installer/operator/go.mod node-ca-injector/go.mod assets-server/go.mod +``` + +## Step 2: Update All Files + +You must update **all** of the following. Do not skip any. + +### Go Module Files + +- **`go.work`** — update the `go 1.xx` directive. The workspace covers + `client-programs/`, `installer/operator/`, and `node-ca-injector/`. +- **`client-programs/go.mod`** — update the `go 1.xx` line +- **`installer/operator/go.mod`** — update the `go 1.xx` line (the kubebuilder operator) +- **`node-ca-injector/go.mod`** — update the `go 1.xx` line +- **`assets-server/go.mod`** — update the `go 1.xx` line (Docker-only module, not in `go.work`) + +Discover every module so none is missed (the platform modules are at the +repo root; ignore any `go.mod` under `workshop-samples/`, which is sample +workshop content with its own lifecycle): + +```bash +git ls-files 'go.mod' '*/go.mod' | grep -v '^workshop-samples/' +``` + +Note: `tunnel-manager` is a Python (uv) component and has no `go.mod`. + +### Dockerfiles + +Use the plain `golang:1.xx` image tag — do not switch to Alpine, Buster, Trixie, +or other derivative tags. Only the `golang:1.xx` version changes — **do not add +or remove the `--platform=$BUILDPLATFORM` prefix** as part of a version bump. + +- **`client-programs/Dockerfile`** — `FROM --platform=$BUILDPLATFORM golang:1.xx AS builder` +- **`installer/operator/Dockerfile`** — `FROM --platform=$BUILDPLATFORM golang:1.xx AS builder` +- **`node-ca-injector/Dockerfile`** — `FROM --platform=$BUILDPLATFORM golang:1.xx AS builder` +- **`assets-server/Dockerfile`** — `FROM --platform=$BUILDPLATFORM golang:1.xx AS builder` +- **`workshop-images/base-environment/Dockerfile`** — `FROM --platform=$BUILDPLATFORM golang:1.xx as builder-image` + +Search for any other Dockerfile referencing golang: + +```bash +grep -rn "FROM .*golang:" --include="Dockerfile*" . +``` + +#### About `--platform=$BUILDPLATFORM` + +It is not a standalone flag — it is correct **only** as a three-part +cross-compile set in the same stage: + +1. `FROM --platform=$BUILDPLATFORM golang:1.xx AS builder` (builder runs on the + build host, not emulated), +2. `ARG TARGETOS` / `ARG TARGETARCH`, +3. `... GOOS=${TARGETOS} GOARCH=${TARGETARCH} go build ...` (cross-compile to the + target). + +With all three, a multiarch build cross-compiles natively instead of running the +Go toolchain under QEMU for each non-native arch — much faster. **Adding the +prefix to a stage that builds with a plain `go build` (no `GOOS`/`GOARCH`) +produces a wrong-architecture binary** — so the prefix and the `GOOS/GOARCH` +build must always go together. + +All five Go Dockerfiles above currently cross-compile and carry the prefix. If +you ever add a new Go build stage, give it the full three-part set (or no +`--platform` at all) — never the prefix alone. + +### CI/CD Workflows + +The Go workflows (`.github/workflows/*.yaml` — note the extension) pin the +toolchain with `actions/setup-go` using `go-version-file:` pointing at a module's +`go.mod` (e.g. `client-programs-ci.yaml` → `client-programs/go.mod`, +`installer-operator-ci.yaml` → `installer/operator/go.mod`). Because the version +is read from `go.mod`, bumping the `go.mod` files above is normally enough — no +hardcoded version to edit. + +Still confirm there's no stray hardcoded version left behind: + +```bash +grep -rnE "go-version:|golang:1\." .github/workflows/ +``` + +If any `go-version: '1.xx'` literal exists, update it (or, preferably, convert it +to `go-version-file:`). + +## Step 3: Verify + +Run in order, fix any failures before proceeding: + +1. Sync dependencies in every module (run `go mod tidy` in each): + +```bash +for m in client-programs installer/operator node-ca-injector assets-server; do + (cd "$m" && go mod tidy) +done +``` + +2. Build the CLI and the operator: + +```bash +make build-cli # CLI (build-client-programs is an alias) +make -C installer/operator build # operator manager binary +``` + +3. Run tests (the operator's envtest is the most likely to surface a + toolchain issue): + +```bash +cd client-programs && go test ./... +make -C installer/operator test +``` + +## Step 4: Post-Verification Checklist + +- [ ] `go.work` updated +- [ ] All four platform `go.mod` files updated (`client-programs`, `installer/operator`, `node-ca-injector`, `assets-server`) +- [ ] All five Dockerfiles with `FROM ...golang:` updated, `--platform=$BUILDPLATFORM` prefix preserved where present +- [ ] CI: no stray hardcoded `go-version:`/`golang:1.` literal left (versions come from `go-version-file: /go.mod`) +- [ ] `go mod tidy` ran cleanly in all modules +- [ ] CLI builds (`make build-cli`) and operator builds + tests (`make -C installer/operator build test`) +- [ ] No remaining references to the old Go version (`grep -rn "golang:1\." --include="Dockerfile*" .`) + +If `go mod tidy` changes `go.sum`, commit that change but confirm with the user first. diff --git a/.claude/skills/educates-upgrade-theme-libraries/SKILL.md b/.claude/skills/educates-upgrade-theme-libraries/SKILL.md new file mode 100644 index 000000000..2668659c7 --- /dev/null +++ b/.claude/skills/educates-upgrade-theme-libraries/SKILL.md @@ -0,0 +1,203 @@ +--- +name: educates-upgrade-theme-libraries +description: Upgrade the vendored third-party frontend libraries bundled into the Educates workshop dashboard theme (Bootstrap, Font Awesome, jQuery, Underscore.js, JSONForm, js-yaml). Invoke when asked to "update theme libraries", "upgrade bootstrap/font-awesome/jquery/underscore/jsonform/js-yaml", "bump the dashboard frontend libraries", or "refresh the vendored web assets". +argument-hint: "[] (omit to check/update all six)" +allowed-tools: "Read, Bash, WebFetch, Glob, Edit" +--- + +# Educates Workshop Theme Libraries Upgrade Protocol + +Refresh the third-party browser libraries vendored into the workshop dashboard +theme. These assets are **committed directly into the repository** and have no +build-time fetcher — this skill is how they are updated: it re-downloads a +library from its upstream source and writes the files back into the tree. + +If `$ARGUMENTS` names a specific library (e.g. `bootstrap`, `jquery`), update +only that one. With no argument, check all six for newer upstream versions and +report what's available before changing anything. + +## Canonical location + +All libraries live under one directory (the `educates` dashboard theme's static +assets): + +``` +workshop-images/base-environment/opt/eduk8s/etc/themes/educates/static/static/libraries/ +``` + +Call this `$LIB` below. The target filenames are **version-agnostic** (no +version in the path), so an upgrade overwrites the existing files in place — no +renaming or `git rm` of old files is needed (except Font Awesome / Bootstrap if +upstream ever changes which files ship). + +## Libraries, sources, and target files + +Two shapes: **zip subset** (download a release zip, extract a few files, +stripping the zip's top-level folder) and **single file** (download one JS file +directly). Versions shown are the current committed ones — confirm against the +tree before bumping (see "Finding current versions"). + +| Library | Shape | Upstream source (version in URL) | Files written under `$LIB` | +|---|---|---|---| +| `bootstrap` | zip subset | `https://github.com/twbs/bootstrap/releases/download/v/bootstrap--dist.zip` | `bootstrap/css/bootstrap.min.css`, `bootstrap/js/bootstrap.bundle.min.js` | +| `font-awesome` | zip subset | `https://github.com/FortAwesome/Font-Awesome/releases/download//fontawesome-free--web.zip` | `font-awesome/css/all.min.css` + `font-awesome/webfonts/{fa-brands-400,fa-regular-400,fa-solid-900,fa-v4compatibility}.{woff2,ttf}` (8 webfonts) | +| `jquery` | single file | `https://cdn.jsdelivr.net/npm/jquery@/dist/jquery.min.js` | `jquery/jquery.min.js` | +| `underscore` | single file | `https://cdn.jsdelivr.net/npm/underscore@/underscore-umd-min.js` | `underscore/underscore-umd-min.js` | +| `jsonform` | single file | `https://cdn.jsdelivr.net/npm/jsonform@/lib/jsonform.min.js` | `jsonform/jsonform.min.js` | +| `js-yaml` | single file | `https://cdn.jsdelivr.net/npm/js-yaml@/dist/js-yaml.min.js` | `js-yaml/js-yaml.min.js` | + +For the two zip-subset libraries, only the files listed above are kept; the +rest of the release archive is discarded. + +## Keep aligned with the renderer and gateway apps + +These same libraries are also npm dependencies of the two bundled apps in the +base environment — `workshop-images/base-environment/opt/renderer` and +`.../opt/gateway` — which compile them into their own JavaScript via esbuild. +The vendored theme copy and the npm-bundled copy must stay on the **same +version**, or the dashboard's static assets drift from what the apps ship. + +Whenever you change a vendored library version here, update the matching npm +dependency in each app's `package.json` that declares it, and vice versa: + +| Theme library | npm package | `renderer/package.json` | `gateway/package.json` | +|---|---|---|---| +| `bootstrap` | `bootstrap` | yes | yes | +| `font-awesome` | `@fortawesome/fontawesome-free` | yes | yes | +| `jquery` | `jquery` | yes | yes | +| `js-yaml` | `js-yaml` | yes | yes | +| `underscore` | `underscore` | yes | — | +| `jsonform` | `jsonform` | yes | — | + +The `package.json` versions are caret ranges (e.g. `"bootstrap": "^5.3.2"`). +Set the range to the version you vendored (`^`), then refresh the lockfile +and rebuild so the bundle matches: + +```bash +cd workshop-images/base-environment/opt/ # renderer and/or gateway +npm install # updates package-lock.json to the new version +``` + +The app bundle is produced by `scripts/compile.sh` (`tsc` + `esbuild`); it runs +during the base-environment image build, so a `make image-base-environment` (or +running `compile.sh` in the app dir) is what proves the new version compiles and +bundles cleanly. + +## Finding current versions + +The committed minified files carry a version banner in their first line(s): + +```bash +LIB=workshop-images/base-environment/opt/eduk8s/etc/themes/educates/static/static/libraries +head -c 200 "$LIB/bootstrap/css/bootstrap.min.css" # "Bootstrap v5.3.8" +head -c 120 "$LIB/jquery/jquery.min.js" # "jQuery v3.7.1" +head -c 200 "$LIB/font-awesome/css/all.min.css" # "Font Awesome Free 6.5.1" +head -c 200 "$LIB/underscore/underscore-umd-min.js" # underscore version +head -c 200 "$LIB/js-yaml/js-yaml.min.js" +head -c 200 "$LIB/jsonform/jsonform.min.js" +``` + +## Finding the latest upstream version + +- **bootstrap**: latest release at `https://github.com/twbs/bootstrap/releases` (use the latest stable `v5.x`, not a beta/alpha). +- **font-awesome**: latest "Free for Web" release at `https://github.com/FortAwesome/Font-Awesome/releases` (the asset named `fontawesome-free--web.zip`). +- **jquery / underscore / jsonform / js-yaml**: the npm version. Check `https://www.npmjs.com/package/` (or `https://registry.npmjs.org//latest`). jsDelivr serves any published npm version at the URL pattern above. + +Use WebFetch to read the releases/npm page and pick the latest stable version. For major-version bumps, read the changelog for breaking changes and flag them to the user before proceeding. + +## Update process + +Set up the path and a scratch dir: + +```bash +LIB=workshop-images/base-environment/opt/eduk8s/etc/themes/educates/static/static/libraries +TMP=$(mktemp -d) +``` + +### Single-file libraries (jquery, underscore, jsonform, js-yaml) + +Just overwrite the file from the versioned jsDelivr URL. Example (jquery → ``): + +```bash +curl -fsSL "https://cdn.jsdelivr.net/npm/jquery@/dist/jquery.min.js" -o "$LIB/jquery/jquery.min.js" +``` + +Use the matching URL + target from the table for underscore, jsonform, js-yaml. Always use `curl -f` so a 404 (bad version/path) fails loudly instead of writing an error page into the asset. + +### Zip-subset libraries (bootstrap, font-awesome) + +Download the release zip, then copy only the listed files, stripping the zip's +top-level folder. Bootstrap example (`` e.g. `5.3.8`): + +```bash +curl -fsSL "https://github.com/twbs/bootstrap/releases/download/v/bootstrap--dist.zip" -o "$TMP/bootstrap.zip" +unzip -q "$TMP/bootstrap.zip" -d "$TMP/bootstrap" +ROOT="$TMP/bootstrap/bootstrap--dist" +cp "$ROOT/css/bootstrap.min.css" "$LIB/bootstrap/css/bootstrap.min.css" +cp "$ROOT/js/bootstrap.bundle.min.js" "$LIB/bootstrap/js/bootstrap.bundle.min.js" +``` + +Font Awesome example (`` e.g. `6.5.1`): + +```bash +curl -fsSL "https://github.com/FortAwesome/Font-Awesome/releases/download//fontawesome-free--web.zip" -o "$TMP/fa.zip" +unzip -q "$TMP/fa.zip" -d "$TMP/fa" +ROOT="$TMP/fa/fontawesome-free--web" +cp "$ROOT/css/all.min.css" "$LIB/font-awesome/css/all.min.css" +for f in fa-brands-400 fa-regular-400 fa-solid-900 fa-v4compatibility; do + cp "$ROOT/webfonts/$f.woff2" "$LIB/font-awesome/webfonts/$f.woff2" + cp "$ROOT/webfonts/$f.ttf" "$LIB/font-awesome/webfonts/$f.ttf" +done +``` + +Before copying, `ls "$ROOT/css" "$ROOT/webfonts"` to confirm upstream still ships +these exact filenames; Font Awesome occasionally changes its webfont set across +major versions. If the set changed, update the table and the file list, and +`git rm` any file no longer shipped so stale assets don't linger. + +Clean up: `rm -rf "$TMP"`. + +## Verification + +1. Each updated file is non-empty and carries the new version banner: + ```bash + head -c 200 "$LIB//" + ``` + Confirm the version string matches what you intended (catches a silently + downloaded error page or a wrong path). +2. The downloaded file is the minified asset, not HTML (a 404 page). `file` or a + quick `head` should show JS/CSS/font content, not ``. +3. `git diff --stat` shows the expected files under `$LIB//` **and**, + when the version changed, the matching `package.json` (+ `package-lock.json`) + in `renderer`/`gateway` — see "Keep aligned with the renderer and gateway + apps". A theme-only change with no package.json update is usually a drift bug. +4. Full check (optional, heavy): rebuild the base environment image so the theme + bundles the new assets: + ```bash + make image-base-environment + ``` + then load a workshop and confirm the dashboard renders (no missing-asset 404s + in the browser console). + +## Notes and gotchas + +- These files are committed to git, so the update IS the change — there's no + separate sync step or lock file to regenerate. +- The libraries are not checksum-pinned; integrity rests on HTTPS plus the + version-banner and not-HTML checks in Verification above. +- Keep the target filenames exactly as listed — the theme's HTML/templates + reference them by these stable names (e.g. `jquery.min.js`, + `bootstrap.bundle.min.js`, `underscore-umd-min.js`). +- This skill only covers these six dashboard frontend libraries; it does not + touch base-image CLI tools (helm, yq, hugo, …) or any other software. + +## Post-upgrade checklist + +- [ ] Requested library/libraries downloaded from the correct versioned URL +- [ ] Files written to the exact target paths with stable filenames +- [ ] Version banner in each file matches the intended version +- [ ] No error-page HTML written into an asset (`curl -f` used) +- [ ] Font Awesome / Bootstrap: upstream file set unchanged, or table + stale files updated +- [ ] Matching npm dependency aligned to the same version in `renderer/package.json` and `gateway/package.json` (where present), with `npm install` run to update each lockfile +- [ ] `git diff --stat` limited to the intended library directories plus the aligned `package.json`/`package-lock.json` files +- [ ] Major-version bumps: changelog reviewed for breaking changes and flagged diff --git a/.github/workflows/build-and-publish-images.yaml b/.github/workflows/build-and-publish-images.yaml index 1d8beeb93..b6886b311 100644 --- a/.github/workflows/build-and-publish-images.yaml +++ b/.github/workflows/build-and-publish-images.yaml @@ -41,10 +41,14 @@ jobs: - image: assets-server - image: lookup-service - image: node-ca-injector + # The v4 operator lives outside the / convention, + # so it carries an explicit build context. + - image: operator + context: installer/operator steps: - name: Check out the repository - uses: actions/checkout@v4 + uses: actions/checkout@v6 - name: Calculate platforms shell: bash @@ -71,14 +75,14 @@ jobs: echo "REPOSITORY_OWNER=${REPOSITORY_OWNER,,}" >>${GITHUB_ENV} - name: Set up QEMU - uses: docker/setup-qemu-action@v3 + uses: docker/setup-qemu-action@v4 - name: Set up Docker buildx - uses: docker/setup-buildx-action@v3 + uses: docker/setup-buildx-action@v4 - name: Free Disk Space if: ${{ (matrix.image == 'secrets-manager') || (matrix.image == 'session-manager') || (matrix.image == 'training-portal') || (matrix.image == 'tunnel-manager') || (matrix.image == 'lookup-service') }} - uses: endersonmenezes/free-disk-space@v2 + uses: endersonmenezes/free-disk-space@v3 with: remove_android: true remove_dotnet: true @@ -87,7 +91,7 @@ jobs: - name: Restore Docker cache if: ${{ (matrix.image == 'secrets-manager') || (matrix.image == 'session-manager') || (matrix.image == 'training-portal') || (matrix.image == 'tunnel-manager') || (matrix.image == 'lookup-service') }} - uses: actions/cache/restore@v4 + uses: actions/cache/restore@v5 with: path: /tmp/.buildx-cache-amd64-new key: ${{runner.os}}-buildx-cache-${{matrix.image}}-${{github.sha}} @@ -101,7 +105,7 @@ jobs: - name: Generate container image metadata id: meta - uses: docker/metadata-action@v5 + uses: docker/metadata-action@v6 with: images: | ghcr.io/${{env.REPOSITORY_OWNER}}/educates-${{matrix.image}} @@ -112,16 +116,24 @@ jobs: type=sha - name: Login to GitHub container registry - uses: docker/login-action@v3 + uses: docker/login-action@v4 with: username: ${{github.actor}} password: ${{secrets.GITHUB_TOKEN}} registry: ghcr.io + # On release tags the operator image must embed the runtime + # subchart tarballs at the released version (versions are stamped + # in CI, not committed — see decisions.md). + - name: Stamp release version into operator chart embeds + if: matrix.image == 'operator' && startsWith(github.ref, 'refs/tags/') + shell: bash + run: ./hack/stamp-release-version.sh "${GITHUB_REF##*/}" ghcr.io "${{env.REPOSITORY_OWNER}}" + - name: Build and push ${{matrix.image}} image - uses: docker/build-push-action@v6 + uses: docker/build-push-action@v7 with: - context: ${{matrix.image}} + context: ${{matrix.context || matrix.image}} platforms: ${{env.TARGET_PLATFORMS}} tags: ${{steps.meta.outputs.tags}} cache-from: type=local,src=/tmp/.buildx-cache-old @@ -139,7 +151,7 @@ jobs: - name: Save Docker cache if: ${{ (matrix.image == 'secrets-manager') || (matrix.image == 'session-manager') || (matrix.image == 'training-portal') || (matrix.image == 'tunnel-manager') || (matrix.image == 'lookup-service') }} - uses: actions/cache/save@v4 + uses: actions/cache/save@v5 with: path: /tmp/.buildx-cache-new key: ${{runner.os}}-buildx-cache-${{matrix.image}}-${{github.sha}} @@ -155,7 +167,7 @@ jobs: steps: - name: Free Disk Space - uses: endersonmenezes/free-disk-space@v2 + uses: endersonmenezes/free-disk-space@v3 with: remove_android: true remove_dotnet: true @@ -163,7 +175,7 @@ jobs: remove_tool_cache: true - name: Check out the repository - uses: actions/checkout@v4 + uses: actions/checkout@v6 - name: Calculate platforms shell: bash @@ -190,17 +202,17 @@ jobs: echo "REPOSITORY_OWNER=${REPOSITORY_OWNER,,}" >>${GITHUB_ENV} - name: Set up QEMU - uses: docker/setup-qemu-action@v3 + uses: docker/setup-qemu-action@v4 - name: Set up Docker buildx - uses: docker/setup-buildx-action@v3 + uses: docker/setup-buildx-action@v4 - name: Verify docker daemon image contents run: | docker images - name: Restore Docker cache - uses: actions/cache/restore@v4 + uses: actions/cache/restore@v5 with: path: /tmp/.buildx-cache-new key: ${{runner.os}}-buildx-cache-base-environment-${{github.sha}} @@ -215,7 +227,7 @@ jobs: - name: Generate container image metadata id: meta - uses: docker/metadata-action@v5 + uses: docker/metadata-action@v6 with: images: | ghcr.io/${{env.REPOSITORY_OWNER}}/educates-base-environment @@ -226,14 +238,14 @@ jobs: type=sha - name: Login to GitHub container registry - uses: docker/login-action@v3 + uses: docker/login-action@v4 with: username: ${{github.actor}} password: ${{secrets.GITHUB_TOKEN}} registry: ghcr.io - name: Build and push base-environment image - uses: docker/build-push-action@v6 + uses: docker/build-push-action@v7 with: context: workshop-images/base-environment platforms: ${{env.TARGET_PLATFORMS}} @@ -251,7 +263,7 @@ jobs: du -ks /tmp/.buildx-cache-* || true - name: Save Docker cache - uses: actions/cache/save@v4 + uses: actions/cache/save@v5 with: path: /tmp/.buildx-cache-new key: ${{runner.os}}-buildx-cache-base-environment-${{github.sha}} @@ -280,7 +292,7 @@ jobs: steps: - name: Free Disk Space - uses: endersonmenezes/free-disk-space@v2 + uses: endersonmenezes/free-disk-space@v3 with: remove_android: true remove_dotnet: true @@ -288,7 +300,7 @@ jobs: remove_tool_cache: true - name: Check out the repository - uses: actions/checkout@v4 + uses: actions/checkout@v6 - name: Calculate platforms shell: bash @@ -316,10 +328,10 @@ jobs: echo "REPOSITORY_SHA_TAG=sha-${GITHUB_SHA::7}" >>${GITHUB_ENV} - name: Set up QEMU - uses: docker/setup-qemu-action@v3 + uses: docker/setup-qemu-action@v4 - name: Set up Docker buildx - uses: docker/setup-buildx-action@v3 + uses: docker/setup-buildx-action@v4 - name: Verify docker daemon image contents run: | @@ -327,7 +339,7 @@ jobs: - name: Restore Docker cache if: ${{ (matrix.image == 'conda-environment') }} - uses: actions/cache/restore@v4 + uses: actions/cache/restore@v5 with: path: /tmp/.buildx-cache-amd64-new key: ${{runner.os}}-buildx-cache-${{matrix.image}}-${{github.sha}} @@ -341,7 +353,7 @@ jobs: - name: Generate container image metadata id: meta - uses: docker/metadata-action@v5 + uses: docker/metadata-action@v6 with: images: | ghcr.io/${{env.REPOSITORY_OWNER}}/educates-${{matrix.image}} @@ -352,14 +364,14 @@ jobs: type=sha - name: Login to GitHub container registry - uses: docker/login-action@v3 + uses: docker/login-action@v4 with: username: ${{github.actor}} password: ${{secrets.GITHUB_TOKEN}} registry: ghcr.io - name: Build and push ${{matrix.image}} image - uses: docker/build-push-action@v6 + uses: docker/build-push-action@v7 with: context: workshop-images/${{matrix.image}} platforms: ${{env.TARGET_PLATFORMS}} @@ -381,138 +393,18 @@ jobs: du -ks /tmp/.buildx-cache-* || true - name: Save Docker cache - uses: actions/cache/save@v4 + uses: actions/cache/save@v5 with: path: /tmp/.buildx-cache-new key: ${{runner.os}}-buildx-cache-${{matrix.image}}-${{github.sha}} - publish-carvel-bundles: - name: Bundle - runs-on: ubuntu-latest - - permissions: - contents: read - packages: write - id-token: write - - needs: - - publish-generic-images - - publish-workshop-images - - steps: - - name: Check out the repository - uses: actions/checkout@v4 - - - name: Install Carvel tools - shell: bash - run: curl -L https://carvel.dev/install.sh | bash - - - name: Calculate variables - shell: bash - run: | - REPOSITORY_OWNER=${{github.repository_owner}} - echo "REPOSITORY_OWNER=${REPOSITORY_OWNER,,}" >>${GITHUB_ENV} - echo "REPOSITORY_TAG=${GITHUB_REF##*/}" >>${GITHUB_ENV} - echo "REPOSITORY_SHA_TAG=sha-${GITHUB_SHA::7}" >>${GITHUB_ENV} - - - name: Create publish values file - shell: bash - run: | - cat < publish-values.yaml - clusterInfrastructure: - provider: "custom" - clusterPackages: - contour: - enabled: true - settings: - infraProvider: custom - cert-manager: - enabled: true - settings: {} - external-dns: - enabled: true - settings: - infraProvider: custom - deployment: - args: - - --provider=custom - - --source=custom - certs: - enabled: true - settings: - certProvider: local - domains: - - "example.com" - local: - caCertificate: - ca.crt: "AA" - ca.key: "BB" - kyverno: - enabled: true - settings: {} - educates: - enabled: true - settings: - clusterIngress: - domain: "educates.example.com" - imageRegistry: - host: "ghcr.io" - namespace: ${{env.REPOSITORY_OWNER}} - version: ${{env.REPOSITORY_TAG}} - lookupService: - enabled: true - EOF - - - name: Publish educates-installer bundle - shell: bash - run: | - # Create the kbld-images.yaml file with references to educates images - ytt -f carvel-packages/installer/config/images.yaml \ - -f carvel-packages/installer/config/schema.yaml \ - -v imageRegistry.host=ghcr.io \ - -v imageRegistry.namespace=${{env.REPOSITORY_OWNER}} \ - -v version=${{env.REPOSITORY_TAG}} > carvel-packages/installer/bundle/kbld/kbld-images.yaml - # Cat the generated file for debugging purposes - cat carvel-packages/installer/bundle/kbld/kbld-images.yaml - # Create images lock file. We use a sample values file to pass validations - # We properly rewrite references to images via kbld - ytt --data-values-file publish-values.yaml \ - -f carvel-packages/installer/bundle/config | kbld -f - \ - -f carvel-packages/installer/bundle/kbld/kbld-images.yaml \ - --imgpkg-lock-output carvel-packages/installer/bundle/.imgpkg/images.yml - # Push the bundle to the registry - imgpkg push \ - -b ghcr.io/${{env.REPOSITORY_OWNER}}/educates-installer:${{env.REPOSITORY_TAG}} \ - -f carvel-packages/installer/bundle \ - --registry-username=${{github.actor}} \ - --registry-password=${{secrets.GITHUB_TOKEN}} - ytt -f carvel-packages/installer/config/app.yaml \ - -f carvel-packages/installer/config/schema.yaml \ - -v version=${{env.REPOSITORY_TAG}} \ - -v imageRegistry.host=ghcr.io \ - -v imageRegistry.namespace=${{env.REPOSITORY_OWNER}} > educates-installer-app.yaml - # Copy and rename rbac.yaml file - cp carvel-packages/installer/config/rbac.yaml educates-installer-app-rbac.yaml - - - name: Save educates-installer-app.yaml - uses: actions/upload-artifact@v4 - with: - name: educates-installer-app.yaml - path: educates-installer-app.yaml - - - name: Save educates-installer-app-rbac.yaml - uses: actions/upload-artifact@v4 - with: - name: educates-installer-app-rbac.yaml - path: educates-installer-app-rbac.yaml - build-client-programs-linux-amd64: name: Build (clients) / amd64@linux runs-on: ubuntu-latest steps: - name: Check out the repository - uses: actions/checkout@v4 + uses: actions/checkout@v6 - name: Calculate variables shell: bash @@ -528,6 +420,13 @@ jobs: cache-dependency-path: | client-programs/go.sum + # On release tags the chart embedded in the CLI must carry the + # released version and this fork's registry annotations. + - name: Stamp release version into embedded chart + if: startsWith(github.ref, 'refs/tags/') + shell: bash + run: ./hack/stamp-release-version.sh "${{env.REPOSITORY_TAG}}" ghcr.io "${{env.REPOSITORY_OWNER}}" --charts-only + - name: Build educates client program shell: bash run: | @@ -539,7 +438,7 @@ jobs: IMAGE_REPOSITORY=ghcr.io/${{env.REPOSITORY_OWNER}} go build -o educates-linux-amd64 -ldflags "-X 'main.projectVersion=$REPOSITORY_TAG' -X 'main.imageRepository=$IMAGE_REPOSITORY'" cmd/educates/main.go - - uses: actions/upload-artifact@v4 + - uses: actions/upload-artifact@v7 with: name: educates-linux-amd64 path: client-programs/educates-linux-amd64 @@ -550,7 +449,7 @@ jobs: steps: - name: Check out the repository - uses: actions/checkout@v4 + uses: actions/checkout@v6 - name: Calculate variables shell: bash @@ -566,6 +465,13 @@ jobs: cache-dependency-path: | client-programs/go.sum + # On release tags the chart embedded in the CLI must carry the + # released version and this fork's registry annotations. + - name: Stamp release version into embedded chart + if: startsWith(github.ref, 'refs/tags/') + shell: bash + run: ./hack/stamp-release-version.sh "${{env.REPOSITORY_TAG}}" ghcr.io "${{env.REPOSITORY_OWNER}}" --charts-only + - name: Build educates client program shell: bash run: | @@ -577,7 +483,7 @@ jobs: IMAGE_REPOSITORY=ghcr.io/${{env.REPOSITORY_OWNER}} GOOS=linux GOARCH=arm64 go build -o educates-linux-arm64 -ldflags "-X 'main.projectVersion=$REPOSITORY_TAG' -X 'main.imageRepository=$IMAGE_REPOSITORY'" cmd/educates/main.go - - uses: actions/upload-artifact@v4 + - uses: actions/upload-artifact@v7 with: name: educates-linux-arm64 path: client-programs/educates-linux-arm64 @@ -588,7 +494,7 @@ jobs: steps: - name: Check out the repository - uses: actions/checkout@v4 + uses: actions/checkout@v6 - name: Calculate variables shell: bash @@ -604,6 +510,13 @@ jobs: cache-dependency-path: | client-programs/go.sum + # On release tags the chart embedded in the CLI must carry the + # released version and this fork's registry annotations. + - name: Stamp release version into embedded chart + if: startsWith(github.ref, 'refs/tags/') + shell: bash + run: ./hack/stamp-release-version.sh "${{env.REPOSITORY_TAG}}" ghcr.io "${{env.REPOSITORY_OWNER}}" --charts-only + - name: Build educates client program shell: bash run: | @@ -616,7 +529,7 @@ jobs: # Need to build for amd64 on darwin on an arm64 runner as they are deprecating amd64 runner. GOOS=darwin GOARCH=amd64 go build -o educates-darwin-amd64 -ldflags "-X 'main.projectVersion=$REPOSITORY_TAG' -X 'main.imageRepository=$IMAGE_REPOSITORY'" cmd/educates/main.go - - uses: actions/upload-artifact@v4 + - uses: actions/upload-artifact@v7 with: name: educates-darwin-amd64 path: client-programs/educates-darwin-amd64 @@ -627,7 +540,7 @@ jobs: steps: - name: Check out the repository - uses: actions/checkout@v4 + uses: actions/checkout@v6 - name: Calculate variables shell: bash @@ -643,6 +556,13 @@ jobs: cache-dependency-path: | client-programs/go.sum + # On release tags the chart embedded in the CLI must carry the + # released version and this fork's registry annotations. + - name: Stamp release version into embedded chart + if: startsWith(github.ref, 'refs/tags/') + shell: bash + run: ./hack/stamp-release-version.sh "${{env.REPOSITORY_TAG}}" ghcr.io "${{env.REPOSITORY_OWNER}}" --charts-only + - name: Build educates client program shell: bash run: | @@ -654,72 +574,11 @@ jobs: IMAGE_REPOSITORY=ghcr.io/${{env.REPOSITORY_OWNER}} go build -o educates-darwin-arm64 -ldflags "-X 'main.projectVersion=$REPOSITORY_TAG' -X 'main.imageRepository=$IMAGE_REPOSITORY'" cmd/educates/main.go - - uses: actions/upload-artifact@v4 + - uses: actions/upload-artifact@v7 with: name: educates-darwin-arm64 path: client-programs/educates-darwin-arm64 - publish-client-programs: - name: Client Programs Imgpkg Bundle - runs-on: ubuntu-latest - - permissions: - contents: read - packages: write - id-token: write - - needs: - - build-client-programs-linux-amd64 - - build-client-programs-linux-arm64 - - build-client-programs-darwin-amd64 - - build-client-programs-darwin-arm64 - - steps: - - name: Restore educates-linux-amd64 - uses: actions/download-artifact@v4 - with: - name: educates-linux-amd64 - path: client-programs - - - name: Restore educates-linux-arm64 - uses: actions/download-artifact@v4 - with: - name: educates-linux-arm64 - path: client-programs - - - name: Restore educates-darwin-amd64 - uses: actions/download-artifact@v4 - with: - name: educates-darwin-amd64 - path: client-programs - - - name: Restore educates-darwin-arm64 - uses: actions/download-artifact@v4 - with: - name: educates-darwin-arm64 - path: client-programs - - - name: Install Carvel tools - shell: bash - run: curl -L https://carvel.dev/install.sh | bash - - - name: Calculate variables - shell: bash - run: | - REPOSITORY_OWNER=${{github.repository_owner}} - echo "REPOSITORY_OWNER=${REPOSITORY_OWNER,,}" >>${GITHUB_ENV} - echo "REPOSITORY_TAG=${GITHUB_REF##*/}" >>${GITHUB_ENV} - - - name: Publish client programs - shell: bash - run: | - chmod +x client-programs/* - imgpkg push \ - -i ghcr.io/${{env.REPOSITORY_OWNER}}/educates-client-programs:${{env.REPOSITORY_TAG}} \ - -f client-programs \ - --registry-username=${{github.actor}} \ - --registry-password=${{secrets.GITHUB_TOKEN}} - publish-cli-image: name: Publish (cli) image runs-on: ubuntu-latest @@ -734,7 +593,7 @@ jobs: steps: - name: Check out the repository - uses: actions/checkout@v4 + uses: actions/checkout@v6 - name: Calculate variables shell: bash @@ -742,6 +601,14 @@ jobs: REPOSITORY_OWNER=${{github.repository_owner}} echo "REPOSITORY_OWNER=${REPOSITORY_OWNER,,}" >>${GITHUB_ENV} echo "REPOSITORY_SHA_TAG=sha-${GITHUB_SHA::7}" >>${GITHUB_ENV} + echo "REPOSITORY_TAG=${GITHUB_REF##*/}" >>${GITHUB_ENV} + + # On release tags the chart embedded in the CLI must carry the + # released version and this fork's registry annotations. + - name: Stamp release version into embedded chart + if: startsWith(github.ref, 'refs/tags/') + shell: bash + run: ./hack/stamp-release-version.sh "${{env.REPOSITORY_TAG}}" ghcr.io "${{env.REPOSITORY_OWNER}}" --charts-only - name: Calculate platforms shell: bash @@ -769,7 +636,7 @@ jobs: - name: Generate container image metadata id: meta - uses: docker/metadata-action@v5 + uses: docker/metadata-action@v6 with: images: | ghcr.io/${{env.REPOSITORY_OWNER}}/educates-cli @@ -780,20 +647,22 @@ jobs: type=sha - name: Login to GitHub container registry - uses: docker/login-action@v3 + uses: docker/login-action@v4 with: username: ${{github.actor}} password: ${{secrets.GITHUB_TOKEN}} registry: ghcr.io - name: Build and push docker-cli image - uses: docker/build-push-action@v6 + uses: docker/build-push-action@v7 with: context: client-programs platforms: ${{env.TARGET_PLATFORMS}} build-args: | REPOSITORY=ghcr.io/${{env.REPOSITORY_OWNER}} TAG=${{env.REPOSITORY_SHA_TAG}} + PROJECT_VERSION=${{env.REPOSITORY_TAG}} + IMAGE_REPOSITORY=ghcr.io/${{env.REPOSITORY_OWNER}} tags: ${{steps.meta.outputs.tags}} push: true @@ -811,7 +680,7 @@ jobs: steps: - name: Check out the repository - uses: actions/checkout@v4 + uses: actions/checkout@v6 - name: Calculate variables shell: bash @@ -839,14 +708,14 @@ jobs: echo "TARGET_PLATFORMS=${TARGET_PLATFORMS}" >>${GITHUB_ENV} - name: Set up QEMU - uses: docker/setup-qemu-action@v3 + uses: docker/setup-qemu-action@v4 - name: Set up Docker buildx - uses: docker/setup-buildx-action@v3 + uses: docker/setup-buildx-action@v4 - name: Generate container image metadata id: meta - uses: docker/metadata-action@v5 + uses: docker/metadata-action@v6 with: images: | ghcr.io/${{env.REPOSITORY_OWNER}}/educates-docker-extension @@ -857,14 +726,14 @@ jobs: type=sha - name: Login to GitHub container registry - uses: docker/login-action@v3 + uses: docker/login-action@v4 with: username: ${{github.actor}} password: ${{secrets.GITHUB_TOKEN}} registry: ghcr.io - name: Build and push docker-extension image - uses: docker/build-push-action@v6 + uses: docker/build-push-action@v7 with: context: docker-extension platforms: ${{env.TARGET_PLATFORMS}} @@ -874,17 +743,169 @@ jobs: tags: ${{steps.meta.outputs.tags}} push: true + publish-charts: + name: Publish (helm charts) + runs-on: ubuntu-latest + if: startsWith(github.ref, 'refs/tags/') + + permissions: + contents: read + packages: write + + # Charts reference the images this run publishes; don't push charts + # for a release whose images failed. + needs: + - publish-generic-images + + steps: + - name: Check out the repository + uses: actions/checkout@v6 + + - name: Calculate variables + shell: bash + run: | + REPOSITORY_OWNER=${{github.repository_owner}} + echo "REPOSITORY_OWNER=${REPOSITORY_OWNER,,}" >>${GITHUB_ENV} + echo "REPOSITORY_TAG=${GITHUB_REF##*/}" >>${GITHUB_ENV} + + - name: Stamp release version + shell: bash + run: ./hack/stamp-release-version.sh "${{env.REPOSITORY_TAG}}" ghcr.io "${{env.REPOSITORY_OWNER}}" + + - name: Package charts + shell: bash + run: | + mkdir -p dist + helm package installer/charts/educates-installer --destination dist + helm package installer/charts/educates-training-platform --destination dist + + - name: Login to GitHub container registry + shell: bash + run: | + echo "${{secrets.GITHUB_TOKEN}}" | helm registry login ghcr.io \ + --username ${{github.actor}} --password-stdin + + - name: Push charts to OCI registry + shell: bash + run: | + helm push dist/educates-installer-${{env.REPOSITORY_TAG}}.tgz \ + oci://ghcr.io/${{env.REPOSITORY_OWNER}}/charts + helm push dist/educates-training-platform-${{env.REPOSITORY_TAG}}.tgz \ + oci://ghcr.io/${{env.REPOSITORY_OWNER}}/charts + + - uses: actions/upload-artifact@v7 + with: + name: helm-charts + path: dist/*.tgz + + publish-schemas: + name: Publish (json schemas) + runs-on: ubuntu-latest + if: startsWith(github.ref, 'refs/tags/') + # Deploys to this repository's GitHub Pages site (upstream maps it + # to schemas.educates.dev — see developer-docs/json-schemas.md). + # Forks without Pages enabled fail the deploy step; that must not + # gate the release. + continue-on-error: true + + permissions: + contents: read + pages: write + id-token: write + + environment: + name: github-pages + url: ${{steps.deployment.outputs.page_url}} + + steps: + - name: Check out the repository + uses: actions/checkout@v6 + + # Published filenames drop the .schema infix to match the $id + # baked into each schema (…/cli/v1alpha1/.json). + - name: Stage schemas + shell: bash + run: | + mkdir -p site/cli/v1alpha1 + for f in client-programs/pkg/config/v1alpha1/schemas/*.schema.json; do + name=$(basename "$f" .schema.json) + cp "$f" "site/cli/v1alpha1/$name.json" + done + { + echo 'Educates CLI JSON schemas' + echo '

Educates CLI JSON schemas (cli.educates.dev/v1alpha1)

    ' + for f in site/cli/v1alpha1/*.json; do + echo "
  • $(basename "$f")
  • " + done + echo '
' + } > site/index.html + + - name: Setup Pages + uses: actions/configure-pages@v6 + + - name: Upload Pages artifact + uses: actions/upload-pages-artifact@v5 + with: + path: site + + - name: Deploy to GitHub Pages + id: deployment + uses: actions/deploy-pages@v5 + + publish-image-list: + name: Publish (image list) + runs-on: ubuntu-latest + if: startsWith(github.ref, 'refs/tags/') + + permissions: + contents: read + packages: read + + # Digest resolution needs every listed image already pushed. + needs: + - publish-generic-images + - publish-workshop-base-image + + steps: + - name: Check out the repository + uses: actions/checkout@v6 + + - name: Calculate variables + shell: bash + run: | + REPOSITORY_OWNER=${{github.repository_owner}} + echo "REPOSITORY_OWNER=${REPOSITORY_OWNER,,}" >>${GITHUB_ENV} + echo "REPOSITORY_TAG=${GITHUB_REF##*/}" >>${GITHUB_ENV} + + # Digest-pinned list of every image an air-gapped install needs + # (platform images + base-environment + upstream cluster-service + # images from the vendored charts). Attached to the GitHub + # release for name-preserving mirroring with skopeo/crane. + - name: Generate image list + shell: bash + run: | + skopeo login ghcr.io --username ${{github.actor}} --password ${{secrets.GITHUB_TOKEN}} + ./hack/generate-image-list.sh "${{env.REPOSITORY_TAG}}" ghcr.io "${{env.REPOSITORY_OWNER}}" \ + > educates-images-${{env.REPOSITORY_TAG}}.txt + cat educates-images-${{env.REPOSITORY_TAG}}.txt + + - uses: actions/upload-artifact@v7 + with: + name: image-list + path: educates-images-*.txt + release-artifacts: name: Release runs-on: ubuntu-latest if: startsWith(github.ref, 'refs/tags/') needs: - - publish-carvel-bundles - build-client-programs-linux-amd64 - build-client-programs-linux-arm64 - build-client-programs-darwin-amd64 - build-client-programs-darwin-arm64 - publish-docker-extension + - publish-charts + - publish-image-list steps: - name: Calculate variables @@ -899,36 +920,36 @@ jobs: echo "REPOSITORY_TAG=${REPOSITORY_TAG}" >>${GITHUB_ENV} echo "PRERELEASE=${PRERELEASE}" >>${GITHUB_ENV} - - name: Restore educates-installer-app.yaml - uses: actions/download-artifact@v4 - with: - name: educates-installer-app.yaml - - - name: Restore educates-installer-app-rbac.yaml - uses: actions/download-artifact@v4 - with: - name: educates-installer-app-rbac.yaml - - name: Restore educates-linux-amd64 - uses: actions/download-artifact@v4 + uses: actions/download-artifact@v8 with: name: educates-linux-amd64 - name: Restore educates-linux-arm64 - uses: actions/download-artifact@v4 + uses: actions/download-artifact@v8 with: name: educates-linux-arm64 - name: Restore educates-darwin-amd64 - uses: actions/download-artifact@v4 + uses: actions/download-artifact@v8 with: name: educates-darwin-amd64 - name: Restore educates-darwin-arm64 - uses: actions/download-artifact@v4 + uses: actions/download-artifact@v8 with: name: educates-darwin-arm64 + - name: Restore helm charts + uses: actions/download-artifact@v8 + with: + name: helm-charts + + - name: Restore image list + uses: actions/download-artifact@v8 + with: + name: image-list + - name: Generate file checksums for CLI binaries shell: bash run: | @@ -936,27 +957,28 @@ jobs: sha256sum educates-darwin-arm64 >> checksums.txt sha256sum educates-linux-amd64 >> checksums.txt sha256sum educates-linux-arm64 >> checksums.txt - sha256sum educates-installer-app.yaml >> checksums.txt - sha256sum educates-installer-app-rbac.yaml >> checksums.txt + sha256sum educates-installer-${{env.REPOSITORY_TAG}}.tgz >> checksums.txt + sha256sum educates-training-platform-${{env.REPOSITORY_TAG}}.tgz >> checksums.txt + sha256sum educates-images-${{env.REPOSITORY_TAG}}.txt >> checksums.txt echo 'File Checksums' >> release-notes.md echo '--------------' >> release-notes.md echo '```' >> release-notes.md cat checksums.txt >> release-notes.md echo '```' >> release-notes.md - - uses: actions/upload-artifact@v4 + - uses: actions/upload-artifact@v7 with: name: checksums.txt path: checksums.txt - - uses: actions/upload-artifact@v4 + - uses: actions/upload-artifact@v7 with: name: release-notes.md path: release-notes.md - name: Create release id: create_release - uses: softprops/action-gh-release@v2 + uses: softprops/action-gh-release@v3 env: GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}} with: @@ -967,9 +989,10 @@ jobs: body_path: release-notes.md files: | checksums.txt - educates-installer-app.yaml - educates-installer-app-rbac.yaml educates-linux-amd64 educates-linux-arm64 educates-darwin-amd64 educates-darwin-arm64 + educates-installer-*.tgz + educates-training-platform-*.tgz + educates-images-*.txt diff --git a/.github/workflows/client-programs-ci.yaml b/.github/workflows/client-programs-ci.yaml new file mode 100644 index 000000000..9cc35af7e --- /dev/null +++ b/.github/workflows/client-programs-ci.yaml @@ -0,0 +1,41 @@ +name: Client Programs CI + +on: + push: + branches: [develop, main] + paths: + - 'client-programs/**' + - 'installer/charts/educates-installer/**' + - 'go.work' + - 'go.work.sum' + - '.github/workflows/client-programs-ci.yaml' + pull_request: + paths: + - 'client-programs/**' + - 'installer/charts/educates-installer/**' + - 'go.work' + - 'go.work.sum' + - '.github/workflows/client-programs-ci.yaml' + +jobs: + ci: + name: Build, vet, test, drift checks + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v6 + + - uses: actions/setup-go@v6 + with: + go-version-file: client-programs/go.mod + cache-dependency-path: | + go.work.sum + client-programs/go.sum + + # Single source of truth: `make ci-cli` runs exactly the checks + # this job gates — theme-file staging, go vet/build/test, and the + # embedded-chart + CLI-schema drift checks. Edit the Makefile, not + # this list, so local `make ci` and CI never drift apart. See + # developer-docs/build-instructions.md. + - name: make ci-cli + run: make ci-cli diff --git a/.github/workflows/installer-operator-ci.yaml b/.github/workflows/installer-operator-ci.yaml new file mode 100644 index 000000000..6031978a0 --- /dev/null +++ b/.github/workflows/installer-operator-ci.yaml @@ -0,0 +1,44 @@ +name: Installer Operator CI + +on: + push: + branches: [develop, main] + paths: + - 'installer/operator/**' + - 'installer/charts/**' + - 'hack/**' + - 'go.work' + - 'go.work.sum' + - '.github/workflows/installer-operator-ci.yaml' + pull_request: + paths: + - 'installer/operator/**' + - 'installer/charts/**' + - 'hack/**' + - 'go.work' + - 'go.work.sum' + - '.github/workflows/installer-operator-ci.yaml' + +jobs: + ci: + name: Chart-sync, build, vet, drift, envtest, lint + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v6 + + - uses: actions/setup-go@v6 + with: + go-version-file: installer/operator/go.mod + cache-dependency-path: | + go.work.sum + installer/operator/go.sum + + # Single source of truth: `make ci-operator` runs exactly the + # checks this job gates — chart-version/annotation lint, go + # vet/build, CRD/RBAC + DeepCopy drift checks, envtest, and + # golangci-lint. Edit the Makefile, not this list, so local + # `make ci` and CI never drift apart. See + # developer-docs/build-instructions.md. + - name: make ci-operator + run: make ci-operator diff --git a/.gitignore b/.gitignore index e815c7a5d..fb75ddd02 100644 --- a/.gitignore +++ b/.gitignore @@ -3,9 +3,6 @@ __pycache__ *.swp *.vsix .netlify -/carvel-packages/installer/test-*.yaml -/carvel-packages/installer/bundle/.imgpkg/images.yml -/carvel-packages/installer/bundle/kbld/kbld-images.yaml /client-programs/bin /client-programs/pkg/renderer/files /developer-testing @@ -34,3 +31,6 @@ vendor # AI Assistant specific files .cursor + +# Claude Code user-local config and skills +/.claude diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 000000000..5c7019bea --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,502 @@ +# CLAUDE.md + +This file is a briefing for Claude Code working in this repository. Read it +fully before doing anything substantial. Sections are ordered by importance — +the top is what changes day-to-day, the bottom is mostly stable. + +--- + +## What's happening right now + +The v4 install path is the only install path in this repo. v3 +(Carvel-based installer, `carvel-packages/installer/`, kapp-controller) +has been deleted from the CLI and tree. + +- **Install pipeline:** Helm-chart + Go operator. Users run + `educates admin platform deploy` (helm install operator chart + + kubectl apply 4 platform CRs), or `educates local cluster create` + for the laptop flow (kind + registry + deploy in one). +- **v3 is gone.** There's no in-place migration. Users on v3 delete + their old install and follow the v4 path. The CLI silently migrates + a v3 `values.yaml` → v4 `config.yaml` on first run when the v3 + provider was kind (or empty); other providers get a clear + re-declare error (Phase 5 step 10, landed 2026-06-06). +- **CLI config is a kind ladder** (`cli.educates.dev/v1alpha1`): + `EducatesLocalConfig` (laptop; lives at `/config.yaml`), + scenario kinds `EducatesGKEConfig` / `EducatesEKSConfig` / + `EducatesInlineConfig`, and the `EducatesConfig` escape hatch (CR + specs verbatim, no CLI defaults). JSON schemas are embedded at + `client-programs/pkg/config/v1alpha1/schemas/`. Data home is + `$XDG_DATA_HOME/educates/`, overridable via `EDUCATES_CLI_DATA_HOME`. + See decisions log. + +**Carvel libraries still live in the CLI** (`carvel.dev/imgpkg`, +`kapp`, `ytt`, `vendir`) — they power the **workshop tooling** +(`educates {cluster,docker} workshop ...` commands for publish / +deploy / serve). The install path no longer touches them. + +**The Educates runtime is not changing in v4.** Components in +`session-manager/`, `secrets-manager/`, `lookup-service/`, +`training-portal/`, `tunnel-manager/`, `workshop-images/`, and supporting +services keep their current Python/kopf/Django implementations. Only the +installation mechanism and packaging changes. + +Phases 0–5 are complete. The active work is post-Phase-5 hardening +(operator follow-ups from `docs/architecture/follow-up-issues.md`, CI +drift checks) and Phase 6 release prep. Day-to-day, that's what code +changes should advance. + +--- + +## Repository scope: what's safe to change vs not + +When working on v4 installer tasks: + +**Safe to create/modify:** +- New code for the v4 installer (operator, CRDs, Helm charts). Charts should + live in `installer/charts`, operator code in `installer/operator`, + vendored upstream Helm charts in `installer/operator/vendored-charts`. +- The CLI in `client-programs/` — needs significant changes for v4. The + existing Carvel-related code will be removed; new commands wrap the + Helm-chart + CR-apply workflow. +- Documentation in `project-docs/` for v4 installation flows. +- Architecture documents in `docs/architecture/`. + +**Don't touch unless explicitly asked:** +- `session-manager/`, `secrets-manager/`, `training-portal/`, + `lookup-service/`, `tunnel-manager/`, `node-ca-injector/`, + `assets-server/`, `image-cache/` — runtime components, not changing in v4. +- `workshop-images/` — workshop runtime, orthogonal to installer work. +- (Deleted) `carvel-packages/` and `vendir.yml` — gone with v3, + including the release workflow's old "Publish educates-installer + bundle" job (removed 2026-06-10; a v4 chart-publish step replaces it + in Phase 6). + +**Special case:** if a v4 task needs a runtime component change (very rare — +e.g., a config flag the runtime needs to consume differently), flag it +explicitly before changing the runtime. These changes have wider +implications. + +--- + +## Working norms + +How I expect to collaborate: + +- **Ask before destructive operations.** `rm`, `git push`, `git reset --hard`, + deleting files outside `/tmp` — confirm first. +- **Don't push to remote.** Commits are fine when asked; pushes are mine. +- **Small, focused commits with clear messages.** Conventional Commits style + preferred (`feat(operator): ...`, `fix(crd): ...`). +- **No `Co-Authored-By: Claude` trailers in commit messages.** Commits are + authored by me; collaboration with you is a working detail, not a + history artefact. Plain commit message body, no attribution footer. +- **Don't run tests unless asked.** I'll often want to inspect intermediate + state without test runs interfering. +- **Verify Helm chart values before suggesting them.** `helm show values + ` is the source of truth, not your training data. +- **Verify Kubernetes API semantics before suggesting them.** Especially + finalizers, namespace deletion, controller-runtime cache behavior. When in + doubt, ask me to verify, or read the source. +- **Prefer asking over assuming.** A clarifying question costs me 10 seconds. + Wrong code costs me 30 minutes of debugging plus the time to undo it. +- **When uncertain about a design decision, stop and ask.** Don't pick a + direction and run with it. +- **Always draft a plan or check-list when working with complex tasks**. If you envision + the task is going to be long, either plan properly if needed, or at least create + a task-list to track progress. +- **Every user-facing change needs a release-notes entry to be complete.** Before + considering a change done, add or update the matching entry in + `project-docs/release-notes/version-4.0.0.md` (New Features / Features Changed / + Bugs Fixed). Purely internal changes — refactors, CI, tests, developer docs — + are exempt. Match the file's prose style: full sentences, double-backtick + literals, wrapped lines. + +--- + +## Reference documents (read these when relevant) + +These documents live in `docs/architecture/` and contain decisions that +shouldn't be relitigated: + +- **`educates-crd-draft-v1alpha1-r3.md`** — full design of the four v4 CRDs + (EducatesClusterConfig, SecretsManager, LookupService, SessionManager). + Currently at revision 3. Read before any CRD-related work. +- **`educates-v4-development-plan.md`** — phased plan for v4 implementation, estimates, + collaboration playbook, risks, open items. Read before starting a new + phase. +- **`decisions.md`** — log of architectural decisions and their rationale. + One paragraph per decision. Update when significant decisions are made. + +If something I ask contradicts these docs, point at the doc. If the doc is +wrong, we update it explicitly — don't silently diverge from it. + +--- + +## Build and run commands + +### Install path (v4 only) + +CLI-driven (laptop or single command from CI): + +```bash +educates local secrets add ca -ca --domain # one-time: generate self-signed CA +educates local config init # one-time: write a minimal config +educates local cluster create # kind + registry + deploy in one +# Or after the cluster's already up: +educates admin platform deploy --local-config +educates admin platform render --local-config # dry-run / GitOps preview +educates admin platform delete # uninstall +``` + +Raw helm + kubectl path (no CLI): + +```bash +helm install educates-installer ./installer/charts/educates-installer \ + --namespace educates-installer --create-namespace +kubectl apply -f educates-cluster-config.yaml +kubectl apply -f educates-secrets-manager.yaml +kubectl apply -f educates-lookup-service.yaml # optional +kubectl apply -f educates-session-manager.yaml +``` + +#### Operator project (Phase 0+) + +The Go operator lives at `installer/operator/` (kubebuilder project, +with the standard `config/` kustomize tree stripped — `controller-gen` +writes CRDs and RBAC directly into the `educates-installer` chart). +Module path: `github.com/educates/educates-training-platform/installer/operator`, +in `go.work`. API packages: `api/config/v1alpha1` (EducatesClusterConfig) +and `api/platform/v1alpha1` (SecretsManager, LookupService, +SessionManager). + +Make targets, all run from `installer/operator/`: + +```bash +make manifests # Regenerate CRDs + RBAC into the chart +make generate # Regenerate deepcopy +make test # Run envtest (downloads binaries on first run) +make envtest # Just download envtest binaries +make docker-build # Build local operator image (Phase 0 dev only) +make smoke-test # kind + helm install + apply CR + assert log line +make lint # golangci-lint +make vendor-charts # Download upstream charts into vendored-charts/, verify SHA256 +make verify-vendored-charts # Re-verify SHA256 of tarballs already on disk +``` + +Phase status (as of 2026-06-10): + +- **Phase 0 (foundations) — done.** Scaffold, CRDs, chart, envtest, smoke + test, CI all in place. Reconcilers were stubs. +- **Phase 1 (Inline mode) — done.** EducatesClusterConfig Inline-mode + validator + watches + finalizer + status contract live; the three + platform reconcilers (SecretsManager, LookupService, SessionManager) + are still stubs until Phase 4. +- **Phase 2 (Bundled cert-manager end-to-end) — done.** Session 1 + groundwork (vendoring + Helm SDK wrapper + typed cert-manager access) + plus Session 2's three commits land the full Managed-mode pipeline: + embedded-chart install via `//go:embed`; cert-manager Deployment + readiness gate; CustomCA Secret copy operator-ns → cert-manager-ns; + ClusterIssuer + wildcard Certificate via SSA (field manager + `educates-installer`); `status.ingress` published with + wildcardCertificateSecretRef + clusterIssuerRef; `CertificatesReady` + condition tied to `Certificate.Ready`; finalizer drains in reverse + install order. +- **Phase 3 (Contour + external-dns + Kyverno + ACME) — done.** The + remaining three cluster services land with the same shape as Phase 2: + vendored Helm chart, Deployment-readiness gate, finalizer drain in + reverse-install order, per-service Ready condition + (`IngressReady`, `DNSReady`, `PolicyEnforcementReady`) and + Bundled-chart version published to `status.bundledChartVersions`. + cert-manager grows ACME-DNS01 support for Route53 (IRSA on EKS) and + CloudDNS (Workload Identity on GKE); static-credentials Secrets and + Cloudflare/AzureDNS providers are reserved in the CRD but rejected as + "not yet supported" until follow-ups land them. Real-cluster + verification: kind (CustomCA + Contour, samples/01) and GKE + (CloudDNS-ACME + external-dns + Kyverno, samples/02). + Sample CRs live under `installer/samples/`. +- **Phase 4 (platform component reconcilers) — done (2026-05-14).** + Three sessions: SecretsManagerReconciler, LookupServiceReconciler, + SessionManagerReconciler. Each gates on + `EducatesClusterConfig.status` being Ready (SessionManager + additionally on SecretsManager.Ready), installs its component as a + Helm release from the vendored runtime subchart tarballs + (secrets-manager, lookup-service, session-manager + the + node-ca-injector / remote-access extras) into the shared `educates` + namespace, and drains it via finalizer. Four SessionManager spec + blocks are reserved but unwired (`themes`/`defaultTheme`, + `defaultAccessCredentials`, `imagePrePuller`, `registryMirrors`) — + see follow-up-issues.md. Known gap: deleting EducatesClusterConfig + before the platform CRs wedges SessionManager's helm uninstall + (Kyverno CRDs already gone) — fix tracked as the + `PlatformCRsPresent` finalizer guard. +- **Phase 5 (CLI rewrite) — done (2026-06-06).** All 11 steps landed: + kind-discriminated config loader + embedded JSON schemas, + CRD-derived `EducatesConfig` schema (`make generate-cli-schemas`), + translator (kind → operator chart values + 4 CRs), `admin platform + render/deploy/delete` (deploy owns the CRD lifecycle and waits + Ready; delete drains in reverse order with `--yes`/`--purge`), + schema-aware `local config init/get/set/view/edit`, `local cluster + create` tail-calling platform deploy with preflight checks, Carvel + install path deleted, first-run v3→v4 migration shim, and the + GKE/EKS/Inline scenario kinds. Open follow-ups tracked in + follow-up-issues.md. + +Living conventions (carry across phases unless superseded): + +- **Spec types carry the full r3 shape from day one.** Status grows + alongside the reconciler that produces each field. See decisions log. +- **CEL rules:** EducatesClusterConfig has three structural CEL rules + on spec — singleton name, mode immutability, mode-field exclusivity. + The three platform CRDs have singleton-name only. +- **RBAC:** EducatesClusterConfig reconciler has read-only `get/list/watch` + on its referenced kinds (Secrets, ClusterIssuers, IngressClasses) plus + full access on its own kind. Platform reconcilers carry full access + on their own kinds plus what their chart installs need — grown in + Phase 4 when the reconcilers came online. +- **Watches:** Secret + IngressClass + Deployment are registered + in `SetupWithManager` (operator-namespace-scoped Secret cache; + cluster-scoped IngressClass; Deployment cluster-wide). + cert-manager.io ClusterIssuer + Certificate are *deferred* — + registered at runtime by `CRDWatcher` + (`internal/controller/config/crd_watcher.go`) once discovery + confirms the CRDs exist. Activation lag is up to the + CRDWatcher's `PollInterval` (15s in production). cert-manager + CRDs are **not** a prerequisite for operator startup as of + 2026-05-13; the 2026-05-06 prerequisite decision was reversed + via the deferred-watch pattern, after a first attempt with + unstructured watches proved insufficient. See decisions log. +- **Watch event filtering:** Each watched kind has its own mapping + function (`mapSecretToSingleton`, `mapIngressClassToSingleton`, + etc., in `watches.go`) that drops events the reconciler can't + act on — referenced from spec or operator-owned only. Eliminates + the cluster-wide reconcile flood that cert-manager bootstrap + used to trigger. Each new watched kind added in Phase 3 gets + its own narrowing mapper. Deferred-watch kinds use the same + mapper machinery — `CRDWatcher.Targets` carries `(GVK, MapFunc)` + pairs. +- **cert-manager.io access split:** watches go through + CRDWatcher's deferred-registration path (no GVK-at-startup + requirement); Get / Create / Update / SSA-patch calls use + typed `cmv1.*` (those only run after `ensureCertManagerReady` + confirms the CRDs are present, so typed GVK resolution always + succeeds). On CRD *removal* post-activation (rare; mostly the + end of Managed-mode teardown), the reconciler classifies the + resulting `NoMatchError` / 404-with-UnexpectedServerResponse + via `isCertManagerCRDMissingErr` and surfaces + `CertificatesReady=False reason=CertManagerCRDsMissing`, + `phase=Degraded`. Controller-runtime's underlying Kind source + keeps spamming retry errors in the log until pod restart — + captured as a follow-up. +- **Helm SDK:** v4 (`helm.sh/helm/v4`), wrapped by + `installer/operator/internal/helm` so reconcilers don't repeat + `action.Configuration` boilerplate. Use `helm.NewClient(restCfg, ns)` + in production and `helm.NewMemoryClient(ns)` in tests. +- **Vendored upstream charts** live at `installer/operator/vendored-charts/-.tgz`, + integrity-recorded in `SHA256SUMS`. The operator loads them via + `helm.LoadArchive`. Refresh with `make vendor-charts` after updating + the version + hash entries. No `educates-cluster-services` umbrella + chart exists or is planned — the operator is the sole installer of + cluster services. +- **Operator image:** local-dev placeholder + `make docker-build` only. + Publish-time annotations + release workflow land in Phase 6. Running + `helm install` against the chart from a clone requires `make + docker-build` + `kind load` first. +- **Operator namespace** is supplied via the `OPERATOR_NAMESPACE` env + var (downward API in the chart Deployment). User-supplied Secrets + referenced from `EducatesClusterConfig.spec.inline` must live there. + +### Common + +```bash +make build-client-programs # Build educates CLI binary +cd client-programs && go mod tidy # Tidy CLI deps +cd node-ca-injector && go test ./... # Run Go tests +make build-project-docs # Build Sphinx docs +make prune-all # Clean caches and build artifacts +``` + +### CI parity (run the gating workflows locally) + +```bash +make ci # All CI checks (CLI + operator) +make ci-cli # client-programs-ci.yaml: vet/build/test + chart/schema drift +make ci-operator # installer-operator-ci.yaml: vet/build + manifest/deepcopy drift + envtest + lint +make stage-renderer-files # Stage the gitignored CLI theme embed dir (also done by build-cli/ci-cli) +``` + +`ci-operator` needs the Go version pinned in `installer/operator/go.mod` +on `PATH` (or `GOTOOLCHAIN=go1.x.y`) to avoid mixed-toolchain compile +errors. See `developer-docs/build-instructions.md`. + +--- + +## Architecture + +### Runtime components + +- **session-manager/** — Python/kopf operator managing workshop sessions, + environments, allocations, training portals, vcluster integration. Main + control plane. +- **secrets-manager/** — Python/kopf operator handling secret copying, + exporting, importing, injection across namespaces. +- **training-portal/** — Django web app, user-facing portal. Exposes REST API. +- **lookup-service/** — Python service for service discovery. +- **tunnel-manager/** — Hybrid Python/Go operator for network tunneling. +- **node-ca-injector/** — Go program injecting CA certificates into + Kubernetes nodes. +- **workshop-images/** — Dockerfiles for workshop session containers. + +### Installer + +- **installer/charts/educates-installer/** — the operator Helm chart. + Installed by `educates admin platform deploy` (via embedded copy at + `client-programs/pkg/deployer/chart/files/`) or by raw `helm install`. +- **installer/operator/** — the Go operator that reconciles the four + CRDs (EducatesClusterConfig, SecretsManager, LookupService, + SessionManager). Uses helm.sh/helm/v4 SDK to install cluster + services (cert-manager, contour, kyverno, external-dns) from + vendored upstream charts. +- **client-programs/** — Go CLI (`educates`). Holds the v4 install + pipeline (load → translate → helm install + apply CRs + wait Ready) + and the workshop tooling (publish, deploy, render — these still + use carvel libs for OCI bundle and kapp deploy). + +### Go workspace + +`go.work` covers `client-programs/` and `node-ca-injector/`. Other Go +services (`assets-server/`, `tunnel-manager/`) have their own `go.mod` and +are built only via Docker. + +--- + +## Architecture (target state — v4) + +The v4 installer has three layers: + +1. **`educates-installer` Helm chart** — installs the operator, four CRDs, + and RBAC. This is what users `helm install` (imperative) or what + ArgoCD/Flux points at (declarative). Same artifact, both paths. +2. **Go operator** — reconciles the four CRDs. Uses Helm Go SDK to install + upstream charts (cert-manager, contour, kyverno, external-dns) and the + `educates-training-platform` chart for the runtime. Has finalizers for + clean uninstall. +3. **`educates-training-platform` Helm chart** — umbrella chart with three + subcharts (secrets-manager, lookup-service, session-manager). Installs + the Educates runtime. Also usable standalone for users who don't want + the operator. + +The four CRDs (all cluster-scoped, all singletons named `cluster`): + +- **`EducatesClusterConfig`** (`config.educates.dev/v1alpha1`) — + cluster-wide infrastructure and services. Two modes: `Managed` (operator + installs services) and `Inline` (user declares pre-existing resources). +- **`SecretsManager`** (`platform.educates.dev/v1alpha1`) — secrets-manager + component. +- **`LookupService`** (`platform.educates.dev/v1alpha1`) — lookup-service + component. +- **`SessionManager`** (`platform.educates.dev/v1alpha1`) — session-manager + component. Requires SecretsManager.Ready. + +Components consume `EducatesClusterConfig.status` as their input contract. +They never read its `.spec` directly. This is what lets Inline mode work +without components knowing the difference. + +For full schema details, see `docs/architecture/educates-crd-draft-v1alpha1-r3.md`. + +--- + +## Key conventions and gotchas + +**CRDs and Go types:** +- Field names follow Kubernetes conventions: `camelCase` in YAML/JSON, + `PascalCase` in Go structs, lowercase tags. +- Use `+kubebuilder:` markers for validation, defaults, printer columns. +- Singleton enforcement uses CEL: `self.metadata.name == 'cluster'`. +- Mode immutability uses CEL with `oldSelf`. + +**Status conventions:** +- Status is the public interface for component CRs and humans. Treat it as + versioned API surface. +- Keep status minimal — only the inter-CR contract plus conditions. +- Use standard Kubernetes condition types (`Ready`, plus PascalCase + domain-specific ones like `CertificatesReady`). + +**Watches:** +- Reconcilers must watch referenced resources (Secrets, ClusterIssuers, + IngressClasses), not just react to CR generation changes. External + changes — like a deleted TLS secret — must propagate to status within + seconds. +- Use controller-runtime `.Watches()` with a mapping function targeting + resources by name. + +**Helm SDK usage:** +- Target `helm v4` +- Use `helm.sh/helm/v4/pkg/action` for chart operations. +- Don't shell out to the `helm` binary; use the SDK in-process. +- Always verify chart values against the upstream chart's current + `values.yaml`. Don't rely on memory. + +**Readiness checks for cluster services:** +- `Deployment.status.availableReplicas == replicas` is necessary but not + sufficient. +- For cert-manager: also verify the API discovery responds (e.g., + `GET /apis/cert-manager.io/v1` returns 200). +- For Kyverno: similar webhook readiness check. +- For Contour: IngressClass exists and the controller is healthy. + +**Local dev environment:** +- Local kind cluster expects port 5001 for the local Docker registry. +- macOS users may have an `educates resolver` providing `*.educates.test` + resolution to a local IP (typically `10.10.10.1`). +- Use `educates create-cluster --cluster-only` if you want kind without v3 + Educates installed, then test v4 against it. + +**Image relocation:** +- For air-gapped, prefer `helm dt wrap`/`unwrap` or equivalent at build + time, not runtime. +- For online but mirrored registries, use the + `EducatesClusterConfig.spec.imageRegistry.prefix` field. +- Don't replicate `kbld`-style runtime digest resolution in the operator; + pin in published values files instead. + +--- + +## Glossary + +Educates uses domain-specific terms that have precise meanings: + +- **Workshop** — a Kubernetes resource (Workshop CR) defining a workshop's + content, environment requirements, session lifetime, etc. The recipe. +- **Workshop Environment** — a deployed instance of a workshop, ready to + spawn sessions. Created by the training portal from a Workshop. +- **Workshop Session** — an actual user's session, with its own namespace, + resources, and (optionally) vcluster. +- **Training Portal** — a deployed instance of the user-facing UI. Multiple + training portals can exist on one Educates install, each serving + different workshops. +- **Cluster service** — an operational dependency of Educates that lives at + cluster scope (cert-manager, contour, kyverno, external-dns). Distinct + from Educates components. +- **Educates component** — secrets-manager, lookup-service, session-manager. + These three are individually deployable; session-manager depends on + secrets-manager. +- **BYO** — Bring Your Own. Used when the user provides a cluster service + themselves (their own cert-manager, their own ingress controller) and + Educates uses it via External-mode discriminators or full Inline mode. +- **Managed mode** vs **Inline mode** — `EducatesClusterConfig.spec.mode` + values. Managed = operator installs cluster services. Inline = user + asserts what already exists. +- **Operator namespace** — the namespace where the v4 operator runs and + where it expects to find user-provided Secrets (TLS, CA, image-pull + secrets) referenced by name in CRs. + +--- + +## When in doubt + +- If a question is architectural and there's no docs-of-record for it, + start a conversation in Claude Desktop and update the docs after. +- If a question is about how to implement something concrete, ask in this + Claude Code session. +- If unsure which it is, default to asking. Asking is cheap. diff --git a/Makefile b/Makefile index bce628e97..4904ea41d 100644 --- a/Makefile +++ b/Makefile @@ -1,134 +1,42 @@ # ============================================================================= -# Educates Training Platform - Build System +# Educates Training Platform — build system # ============================================================================= # -# This Makefile provides a comprehensive build system for the Educates training -# platform, supporting both single-platform and multi-architecture builds. +# Plain `make` produces a complete locally-built system: the educates CLI +# (with compiled-in defaults pointing at the local registry), all core +# platform images and the operator image, pushed to localhost:5001. Then: # -# ============================================================================= -# CONFIGURATION PARAMETERS -# ============================================================================= -# -# The following parameters can be set via environment variables or make arguments: -# -# PUSH_IMAGES -# Description: Controls whether images are pushed to registry or loaded locally -# Note: If PUSH_IMAGES is false, the images are loaded locally with --load -# and only one image is built for the current platform. -# Default: true (images are pushed to a registry) -# Values: true/false -# Examples: -# - Load locally: PUSH_IMAGES=false -# - Push to registry: PUSH_IMAGES=true (or omit) -# Usage: -# make build-all-images PUSH_IMAGES=false -# export PUSH_IMAGES=false && make build-all-images -# -# TARGET_PLATFORMS -# Description: Controls target platform(s) for Docker builds -# Default: Current platform (e.g., linux/amd64 on x86_64 systems) -# Note: If PUSH_IMAGES is false, TARGET_PLATFORMS is ignored. -# Examples: -# - Single platform: TARGET_PLATFORMS=linux/arm64 -# - Multi-platform: TARGET_PLATFORMS=linux/amd64,linux/arm64 -# Usage: -# make build-all-images TARGET_PLATFORMS=linux/arm64,linux/amd64 -# export TARGET_PLATFORMS=linux/arm64 && make build-all-images -# -# IMAGE_REPOSITORY -# Description: Docker registry/repository for built images -# Default: localhost:5001 -# Examples: -# - Local registry: localhost:5001 -# - Docker Hub: yourusername/educates -# - Private registry: registry.company.com/educates -# -# PACKAGE_VERSION -# Description: Version tag for built images -# Default: latest -# Examples: v1.0.0, dev, latest -# -# ============================================================================= -# BUILD TARGETS -# ============================================================================= -# -# Main Targets: -# all - Build all images and client programs -# build-all-images - Build all Docker images -# build-core-images - Build core platform images only -# build-client-programs - Build Go client programs -# -# Individual Image Targets: -# build-session-manager - Session management service -# build-training-portal - Web portal interface -# build-base-environment - Base workshop environment -# build-jdk8-environment - Java 8 workshop environment -# build-jdk11-environment - Java 11 workshop environment -# build-jdk17-environment - Java 17 workshop environment -# build-jdk21-environment - Java 21 workshop environment -# build-conda-environment - Python/Conda workshop environment -# build-desktop-environment- Desktop GUI workshop environment -# build-docker-registry - Local Docker registry -# build-pause-container - Kubernetes pause container -# build-secrets-manager - Secrets management service -# build-tunnel-manager - Network tunneling service -# build-image-cache - Image caching service -# build-assets-server - Static assets server -# build-lookup-service - Service discovery +# client-programs/bin/educates- local cluster create # -# Utility Targets: -# setup-buildx - Setup Docker buildx for multiarch builds -# clean-buildx - Clean up builder -# list-platforms - Show supported platforms -# help - Show available targets -# -# ============================================================================= -# USAGE EXAMPLES -# ============================================================================= -# -# Basic usage (builds for current platform, loads locally): -# make build-all-images -# -# Build for specific platform: -# make build-all-images TARGET_PLATFORMS=linux/arm64 -# -# Multi-architecture build: -# make build-all-images TARGET_PLATFORMS=linux/amd64,linux/arm64 -# -# Don't push to registry: -# make build-all-images PUSH_IMAGES=false -# -# Combined parameters: -# make build-all-images TARGET_PLATFORMS=linux/amd64,linux/arm64 PUSH_IMAGES=true -# -# Using environment variables: -# export TARGET_PLATFORMS=linux/arm64,linux/amd64 -# export PUSH_IMAGES=true -# make build-all-images -# -# Build specific service: -# make build-training-portal TARGET_PLATFORMS=linux/arm64 -# -# ============================================================================= -# PLATFORM DETECTION -# ============================================================================= +# deploys the locally built system with no further configuration. # -# The Makefile automatically detects the current system: -# - Operating System: Darwin, Linux, Windows -# - Architecture: amd64, arm64, etc. -# - Normalizes x86_64 to amd64 for consistency +# Knobs (env vars or `make VAR=value`): +# IMAGE_REPOSITORY registry for images (default localhost:5001) +# PACKAGE_VERSION image tag (default latest) +# TARGET_PLATFORMS image platforms; DEFAULTS TO THE CURRENT HOST +# ARCHITECTURE ONLY. Multi-arch is explicit opt-in: +# TARGET_PLATFORMS=linux/amd64,linux/arm64 +# PUSH_IMAGES false = load into the Docker daemon instead of +# pushing (single platform only; default true) +# CLI_VERSION / CLI_IMAGE_REPOSITORY +# compiled-in CLI defaults (default: PACKAGE_VERSION / +# IMAGE_REPOSITORY). A non-semver CLI_VERSION marks the +# binary as a dev build, which auto-targets its +# registry for all platform images at deploy time. # -# The target for build-client-programs is always set to the current platform, so that -# on macos a binary will be built for the current platform. But the push-client-programs -# target will create a multiarch image for the target platforms and the corresponding binaries, -# in the form of "educates-cli" image, and will also generate an "educates-client-programs" oci artifact -# with all the binaries for the target platforms. (Pushed via imgpkg) +# `make` regenerates committed embedded artifacts (operator CRDs/subchart +# tarballs, CLI-embedded chart and schemas) when their sources changed — +# a dirty tree after `make` means those need committing. # +# Prerequisites beyond docker + go: helm (subchart packaging). +# Run `make help` for the target list. # ============================================================================= -# -IMAGE_REPOSITORY = localhost:5001 -PACKAGE_VERSION = latest -RELEASE_VERSION = 0.0.1 + +IMAGE_REPOSITORY ?= localhost:5001 +PACKAGE_VERSION ?= latest + +CLI_VERSION ?= $(PACKAGE_VERSION) +CLI_IMAGE_REPOSITORY ?= $(IMAGE_REPOSITORY) UNAME_SYSTEM := $(shell uname -s | tr '[:upper:]' '[:lower:]') UNAME_MACHINE := $(shell uname -m) @@ -143,243 +51,230 @@ endif TARGET_PLATFORM = $(TARGET_SYSTEM)-$(TARGET_MACHINE) BUILDX_BUILDER = educates-multiarch-builder -# Platform configuration - can be overridden by TARGET_PLATFORMS env var or make parameter +# Image platforms: current host architecture only, unless TARGET_PLATFORMS +# is set explicitly. Never silently multi-arch — cross-arch builds run +# under QEMU emulation and belong in CI or an explicit opt-in. ifeq ($(TARGET_PLATFORMS),) -# Default to current platform when TARGET_PLATFORMS is not set -DOCKER_PLATFORM = linux/$(TARGET_MACHINE) -MULTIARCH_PLATFORMS = linux/amd64,linux/arm64 +IMAGE_PLATFORMS = linux/$(TARGET_MACHINE) else -# Use TARGET_PLATFORMS when set (allows for custom multiarch builds) -DOCKER_PLATFORM = $(TARGET_PLATFORMS) -MULTIARCH_PLATFORMS = $(TARGET_PLATFORMS) +IMAGE_PLATFORMS = $(TARGET_PLATFORMS) endif -# Push/Load configuration - can be overridden by PUSH_IMAGES env var or make parameter +# PUSH_IMAGES=false loads the image into the Docker daemon (`--load` +# semantics, single platform only) instead of pushing to the registry. ifeq ($(PUSH_IMAGES),false) -# Load images locally when PUSH_IMAGES is not true (default) DOCKER_BUILDER = -MULTIARCH_PLATFORMS = $(DOCKER_PLATFORM) +IMAGE_PLATFORMS = linux/$(TARGET_MACHINE) else -# Push images to registry when PUSH_IMAGES is true DOCKER_BUILDER = --builder ${BUILDX_BUILDER} --push endif -all: build-all-images # deploy-installer deploy-workshop - -# Multiarch build targets -build-all-images: setup-buildx build-session-manager build-training-portal \ - build-base-environment build-jdk8-environment build-jdk11-environment \ - build-jdk17-environment build-jdk21-environment \ - build-conda-environment build-docker-registry \ - build-pause-container build-secrets-manager build-tunnel-manager \ - build-image-cache build-assets-server build-lookup-service \ - build-node-ca-injector build-cli-image - -build-core-images: setup-buildx build-session-manager build-training-portal \ - build-base-environment build-docker-registry build-pause-container \ - build-secrets-manager build-tunnel-manager build-image-cache \ - build-assets-server build-lookup-service build-node-ca-injector - -build-session-manager: - docker build --progress plain --platform $(MULTIARCH_PLATFORMS) \ - $(DOCKER_BUILDER) \ - -t $(IMAGE_REPOSITORY)/educates-session-manager:$(PACKAGE_VERSION) \ - session-manager - -build-training-portal: - docker build --progress plain --platform $(MULTIARCH_PLATFORMS) \ - $(DOCKER_BUILDER) \ - -t $(IMAGE_REPOSITORY)/educates-training-portal:$(PACKAGE_VERSION) \ - training-portal - -build-base-environment: - docker build --progress plain --platform $(MULTIARCH_PLATFORMS) \ - $(DOCKER_BUILDER) \ - -t $(IMAGE_REPOSITORY)/educates-base-environment:$(PACKAGE_VERSION) \ - workshop-images/base-environment - -build-jdk8-environment: build-base-environment - docker build --progress plain --platform $(MULTIARCH_PLATFORMS) \ - --build-arg PACKAGE_VERSION=$(PACKAGE_VERSION) \ - $(DOCKER_BUILDER) \ - -t $(IMAGE_REPOSITORY)/educates-jdk8-environment:$(PACKAGE_VERSION) \ - workshop-images/jdk8-environment - -build-jdk11-environment: build-base-environment - docker build --progress plain --platform $(MULTIARCH_PLATFORMS) \ - $(DOCKER_BUILDER) \ - --build-arg PACKAGE_VERSION=$(PACKAGE_VERSION) \ - -t $(IMAGE_REPOSITORY)/educates-jdk11-environment:$(PACKAGE_VERSION) \ - workshop-images/jdk11-environment - -build-jdk17-environment: build-base-environment - docker build --progress plain --platform $(MULTIARCH_PLATFORMS) \ - $(DOCKER_BUILDER) \ - --build-arg PACKAGE_VERSION=$(PACKAGE_VERSION) \ - -t $(IMAGE_REPOSITORY)/educates-jdk17-environment:$(PACKAGE_VERSION) \ - workshop-images/jdk17-environment - -build-jdk21-environment: build-base-environment - docker build --progress plain --platform $(MULTIARCH_PLATFORMS) \ - $(DOCKER_BUILDER) \ - --build-arg PACKAGE_VERSION=$(PACKAGE_VERSION) \ - -t $(IMAGE_REPOSITORY)/educates-jdk21-environment:$(PACKAGE_VERSION) \ - workshop-images/jdk21-environment - -build-conda-environment: build-base-environment - docker build --progress plain --platform $(MULTIARCH_PLATFORMS) \ - $(DOCKER_BUILDER) \ - --build-arg PACKAGE_VERSION=$(PACKAGE_VERSION) \ - -t $(IMAGE_REPOSITORY)/educates-conda-environment:$(PACKAGE_VERSION) \ - workshop-images/conda-environment - -build-desktop-environment: build-base-environment - docker build --progress plain --platform $(MULTIARCH_PLATFORMS) \ - $(DOCKER_BUILDER) \ - --build-arg PACKAGE_VERSION=$(PACKAGE_VERSION) \ - -t $(IMAGE_REPOSITORY)/educates-desktop-environment:$(PACKAGE_VERSION) \ - workshop-images/desktop-environment - -build-docker-registry: - docker build --progress plain --platform $(MULTIARCH_PLATFORMS) \ - $(DOCKER_BUILDER) \ - -t $(IMAGE_REPOSITORY)/educates-docker-registry:$(PACKAGE_VERSION) \ - docker-registry - -build-pause-container: - docker build --progress plain --platform $(MULTIARCH_PLATFORMS) \ - $(DOCKER_BUILDER) \ - -t $(IMAGE_REPOSITORY)/educates-pause-container:$(PACKAGE_VERSION) \ - pause-container - -build-secrets-manager: - docker build --progress plain --platform $(MULTIARCH_PLATFORMS) \ - $(DOCKER_BUILDER) \ - -t $(IMAGE_REPOSITORY)/educates-secrets-manager:$(PACKAGE_VERSION) \ - secrets-manager - -build-tunnel-manager: - docker build --progress plain --platform $(MULTIARCH_PLATFORMS) \ - $(DOCKER_BUILDER) \ - -t $(IMAGE_REPOSITORY)/educates-tunnel-manager:$(PACKAGE_VERSION) \ - tunnel-manager - -build-image-cache: - docker build --progress plain --platform $(MULTIARCH_PLATFORMS) \ - $(DOCKER_BUILDER) \ - -t $(IMAGE_REPOSITORY)/educates-image-cache:$(PACKAGE_VERSION) \ - image-cache - -build-assets-server: - docker build --progress plain --platform $(MULTIARCH_PLATFORMS) \ - $(DOCKER_BUILDER) \ - -t $(IMAGE_REPOSITORY)/educates-assets-server:$(PACKAGE_VERSION) \ - assets-server - -build-lookup-service: - docker build --progress plain --platform $(MULTIARCH_PLATFORMS) \ - $(DOCKER_BUILDER) \ - -t $(IMAGE_REPOSITORY)/educates-lookup-service:$(PACKAGE_VERSION) \ - lookup-service - -build-node-ca-injector: - docker build --progress plain --platform $(MULTIARCH_PLATFORMS) \ - $(DOCKER_BUILDER) \ - -t $(IMAGE_REPOSITORY)/educates-node-ca-injector:$(PACKAGE_VERSION) \ - node-ca-injector - -verify-installer-config: -ifneq ("$(wildcard developer-testing/educates-installer-values.yaml)","") - @ytt --file carvel-packages/installer/bundle/config --data-values-file developer-testing/educates-installer-values.yaml -else - @echo "No values file found. Please create developer-testing/educates-installer-values.yaml" - exit 1 -endif +# ============================================================================= +# Image inventory +# ============================================================================= -push-installer-bundle: - ytt -f carvel-packages/installer/config/images.yaml -f carvel-packages/installer/config/schema.yaml -v imageRegistry.host=$(IMAGE_REPOSITORY) -v version=$(PACKAGE_VERSION) > carvel-packages/installer/bundle/kbld/kbld-images.yaml - # For local development, we just need to lock educates images. Everything else can be referenced by tag from real origin. - cat carvel-packages/installer/bundle/kbld/kbld-images.yaml | kbld -f - --imgpkg-lock-output carvel-packages/installer/bundle/.imgpkg/images.yml - imgpkg push -b $(IMAGE_REPOSITORY)/educates-installer:$(RELEASE_VERSION) -f carvel-packages/installer/bundle - mkdir -p developer-testing - ytt -f carvel-packages/installer/config/app.yaml -f carvel-packages/installer/config/schema.yaml -v imageRegistry.host=$(IMAGE_REPOSITORY) -v version=$(RELEASE_VERSION) > developer-testing/educates-installer-app.yaml - -deploy-platform: -ifneq ("$(wildcard developer-testing/educates-installer-values.yaml)","") - ytt --file carvel-packages/installer/bundle/config --data-values-file developer-testing/educates-installer-values.yaml | kapp deploy -a label:installer=educates-installer.app -f - -y -else - @echo "No values file found. Please create developer-testing/educates-installer-values.yaml" - exit 1 -endif +CORE_IMAGES = session-manager training-portal base-environment \ + docker-registry pause-container secrets-manager tunnel-manager \ + image-cache assets-server lookup-service node-ca-injector -delete-platform: - kapp delete -a label:installer=educates-installer.app -y +WORKSHOP_IMAGES = jdk8-environment jdk11-environment jdk17-environment \ + jdk21-environment conda-environment -deploy-platform-app: push-installer-bundle -ifeq ("$(wildcard developer-testing/educates-installer-values.yaml)","") - @echo "No values file found. Please create developer-testing/educates-installer-values.yaml" - exit 1 -endif - -kubectl apply -f carvel-packages/installer/config/rbac.yaml - kubectl create secret generic educates-installer --from-file=developer-testing/educates-installer-values.yaml -o yaml --dry-run=client | kubectl apply -n educates-installer -f - - kubectl apply --namespace educates-installer -f developer-testing/educates-installer-app.yaml +# Build context directories for images whose context isn't ./. +IMAGE_DIR.base-environment = workshop-images/base-environment +$(foreach i,$(WORKSHOP_IMAGES),$(eval IMAGE_DIR.$(i) = workshop-images/$(i))) +IMAGE_DIR.desktop-environment = workshop-images/desktop-environment +IMAGE_DIR.operator = installer/operator +IMAGE_DIR.cli = client-programs -delete-platform-app: - kubectl delete --namespace educates-installer -f developer-testing/educates-installer-app.yaml - -kubectl delete secret educates-installer -n educates-installer - -kubectl delete -f carvel-packages/installer/config/rbac.yaml +# Per-image build args. Workshop images chain FROM base-environment at +# IMAGE_REPOSITORY:PACKAGE_VERSION; the CLI image stamps the same +# compiled-in defaults as the binary build below. +WORKSHOP_BUILD_ARGS = --build-arg IMAGE_REPOSITORY=$(IMAGE_REPOSITORY) --build-arg PACKAGE_VERSION=$(PACKAGE_VERSION) +$(foreach i,$(WORKSHOP_IMAGES) desktop-environment,$(eval IMAGE_BUILD_ARGS.$(i) = $(WORKSHOP_BUILD_ARGS))) +IMAGE_BUILD_ARGS.cli = --build-arg REPOSITORY=$(IMAGE_REPOSITORY) --build-arg TAG=$(PACKAGE_VERSION) \ + --build-arg PROJECT_VERSION=$(CLI_VERSION) --build-arg IMAGE_REPOSITORY=$(CLI_IMAGE_REPOSITORY) -restart-training-platform: - kubectl rollout restart deployment/secrets-manager -n educates - kubectl rollout restart deployment/session-manager -n educates +# ============================================================================= +# Verbs +# ============================================================================= -client-programs-educates: - rm -rf client-programs/pkg/renderer/files - mkdir client-programs/pkg/renderer/files +.DEFAULT_GOAL := local-build + +local-build: build-cli ensure-local-registry build-core-images image-operator ## Build CLI + core images + operator for local testing (default) + @echo "" + @echo "Local build complete:" + @echo " images: $(IMAGE_REPOSITORY)/educates-*:$(PACKAGE_VERSION) ($(IMAGE_PLATFORMS))" + @echo " CLI: client-programs/bin/educates-$(TARGET_PLATFORM)" + @echo "" + @echo "Next: client-programs/bin/educates-$(TARGET_PLATFORM) local cluster create" + +all: local-build + +build-core-images: setup-buildx $(addprefix image-,$(CORE_IMAGES)) ## Build + push the core platform images + +build-workshop-images: setup-buildx $(addprefix image-,$(WORKSHOP_IMAGES)) ## Build + push the optional workshop language images (jdk*, conda) + +build-all-images: build-core-images build-workshop-images image-cli ## Build everything: core + workshop images + CLI image + +# Generic image rule: `make image-` builds + pushes one image. +# Context is ./ unless overridden via IMAGE_DIR. above. +image-%: setup-buildx + docker build --progress plain --platform $(IMAGE_PLATFORMS) \ + $(DOCKER_BUILDER) $(IMAGE_BUILD_ARGS.$*) \ + -t $(IMAGE_REPOSITORY)/educates-$*:$(PACKAGE_VERSION) \ + $(or $(IMAGE_DIR.$*),$*) + +# Workshop language images chain FROM the base environment image. +$(addprefix image-,$(WORKSHOP_IMAGES)) image-desktop-environment: image-base-environment + +# The operator image go:embeds the runtime subchart tarballs — refresh +# them (and generated CRDs/deepcopy) before baking the image. +image-operator: refresh-operator-embeds + +# The CLI image embeds the operator chart + schemas via its build +# context and copies themes from the base-environment image. +image-cli: refresh-cli-embeds image-base-environment + +# ============================================================================= +# Embedded-artifact freshness +# ============================================================================= +# These regenerate committed files. A dirty tree afterwards means chart +# or CRD sources changed — commit the regenerated output (CI enforces +# sync via verify-installer-chart / verify-cli-schemas / chart-sync-lint). + +refresh-operator-embeds: ## Regenerate CRDs + deepcopy + the subchart tarballs the operator embeds + $(MAKE) -C installer/operator manifests generate package-local-charts + @# helm package is not byte-reproducible (gzip timestamps); restore + @# any repackaged tarball whose listing + content are unchanged so + @# `make` keeps a clean tree when nothing really changed. + @for f in $$(git diff --name-only -- 'installer/operator/vendored-charts/*.tgz'); do \ + new_sum=$$( (tar -tzf "$$f"; tar -xzOf "$$f") | shasum -a 256 ); \ + old_sum=$$( (git show HEAD:"$$f" | tar -tz; git show HEAD:"$$f" | tar -xzO) 2>/dev/null | shasum -a 256 ); \ + if [ "$$new_sum" = "$$old_sum" ]; then git checkout --quiet -- "$$f"; fi; \ + done + +refresh-cli-embeds: refresh-operator-embeds embed-installer-chart generate-cli-schemas ## Refresh everything the CLI embeds (chart + schemas) + +package-local-charts: ## Repackage the runtime subcharts into the operator's vendored-charts/ + $(MAKE) -C installer/operator package-local-charts + +generate-cli-schemas: + @# Regenerates EducatesConfig.schema.json from the platform CRDs. + @# Run after `make manifests` in installer/operator/ when CRD shapes change. + go run ./client-programs/hack/gen-cli-schemas + +verify-cli-schemas: generate-cli-schemas + @# Fails when the committed EducatesConfig.schema.json differs from + @# freshly generated output. Run by client-programs CI. + @if ! git diff --exit-code -- client-programs/pkg/config/v1alpha1/schemas/EducatesConfig.schema.json; then \ + echo "ERROR: EducatesConfig.schema.json drifted from the CRDs. Run 'make generate-cli-schemas' and commit the result."; \ + exit 1; \ + fi + +embed-installer-chart: + @# Refreshes the CLI-embedded copy of the operator chart from the + @# canonical source. Run whenever installer/charts/educates-installer + @# changes shape — Chart.yaml updates, new templates, new CRDs. + @# The copy is committed (single-source-of-truth via this target); + @# CI runs verify-installer-chart to catch drift. + rm -rf client-programs/pkg/deployer/chart/files + mkdir -p client-programs/pkg/deployer/chart/files + cp -r installer/charts/educates-installer/. client-programs/pkg/deployer/chart/files/ + +verify-installer-chart: embed-installer-chart + @# Fails when the committed embedded chart copy differs from the + @# canonical chart. Run by client-programs CI. + @if ! git diff --exit-code -- client-programs/pkg/deployer/chart/files; then \ + echo "ERROR: embedded operator chart drifted from installer/charts/educates-installer. Run 'make embed-installer-chart' and commit the result."; \ + exit 1; \ + fi + +# ============================================================================= +# CLI binary +# ============================================================================= + +build-cli: refresh-cli-embeds stage-renderer-files ## Build the educates CLI for the current host platform mkdir -p client-programs/bin + (cd client-programs; go build -gcflags=all="-N -l" \ + -ldflags "-X 'main.projectVersion=$(CLI_VERSION)' -X 'main.imageRepository=$(CLI_IMAGE_REPOSITORY)'" \ + -o bin/educates-$(TARGET_PLATFORM) cmd/educates/main.go) + +build-client-programs: build-cli +client-programs-educates: build-cli + +# pkg/renderer/hugo.go embeds pkg/renderer/files/* via //go:embed, but that +# directory is gitignored and populated at build time from the base-environment +# themes. go vet/build/test fail without it ("no matching files found"), so any +# CLI compile or CI-parity run must stage it first. +stage-renderer-files: ## Stage the gitignored CLI theme files the renderer embeds + rm -rf client-programs/pkg/renderer/files + mkdir -p client-programs/pkg/renderer/files cp -rp workshop-images/base-environment/opt/eduk8s/etc/themes client-programs/pkg/renderer/files/ - (cd client-programs; go build -gcflags=all="-N -l" -o bin/educates-$(TARGET_PLATFORM) cmd/educates/main.go) -build-client-programs: client-programs-educates +# ============================================================================= +# CI parity — run the same checks as the GitHub Actions workflows locally. +# Drift checks regenerate in place and fail on any diff, so a failure may +# leave generated files modified in the working tree (same as CI flags). +# ============================================================================= -push-client-programs: build-client-programs - (cd client-programs; GOOS=linux GOARCH=amd64 go build -o bin/educates-linux-amd64 cmd/educates/main.go) - (cd client-programs; GOOS=linux GOARCH=arm64 go build -o bin/educates-linux-arm64 cmd/educates/main.go) - (cd client-programs; GOOS=linux GOARCH=amd64 go build -o bin/educates-linux-amd64 cmd/educates/main.go) - (cd client-programs; GOOS=linux GOARCH=arm64 go build -o bin/educates-linux-arm64 cmd/educates/main.go) - imgpkg push -i $(IMAGE_REPOSITORY)/educates-client-programs:$(PACKAGE_VERSION) -f client-programs/bin +ci: ci-cli ci-operator ## Run all CI checks locally (CLI + operator) + +ci-cli: stage-renderer-files ## CI parity for the CLI (client-programs-ci.yaml) + cd client-programs && go vet ./... + cd client-programs && go build ./... + cd client-programs && go test ./... + $(MAKE) verify-installer-chart + $(MAKE) verify-cli-schemas + +ci-operator: ## CI parity for the operator (installer-operator-ci.yaml) + ./hack/lint-chart-versions.sh + cd installer/operator && go vet ./... + cd installer/operator && go build ./... + $(MAKE) -C installer/operator manifests + @git diff --exit-code -- installer/charts/educates-installer/crds installer/charts/educates-installer/templates/rbac \ + || { echo "ERROR: generated CRDs/RBAC drifted. Run 'make -C installer/operator manifests' and commit."; exit 1; } + $(MAKE) -C installer/operator generate + @git diff --exit-code -- installer/operator/api \ + || { echo "ERROR: generated DeepCopy drifted. Run 'make -C installer/operator generate' and commit."; exit 1; } + $(MAKE) -C installer/operator test + $(MAKE) -C installer/operator lint + +# The always-on localhost:5001 registry must exist before images can be +# pushed to it. The freshly built CLI deploys it (idempotent, no cluster +# needed). Skipped when not pushing or when targeting another registry. +ensure-local-registry: build-cli +ifeq ($(PUSH_IMAGES),false) + @echo "PUSH_IMAGES=false: images load into the Docker daemon; skipping local registry" +else ifneq ($(IMAGE_REPOSITORY),localhost:5001) + @echo "IMAGE_REPOSITORY=$(IMAGE_REPOSITORY): assuming the registry is reachable" +else + @docker container inspect -f '{{.State.Running}}' educates-registry 2>/dev/null | grep -q true || \ + client-programs/bin/educates-$(TARGET_PLATFORM) local registry deploy +endif -build-cli-image: - docker build --progress plain --platform $(MULTIARCH_PLATFORMS) \ - $(DOCKER_BUILDER) \ - -t $(IMAGE_REPOSITORY)/educates-cli:$(PACKAGE_VERSION) \ - client-programs +# ============================================================================= +# Docker Desktop extension +# ============================================================================= -build-docker-extension : build-cli-image +build-docker-extension: image-cli ## Build the Docker Desktop extension $(MAKE) -C docker-extension build-extension REPOSITORY=$(IMAGE_REPOSITORY) TAG=$(PACKAGE_VERSION) -install-docker-extension : build-docker-extension +install-docker-extension: build-docker-extension $(MAKE) -C docker-extension install-extension REPOSITORY=$(IMAGE_REPOSITORY) TAG=$(PACKAGE_VERSION) -update-docker-extension : build-docker-extension +update-docker-extension: build-docker-extension $(MAKE) -C docker-extension update-extension REPOSITORY=$(IMAGE_REPOSITORY) TAG=$(PACKAGE_VERSION) -project-docs/venv : - python3 -m venv project-docs/venv - project-docs/venv/bin/pip install -r project-docs/requirements.txt - -build-project-docs : project-docs/venv - source project-docs/venv/bin/activate && make -C project-docs html - -open-project-docs : - open project-docs/_build/html/index.html || \ - xdg-open project-docs/_build/html/index.html +# ============================================================================= +# Cluster conveniences +# ============================================================================= -clean-project-docs: - rm -rf project-docs/venv - rm -rf project-docs/_build +restart-training-platform: ## Restart the deployed platform components + kubectl rollout restart deployment/secrets-manager -n educates + kubectl rollout restart deployment/session-manager -n educates -deploy-workshop: +deploy-workshop: ## Deploy the lab-k8s-fundamentals sample workshop kubectl apply -f https://github.com/educates/lab-k8s-fundamentals/releases/download/8.4/workshop.yaml kubectl apply -f https://github.com/educates/lab-k8s-fundamentals/releases/download/8.4/trainingportal.yaml STATUS=1; ATTEMPTS=0; ROLLOUT_STATUS_CMD="kubectl rollout status deployment/training-portal -n lab-k8s-fundamentals-ui"; until [ $$STATUS -eq 0 ] || $$ROLLOUT_STATUS_CMD || [ $$ATTEMPTS -eq 5 ]; do sleep 5; $$ROLLOUT_STATUS_CMD; STATUS=$$?; ATTEMPTS=$$((ATTEMPTS + 1)); done @@ -390,6 +285,29 @@ delete-workshop: open-workshop: URL=`kubectl get trainingportal/lab-k8s-fundamentals -o go-template={{.status.educates.url}}`; (test -x /usr/bin/xdg-open && xdg-open $$URL) || (test -x /usr/bin/open && open $$URL) || true +# ============================================================================= +# Documentation +# ============================================================================= + +project-docs/venv: + python3 -m venv project-docs/venv + project-docs/venv/bin/pip install -r project-docs/requirements.txt + +build-project-docs: project-docs/venv ## Build the Sphinx documentation + source project-docs/venv/bin/activate && make -C project-docs html + +open-project-docs: + open project-docs/_build/html/index.html || \ + xdg-open project-docs/_build/html/index.html + +clean-project-docs: + rm -rf project-docs/venv + rm -rf project-docs/_build + +# ============================================================================= +# Housekeeping +# ============================================================================= + prune-images: docker image prune --force @@ -412,16 +330,32 @@ prune-builds: prune-registry: docker exec educates-registry registry garbage-collect /etc/distribution/config.yml --delete-untagged=true -prune-all: prune-docker prune-builds prune-registry +prune-all: prune-docker prune-builds prune-registry ## Clean caches and build artifacts -# builder management -setup-buildx: ## Setup builder for multiarch builds +setup-buildx: ## Set up the buildx builder used for image pushes docker buildx create --name $(BUILDX_BUILDER) --driver docker-container --driver-opt default-load=true --driver-opt network=host --use || true docker buildx inspect $(BUILDX_BUILDER) --bootstrap -clean-buildx: ## Clean up builder +clean-buildx: ## Remove the buildx builder docker buildx rm $(BUILDX_BUILDER) || true -# Multiarch utility targets -list-platforms: ## List available platforms for multiarch builds - @echo "Supported platforms: $(MULTIARCH_PLATFORMS)" \ No newline at end of file +list-platforms: + @echo "Image platforms: $(IMAGE_PLATFORMS)" + +help: ## Show available targets + @echo "Common targets (see the header comment for the knobs):" + @grep -hE '^[a-zA-Z0-9_.%-]+:.*## ' $(MAKEFILE_LIST) | awk 'BEGIN {FS = ":.*## "}; {printf " \033[36m%-26s\033[0m %s\n", $$1, $$2}' + @echo "" + @echo "Any single image: make image- (e.g. image-training-portal)" + @echo " names: $(CORE_IMAGES) $(WORKSHOP_IMAGES) desktop-environment operator cli" + +.PHONY: local-build all build-core-images build-workshop-images build-all-images \ + refresh-operator-embeds refresh-cli-embeds package-local-charts \ + generate-cli-schemas verify-cli-schemas embed-installer-chart verify-installer-chart \ + build-cli build-client-programs client-programs-educates ensure-local-registry \ + stage-renderer-files ci ci-cli ci-operator \ + build-docker-extension install-docker-extension update-docker-extension \ + restart-training-platform deploy-workshop delete-workshop open-workshop \ + build-project-docs open-project-docs clean-project-docs \ + prune-images prune-docker prune-builds prune-registry prune-all \ + setup-buildx clean-buildx list-platforms help diff --git a/assets-server/Dockerfile b/assets-server/Dockerfile index c794e5d1f..91076823d 100644 --- a/assets-server/Dockerfile +++ b/assets-server/Dockerfile @@ -1,4 +1,4 @@ -FROM --platform=$BUILDPLATFORM golang:1.24.10 AS builder +FROM --platform=$BUILDPLATFORM golang:1.26 AS builder WORKDIR /src diff --git a/assets-server/go.mod b/assets-server/go.mod index ba1b0c6ca..6209e6869 100644 --- a/assets-server/go.mod +++ b/assets-server/go.mod @@ -1,9 +1,10 @@ module github.com/educates/educates-training-platform/assets-server -go 1.20 +go 1.26.0 + +require github.com/spf13/cobra v1.7.0 require ( github.com/inconshreveable/mousetrap v1.1.0 // indirect - github.com/spf13/cobra v1.7.0 // indirect github.com/spf13/pflag v1.0.5 // indirect ) diff --git a/carvel-packages/installer/bundle/config/kapp/kapp-config-apiservices.yaml b/carvel-packages/installer/bundle/config/kapp/kapp-config-apiservices.yaml deleted file mode 100644 index 81d63d22a..000000000 --- a/carvel-packages/installer/bundle/config/kapp/kapp-config-apiservices.yaml +++ /dev/null @@ -1,16 +0,0 @@ -apiVersion: kapp.k14s.io/v1alpha1 -kind: Config -rebaseRules: - - paths: - - [spec, caBundle] - - [spec, group] - - [spec, groupPriorityMinimum] - - [spec, service, name] - - [spec, service, namespace] - - [spec, service, port] - - [spec, version] - - [spec, versionPriority] - type: copy - sources: [existing, new] - resourceMatchers: - - apiVersionKindMatcher: { apiVersion: apiregistration.k8s.io/v1, kind: APIService } diff --git a/carvel-packages/installer/bundle/config/kapp/kapp-config-clusterpolicy.yaml b/carvel-packages/installer/bundle/config/kapp/kapp-config-clusterpolicy.yaml deleted file mode 100644 index 306e1ac63..000000000 --- a/carvel-packages/installer/bundle/config/kapp/kapp-config-clusterpolicy.yaml +++ /dev/null @@ -1,10 +0,0 @@ -apiVersion: kapp.k14s.io/v1alpha1 -kind: Config -rebaseRules: - - paths: - - [spec, admission] - - [spec, rules, { allIndexes: true }, skipBackgroundRequests] - type: copy - sources: [existing, new] - resourceMatchers: - - apiVersionKindMatcher: { apiVersion: kyverno.io/v1, kind: ClusterPolicy } diff --git a/carvel-packages/installer/bundle/config/kapp/kapp-config-crds.yaml b/carvel-packages/installer/bundle/config/kapp/kapp-config-crds.yaml deleted file mode 100644 index c5a3d39c1..000000000 --- a/carvel-packages/installer/bundle/config/kapp/kapp-config-crds.yaml +++ /dev/null @@ -1,55 +0,0 @@ -apiVersion: kapp.k14s.io/v1alpha1 -kind: Config -rebaseRules: - - path: [spec, conversion, strategy] - type: copy - sources: [existing, new] - resourceMatchers: - - apiVersionKindMatcher: - { apiVersion: apiextensions.k8s.io/v1, kind: CustomResourceDefinition } - - path: [spec, preserveUnknownFields] - type: remove - resourceMatchers: - - apiVersionKindMatcher: - { apiVersion: apiextensions.k8s.io/v1, kind: CustomResourceDefinition } - #! The rule below is like removing it - - path: [spec, preserveUnknownFields] - type: copy - sources: [existing] - resourceMatchers: - - apiVersionKindMatcher: - { apiVersion: apiextensions.k8s.io/v1, kind: CustomResourceDefinition } - - paths: - - [ - spec, - versions, - { allIndexes: true }, - additionalPrinterColumns, - { allIndexes: true }, - priority, - ] - type: remove - resourceMatchers: - - apiVersionKindMatcher: - { apiVersion: apiextensions.k8s.io/v1, kind: CustomResourceDefinition } - #! The rule below is like removing it - - paths: - - [ - spec, - versions, - { allIndexes: true }, - additionalPrinterColumns, - { allIndexes: true }, - priority, - ] - type: copy - sources: [existing] - resourceMatchers: - - apiVersionKindMatcher: - { apiVersion: apiextensions.k8s.io/v1, kind: CustomResourceDefinition } - - path: [spec, names, listKind] - type: copy - sources: [existing, new] - resourceMatchers: - - apiVersionKindMatcher: - { apiVersion: apiextensions.k8s.io/v1, kind: CustomResourceDefinition } diff --git a/carvel-packages/installer/bundle/config/kapp/kapp-config-daemonset.yaml b/carvel-packages/installer/bundle/config/kapp/kapp-config-daemonset.yaml deleted file mode 100644 index 077824e63..000000000 --- a/carvel-packages/installer/bundle/config/kapp/kapp-config-daemonset.yaml +++ /dev/null @@ -1,37 +0,0 @@ -apiVersion: kapp.k14s.io/v1alpha1 -kind: Config -rebaseRules: - - paths: - - [spec, selector, matchLabels, "kapp.k14s.io/app"] - type: copy - sources: [existing, new] - resourceMatchers: - - apiVersionKindMatcher: { apiVersion: apps/v1, kind: DaemonSet } - - paths: - - [metadata, annotations, "deprecated.daemonset.template.generation"] - - [spec, revisionHistoryLimit] - - [spec, updateStrategy] - - [spec, template, metadata, creationTimestamp] - - [spec, template, spec, containers, { allIndexes: true }, livenessProbe] - - [spec, template, spec, containers, { allIndexes: true }, readinessProbe] - - [spec, template, spec, containers, { allIndexes: true }, startupProbe] - - [spec, template, spec, containers, { allIndexes: true }, resources] - - [spec, template, spec, containers, { allIndexes: true }, env] - - [spec, template, spec, containers, { allIndexes: true }, terminationMessagePath] - - [spec, template, spec, containers, { allIndexes: true }, terminationMessagePolicy] - - [spec, template, spec, containers, { allIndexes: true }, securityContext] - - [spec, template, spec, securityContext] - - [spec, template, spec, dnsPolicy] - - [spec, template, spec, initContainers, { allIndexes: true }, resources] - - [spec, template, spec, initContainers, { allIndexes: true }, env] - - [spec, template, spec, initContainers, { allIndexes: true }, terminationMessagePath] - - [spec, template, spec, initContainers, { allIndexes: true }, terminationMessagePolicy] - - [spec, template, spec, restartPolicy] - - [spec, template, spec, schedulerName] - - [spec, template, spec, serviceAccount] - - [spec, template, spec, terminationGracePeriodSeconds] - - [spec, template, spec, volumes, { allIndexes: true }, secret, defaultMode] - type: copy - sources: [existing, new] - resourceMatchers: - - apiVersionKindMatcher: { apiVersion: apps/v1, kind: DaemonSet } diff --git a/carvel-packages/installer/bundle/config/kapp/kapp-config-deployment.yaml b/carvel-packages/installer/bundle/config/kapp/kapp-config-deployment.yaml deleted file mode 100644 index 8f8b8a328..000000000 --- a/carvel-packages/installer/bundle/config/kapp/kapp-config-deployment.yaml +++ /dev/null @@ -1,42 +0,0 @@ -apiVersion: kapp.k14s.io/v1alpha1 -kind: Config -rebaseRules: - - paths: - - [spec, selector, matchLabels, "kapp.k14s.io/app"] - type: copy - sources: [existing, new] - resourceMatchers: - - apiVersionKindMatcher: { apiVersion: apps/v1, kind: Deployment } - - paths: - - [spec, replicas] - - [spec, strategy] - - [spec, progressDeadlineSeconds] - - [spec, revisionHistoryLimit] - - [spec, template, metadata, creationTimestamp] - - [spec, template, spec, containers, { allIndexes: true }, livenessProbe] - - [spec, template, spec, containers, { allIndexes: true }, readinessProbe] - - [spec, template, spec, containers, { allIndexes: true }, startupProbe] - - [spec, template, spec, containers, { allIndexes: true }, env] - - [spec, template, spec, containers, { allIndexes: true }, imagePullPolicy] - - [spec, template, spec, containers, { allIndexes: true }, resources] - - [spec, template, spec, containers, { allIndexes: true }, securityContext] - - [spec, template, spec, containers, { allIndexes: true }, terminationMessagePath] - - [spec, template, spec, containers, { allIndexes: true }, terminationMessagePolicy] - - [spec, template, spec, initContainers, { allIndexes: true }, env] - - [spec, template, spec, initContainers, { allIndexes: true }, imagePullPolicy] - - [spec, template, spec, initContainers, { allIndexes: true }, resources] - - [spec, template, spec, initContainers, { allIndexes: true }, securityContext] - - [spec, template, spec, initContainers, { allIndexes: true }, terminationMessagePath] - - [spec, template, spec, initContainers, { allIndexes: true }, terminationMessagePolicy] - - [spec, template, spec, securityContext] - - [spec, template, spec, dnsPolicy] - - [spec, template, spec, restartPolicy] - - [spec, template, spec, schedulerName] - - [spec, template, spec, serviceAccount] - - [spec, template, spec, serviceAccountName] - - [spec, template, spec, terminationGracePeriodSeconds] - - [spec, template, spec, volumes, { allIndexes: true }, secret, defaultMode] - type: copy - sources: [existing, new] - resourceMatchers: - - apiVersionKindMatcher: { apiVersion: apps/v1, kind: Deployment } diff --git a/carvel-packages/installer/bundle/config/kapp/kapp-config-educates.yaml b/carvel-packages/installer/bundle/config/kapp/kapp-config-educates.yaml deleted file mode 100644 index 38f8ef6a6..000000000 --- a/carvel-packages/installer/bundle/config/kapp/kapp-config-educates.yaml +++ /dev/null @@ -1,20 +0,0 @@ -apiVersion: kapp.k14s.io/v1alpha1 -kind: Config -rebaseRules: - - paths: - - [metadata, annotations, "kopf.zalando.org/last-handled-configuration"] - - [spec, rules, { allIndexes: true }, reclaimPolicy] - type: copy - sources: [existing, new] - resourceMatchers: - - apiVersionKindMatcher: { apiVersion: secrets.educates.dev/v1beta1, kind: SecretCopier } - - apiVersionKindMatcher: { apiVersion: secrets.educates.dev/v1beta1, kind: SecretInjector } - - paths: - - [data] - - [metadata, annotations, "kubernetes.io/service-account.uid"] - - [metadata, labels, "kubernetes.io/legacy-token-last-used"] - type: copy - sources: [existing, new] - resourceMatchers: - - kindNamespaceNameMatcher: { kind: Secret, name: secrets-manager-token, namespace: educates } - - kindNamespaceNameMatcher: { kind: Secret, name: session-manager-token, namespace: educates } \ No newline at end of file diff --git a/carvel-packages/installer/bundle/config/kapp/kapp-config-installer-labels.yaml b/carvel-packages/installer/bundle/config/kapp/kapp-config-installer-labels.yaml deleted file mode 100644 index f7d5d5139..000000000 --- a/carvel-packages/installer/bundle/config/kapp/kapp-config-installer-labels.yaml +++ /dev/null @@ -1,17 +0,0 @@ -apiVersion: kapp.k14s.io/v1alpha1 -kind: Config -rebaseRules: - - paths: - - [spec, selector, matchLabels] - type: copy - sources: [existing, new] - resourceMatchers: - - apiVersionKindMatcher: { apiVersion: apps/v1, kind: DaemonSet } - - apiVersionKindMatcher: { apiVersion: apps/v1, kind: Deployment } - - paths: - - [spec, selector] - type: copy - sources: [existing, new] - resourceMatchers: - - apiVersionKindMatcher: { apiVersion: v1, kind: Service } - - apiVersionKindMatcher: { apiVersion: apps/v1, kind: Deployment } diff --git a/carvel-packages/installer/bundle/config/kapp/kapp-config-jobs.yaml b/carvel-packages/installer/bundle/config/kapp/kapp-config-jobs.yaml deleted file mode 100644 index 4e7cf5d3f..000000000 --- a/carvel-packages/installer/bundle/config/kapp/kapp-config-jobs.yaml +++ /dev/null @@ -1,86 +0,0 @@ -apiVersion: kapp.k14s.io/v1alpha1 -kind: Config -rebaseRules: - - paths: - - [spec, jobTemplate, metadata, creationTimestamp] - - [spec, jobTemplate, spec, template, metadata, creationTimestamp] - - [spec, jobTemplate, spec, template, spec, containers, { allIndexes: true }, imagePullPolicy] - - [spec, jobTemplate, spec, template, spec, containers, { allIndexes: true }, resources] - - [ - spec, - jobTemplate, - spec, - template, - spec, - containers, - { allIndexes: true }, - terminationMessagePath, - ] - - [ - spec, - jobTemplate, - spec, - template, - spec, - containers, - { allIndexes: true }, - terminationMessagePolicy, - ] - - [spec, jobTemplate, spec, template, spec, securityContext] - - [spec, jobTemplate, spec, template, spec, dnsPolicy] - - [spec, jobTemplate, spec, template, spec, restartPolicy] - - [spec, jobTemplate, spec, template, spec, schedulerName] - - [spec, jobTemplate, spec, template, spec, serviceAccount] - - [spec, jobTemplate, spec, template, spec, terminationGracePeriodSeconds] - - [spec, scchedule] - - [spec, successfulJobsHistoryLimit] - - [spec, suspend] - type: copy - sources: [existing, new] - resourceMatchers: - - apiVersionKindMatcher: { apiVersion: batch/v1, kind: CronJob } - - paths: - - [spec, backoffLimit] - - [spec, completionMode] - - [spec, completions] - - [spec, manualSelector] - - [spec, parallelism] - - [spec, podReplacementPolicy] - - [spec, selector] - - [spec, suspend] - - [spec, template, metadata, creationTimestamp] - - [spec, template, metadata, labels, "batch.kubernetes.io/controller-uid"] - - [spec, template, metadata, labels, "batch.kubernetes.io/job-name"] - - [spec, template, metadata, labels, "controller-uid"] - - [spec, template, metadata, labels, "job-name"] - - [spec, template, spec, containers, { allIndexes: true }, imagePullPolicy] - - [spec, template, spec, containers, { allIndexes: true }, resources] - - [ - spec, - template, - spec, - containers, - { allIndexes: true }, - terminationMessagePath, - ] - - [ - spec, - template, - spec, - containers, - { allIndexes: true }, - terminationMessagePolicy, - ] - - [spec, template, spec, securityContext] - - [spec, template, spec, dnsPolicy] - - [spec, template, spec, restartPolicy] - - [spec, template, spec, schedulerName] - - [spec, template, spec, serviceAccount] - - [spec, template, spec, terminationGracePeriodSeconds] - - [spec, scchedule] - - [spec, successfulJobsHistoryLimit] - - [spec, suspend] - type: copy - sources: [existing, new] - resourceMatchers: - - apiVersionKindMatcher: { apiVersion: batch/v1, kind: Job } diff --git a/carvel-packages/installer/bundle/config/kapp/kapp-config-kyverno.yaml b/carvel-packages/installer/bundle/config/kapp/kapp-config-kyverno.yaml deleted file mode 100644 index be0e10bd8..000000000 --- a/carvel-packages/installer/bundle/config/kapp/kapp-config-kyverno.yaml +++ /dev/null @@ -1,10 +0,0 @@ -apiVersion: kapp.k14s.io/v1alpha1 -kind: Config -rebaseRules: - - path: [spec, conversion, strategy] - type: copy - sources: [new, existing] - resourceMatchers: - - kindNamespaceNameMatcher: - { kind: CustomResourceDefinition, name: clusterpolicies.kyverno.io } - - kindNamespaceNameMatcher: { kind: CustomResourceDefinition, name: policies.kyverno.io } diff --git a/carvel-packages/installer/bundle/config/kapp/kapp-config-ns.yaml b/carvel-packages/installer/bundle/config/kapp/kapp-config-ns.yaml deleted file mode 100644 index 6cd2e084f..000000000 --- a/carvel-packages/installer/bundle/config/kapp/kapp-config-ns.yaml +++ /dev/null @@ -1,8 +0,0 @@ -apiVersion: kapp.k14s.io/v1alpha1 -kind: Config -rebaseRules: - - path: [metadata, labels, "kubernetes.io/metadata.name"] - type: copy - sources: [existing, new] - resourceMatchers: - - apiVersionKindMatcher: { apiVersion: v1, kind: Namespace } diff --git a/carvel-packages/installer/bundle/config/kapp/kapp-config-secrets.yaml b/carvel-packages/installer/bundle/config/kapp/kapp-config-secrets.yaml deleted file mode 100644 index 2d4113be7..000000000 --- a/carvel-packages/installer/bundle/config/kapp/kapp-config-secrets.yaml +++ /dev/null @@ -1,23 +0,0 @@ -apiVersion: kapp.k14s.io/v1alpha1 -kind: Config -rebaseRules: - - paths: - - [type] - type: copy - sources: [existing, new] - resourceMatchers: - - apiVersionKindMatcher: { apiVersion: v1, kind: Secret } - # - paths: - # - [data] - # - [metadata,annotations,"kubernetes.io/service-account.uid"] - # - [metadata,annotations,"kubernetes.io/service-account.name"] - # - [type] - # type: copy - # sources: [existing, new] - # resourceMatchers: - # - andMatcher: - # matchers: - # - apiVersionKindMatcher: { apiVersion: v1, kind: Secret } - # - hasAnnotationMatcher: - # keys: - # - "kubernetes.io/service-account.name" \ No newline at end of file diff --git a/carvel-packages/installer/bundle/config/kapp/kapp-config-services.yaml b/carvel-packages/installer/bundle/config/kapp/kapp-config-services.yaml deleted file mode 100644 index d1815f992..000000000 --- a/carvel-packages/installer/bundle/config/kapp/kapp-config-services.yaml +++ /dev/null @@ -1,22 +0,0 @@ -apiVersion: kapp.k14s.io/v1alpha1 -kind: Config -rebaseRules: - - paths: - - [spec, selector, "kapp.k14s.io/app"] - type: copy - sources: [existing, new] - resourceMatchers: - - apiVersionKindMatcher: { apiVersion: v1, kind: Service } - - paths: - - [spec, type] - - [spec, clusterIPs] - - [spec, internalTrafficPolicy] - - [spec, ipFamilies] - - [spec, ipFamilyPolicy] - - [spec, sessionAffinity] - - [spec, allocateLoadBalancerNodePorts] - - [spec, ports] - type: copy - sources: [existing, new] - resourceMatchers: - - apiVersionKindMatcher: { apiVersion: v1, kind: Service } diff --git a/carvel-packages/installer/bundle/config/kapp/kapp-config-webhooks.yaml b/carvel-packages/installer/bundle/config/kapp/kapp-config-webhooks.yaml deleted file mode 100644 index 94dcaec73..000000000 --- a/carvel-packages/installer/bundle/config/kapp/kapp-config-webhooks.yaml +++ /dev/null @@ -1,16 +0,0 @@ -apiVersion: kapp.k14s.io/v1alpha1 -kind: Config -rebaseRules: - - paths: - - [webhooks, { allIndexes: true }, clientConfig, service] - - [webhooks, { allIndexes: true }, namespaceSelector] - - [webhooks, { allIndexes: true }, objectSelector] - - [webhooks, { allIndexes: true }, reinvocationPolicy] - - [webhooks, { allIndexes: true }, rules] - type: copy - sources: [existing, new] - resourceMatchers: - - apiVersionKindMatcher: - { apiVersion: admissionregistration.k8s.io/v1, kind: ValidatingWebhookConfiguration } - - apiVersionKindMatcher: - { apiVersion: admissionregistration.k8s.io/v1, kind: MutatingWebhookConfiguration } diff --git a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/config/functions.star b/carvel-packages/installer/bundle/config/ytt/_ytt_lib/config/functions.star deleted file mode 100644 index ba82a2e8c..000000000 --- a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/config/functions.star +++ /dev/null @@ -1,17 +0,0 @@ -load("@ytt:struct", "struct") - -def removeNulls(data): - # Iterate over a struct of scalar values and return only those where value is not null - filtered_data = {} - for key in struct.decode(data): - value = getattr(data, key, None) - if type(value) == "struct": - value = removeNulls(value) - end - if value: #! This means that value is not an empty string, dict, struct, ... - filtered_data[key] = value - end - end - return struct.encode(filtered_data) -end - diff --git a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/config/save-config-overlay.yaml b/carvel-packages/installer/bundle/config/ytt/_ytt_lib/config/save-config-overlay.yaml deleted file mode 100644 index f20307d17..000000000 --- a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/config/save-config-overlay.yaml +++ /dev/null @@ -1,22 +0,0 @@ -#@ load("@ytt:overlay", "overlay") -#@ load("@ytt:data", "data") -#@ load("@ytt:yaml", "yaml") -#@ load("functions.star", "removeNulls") - -#! We create educates namespace in case educates package is not enabled -#@ if/end not data.values.values.clusterPackages.educates.enabled: ---- -apiVersion: v1 -kind: Namespace -metadata: - name: educates - ---- -apiVersion: v1 -kind: ConfigMap -metadata: - name: educates-config - namespace: educates -data: - educates-original-config.yaml: #@ yaml.encode(removeNulls(data.values.config)) - educates-processed-values.yaml: #@ yaml.encode(data.values.values) diff --git a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/infrastructure/custom/00-remove-toplevel-values.yaml b/carvel-packages/installer/bundle/config/ytt/_ytt_lib/infrastructure/custom/00-remove-toplevel-values.yaml deleted file mode 100644 index 931e60126..000000000 --- a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/infrastructure/custom/00-remove-toplevel-values.yaml +++ /dev/null @@ -1,50 +0,0 @@ -#@ load("@ytt:data", "data") -#@ load("@ytt:overlay", "overlay") - -#@overlay/remove -debug: - -#@overlay/remove -localKindCluster: -#@overlay/remove -localDNSResolver: - -#@overlay/remove -clusterInfrastructure: - -#@overlay/remove -sessionManager: -#@overlay/remove -imageRegistry: -#@overlay/remove -version: -#@overlay/remove -imageVersions: -#@overlay/remove -clusterRuntime: -#@overlay/remove -clusterIngress: -#@overlay/remove -sessionCookies: -#@overlay/remove -clusterStorage: -#@overlay/remove -clusterSecrets: -#@overlay/remove -clusterSecurity: -#@overlay/remove -workshopSecurity: -#@overlay/remove -trainingPortal: -#@overlay/remove -dockerDaemon: -#@overlay/remove -clusterNetwork: -#@overlay/remove -workshopAnalytics: -#@overlay/remove -websiteStyling: -#@overlay/remove -imagePuller: -#@overlay/remove -lookupService: diff --git a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/infrastructure/custom/10-default-settings-for-provider.yaml b/carvel-packages/installer/bundle/config/ytt/_ytt_lib/infrastructure/custom/10-default-settings-for-provider.yaml deleted file mode 100644 index 221ebf2c1..000000000 --- a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/infrastructure/custom/10-default-settings-for-provider.yaml +++ /dev/null @@ -1,31 +0,0 @@ -#@ load("@ytt:data", "data") -#@ load("@ytt:overlay", "overlay") -#@ load("functions.star", "isClusterPackageEnableByDefault") - -#! This file contains default values for the custom infrastructure provider. -#! These are the values that will be set if not overridden by the user. - -#@overlay/match-child-defaults missing_ok=True -#@overlay/replace -clusterPackages: - contour: - enabled: #@ isClusterPackageEnableByDefault("contour") - settings: {} - cert-manager: - enabled: #@ isClusterPackageEnableByDefault("cert-manager") - settings: {} - external-dns: - enabled: #@ isClusterPackageEnableByDefault("external-dns") - settings: {} - certs: - enabled: #@ isClusterPackageEnableByDefault("certs") - settings: {} - kyverno: - enabled: #@ isClusterPackageEnableByDefault("kyverno") - settings: {} - kapp-controller: - enabled: #@ isClusterPackageEnableByDefault("kapp-controller") - settings: {} - educates: - enabled: #@ isClusterPackageEnableByDefault("educates") - settings: {} diff --git a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/infrastructure/custom/50-packages-enablement.yaml b/carvel-packages/installer/bundle/config/ytt/_ytt_lib/infrastructure/custom/50-packages-enablement.yaml deleted file mode 100644 index 0a383ee3e..000000000 --- a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/infrastructure/custom/50-packages-enablement.yaml +++ /dev/null @@ -1,28 +0,0 @@ -#@ load("@ytt:data", "data") -#@ load("@ytt:overlay", "overlay") - -#! This enables packages based on the user input - -#@overlay/match-child-defaults missing_ok=True -clusterPackages: - contour: - #@ if/end hasattr(data.values, "clusterPackages") and hasattr(data.values.clusterPackages, "contour") and hasattr(data.values.clusterPackages.contour, "enabled"): - enabled: #@ data.values.clusterPackages.contour.enabled - cert-manager: - #@ if/end hasattr(data.values, "clusterPackages") and hasattr(data.values.clusterPackages, "cert-manager") and hasattr(data.values.clusterPackages["cert-manager"], "enabled"): - enabled: #@ data.values.clusterPackages["cert-manager"].enabled - external-dns: - #@ if/end hasattr(data.values, "clusterPackages") and hasattr(data.values.clusterPackages, "external-dns") and hasattr(data.values.clusterPackages["external-dns"], "enabled"): - enabled: #@ data.values.clusterPackages["external-dns"].enabled - certs: - #@ if/end hasattr(data.values, "clusterPackages") and hasattr(data.values.clusterPackages, "certs") and hasattr(data.values.clusterPackages.certs, "enabled"): - enabled: #@ data.values.clusterPackages.certs.enabled - kyverno: - #@ if/end hasattr(data.values, "clusterPackages") and hasattr(data.values.clusterPackages, "kyverno") and hasattr(data.values.clusterPackages.kyverno, "enabled"): - enabled: #@ data.values.clusterPackages.kyverno.enabled - kapp-controller: - #@ if/end hasattr(data.values, "clusterPackages") and hasattr(data.values.clusterPackages, "kapp-controller") and hasattr(data.values.clusterPackages["kapp-controller"], "enabled"): - enabled: #@ data.values.clusterPackages["kapp-controller"].enabled - educates: - #@ if/end hasattr(data.values, "clusterPackages") and hasattr(data.values.clusterPackages, "educates") and hasattr(data.values.clusterPackages.educates, "enabled"): - enabled: #@ data.values.clusterPackages.educates.enabled diff --git a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/infrastructure/custom/80-copy-educates-config.yaml b/carvel-packages/installer/bundle/config/ytt/_ytt_lib/infrastructure/custom/80-copy-educates-config.yaml deleted file mode 100644 index 285e4c12e..000000000 --- a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/infrastructure/custom/80-copy-educates-config.yaml +++ /dev/null @@ -1,10 +0,0 @@ -#@ load("@ytt:data", "data") -#@ load("@ytt:overlay", "overlay") -#@ load("educates.lib.yaml", "copy_core_educates_values") - -#! This copies only core Educates values. - -#@overlay/match-child-defaults missing_ok=True -clusterPackages: - educates: - settings: #@ copy_core_educates_values() diff --git a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/infrastructure/custom/90-overlays.yaml b/carvel-packages/installer/bundle/config/ytt/_ytt_lib/infrastructure/custom/90-overlays.yaml deleted file mode 100644 index 572322612..000000000 --- a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/infrastructure/custom/90-overlays.yaml +++ /dev/null @@ -1,28 +0,0 @@ -#@ load("@ytt:data", "data") -#@ load("@ytt:overlay", "overlay") - -#@overlay/match-child-defaults missing_ok=True -clusterPackages: - contour: - #@ if/end hasattr(data.values, "clusterPackages") and hasattr(data.values.clusterPackages, "contour") and hasattr(data.values.clusterPackages.contour, "settings"): - settings: #@ data.values.clusterPackages.contour.settings - cert-manager: - #@ if/end hasattr(data.values, "clusterPackages") and hasattr(data.values.clusterPackages, "cert-manager") and hasattr(data.values.clusterPackages["cert-manager"], "settings"): - settings: #@ data.values.clusterPackages["cert-manager"].settings - external-dns: - #@ if/end hasattr(data.values, "clusterPackages") and hasattr(data.values.clusterPackages, "external-dns") and hasattr(data.values.clusterPackages["external-dns"], "settings"): - settings: #@ data.values.clusterPackages["external-dns"].settings - certs: - #@ if/end hasattr(data.values, "clusterPackages") and hasattr(data.values.clusterPackages, "certs") and hasattr(data.values.clusterPackages.certs, "settings"): - settings: #@ data.values.clusterPackages.certs.settings - kyverno: - #@ if/end hasattr(data.values, "clusterPackages") and hasattr(data.values.clusterPackages, "kyverno") and hasattr(data.values.clusterPackages.kyverno, "settings"): - settings: #@ data.values.clusterPackages.kyverno.settings - kapp-controller: - #@ if/end hasattr(data.values, "clusterPackages") and hasattr(data.values.clusterPackages, "kapp-controller") and hasattr(data.values.clusterPackages["kapp-controller"], "settings"): - settings: #@ data.values.clusterPackages["kapp-controller"].settings - -#@overlay/merge - educates: - #@ if/end hasattr(data.values, "clusterPackages") and hasattr(data.values.clusterPackages, "educates") and hasattr(data.values.clusterPackages["educates"], "settings"): - settings: #@ data.values.clusterPackages["educates"].settings diff --git a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/infrastructure/custom/99-remove-settings-disabled.yaml b/carvel-packages/installer/bundle/config/ytt/_ytt_lib/infrastructure/custom/99-remove-settings-disabled.yaml deleted file mode 100644 index 30db2e394..000000000 --- a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/infrastructure/custom/99-remove-settings-disabled.yaml +++ /dev/null @@ -1,36 +0,0 @@ -#@ load("@ytt:data", "data") -#@ load("@ytt:overlay", "overlay") -#@ load("functions.star", "isClusterPackageExplicitDisabled") - -#! This removes settings for disabled packages - -#@overlay/match-child-defaults missing_ok=True -clusterPackages: - contour: - #@ if/end isClusterPackageExplicitDisabled("contour"): - #@overlay/replace - settings: {} - cert-manager: - #@ if/end isClusterPackageExplicitDisabled("cert-manager"): - #@overlay/replace - settings: {} - external-dns: - #@ if/end isClusterPackageExplicitDisabled("external-dns"): - #@overlay/replace - settings: {} - certs: - #@ if/end isClusterPackageExplicitDisabled("certs"): - #@overlay/replace - settings: {} - kyverno: - #@ if/end isClusterPackageExplicitDisabled("kyverno"): - #@overlay/replace - settings: {} - kapp-controller: - #@ if/end isClusterPackageExplicitDisabled("kapp-controller"): - #@overlay/replace - settings: {} - educates: - #@ if/end isClusterPackageExplicitDisabled("educates"): - #@overlay/replace - settings: {} diff --git a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/infrastructure/custom/README.md b/carvel-packages/installer/bundle/config/ytt/_ytt_lib/infrastructure/custom/README.md deleted file mode 100644 index 03a048463..000000000 --- a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/infrastructure/custom/README.md +++ /dev/null @@ -1,5 +0,0 @@ -# Custom -For custom we only accept the clusterPackages configuration. -All the other configuration will be discarded. -There's no default configuration being applied. -Whatever main config is provided it will be discarded \ No newline at end of file diff --git a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/infrastructure/custom/defaults.star b/carvel-packages/installer/bundle/config/ytt/_ytt_lib/infrastructure/custom/defaults.star deleted file mode 100644 index 296e59248..000000000 --- a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/infrastructure/custom/defaults.star +++ /dev/null @@ -1,4 +0,0 @@ -load("@ytt:data", "data") - -enabledByDefaultPackagesList = [ -] \ No newline at end of file diff --git a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/infrastructure/custom/educates.lib.yaml b/carvel-packages/installer/bundle/config/ytt/_ytt_lib/infrastructure/custom/educates.lib.yaml deleted file mode 100644 index cd89ac91d..000000000 --- a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/infrastructure/custom/educates.lib.yaml +++ /dev/null @@ -1,190 +0,0 @@ -#@ load("@ytt:data", "data") - -#! TODO: Customize certs name reference in eks -#@ def copy_all_educates_values(): - -#@ if/end hasattr(data.values, "sessionManager") and data.values.sessionManager != None: -sessionManager: - clusterAdmin: #@ data.values.sessionManager.clusterAdmin -#@ if/end hasattr(data.values, "imageRegistry") and data.values.imageRegistry != None: -imageRegistry: - #@ if/end hasattr(data.values.imageRegistry, "namespace") and data.values.imageRegistry.namespace != None: - namespace: #@ data.values.imageRegistry.namespace - #@ if/end hasattr(data.values.imageRegistry, "host") and data.values.imageRegistry.host != None: - host: #@ data.values.imageRegistry.host -#@ if/end hasattr(data.values, "version") and data.values.version != None: -version: #@ data.values.version -#@ if/end hasattr(data.values, "imageVersions") and data.values.imageVersions != None: -imageVersions: #@ data.values.imageVersions -#@ if/end hasattr(data.values, "clusterRuntime") and data.values.clusterRuntime != None: -clusterRuntime: #@ data.values.clusterRuntime -#@ if/end hasattr(data.values, "clusterIngress") and data.values.clusterIngress != None: -clusterIngress: - #@ if/end hasattr(data.values.clusterIngress, "domain") and data.values.clusterIngress.domain != None: - domain: #@ data.values.clusterIngress.domain - #@ if/end hasattr(data.values.clusterIngress, "class") and data.values.clusterIngress["class"] != None: - class: #@ data.values.clusterIngress["class"] - #@ if/end hasattr(data.values.clusterIngress, "protocol") and data.values.clusterIngress.protocol != None: - protocol: #@ data.values.clusterIngress.protocol - #@ if/end hasattr(data.values.clusterIngress, "tlsCertificate") and data.values.clusterIngress.tlsCertificate != None: - tlsCertificate: - #@ if/end hasattr(data.values.clusterIngress.tlsCertificate, "tls.crt") and data.values.clusterIngress.tlsCertificate["tls.crt"] != None: - tls.crt: #@ data.values.clusterIngress.tlsCertificate["tls.crt"] - #@ if/end hasattr(data.values.clusterIngress.tlsCertificate, "tls.key") and data.values.clusterIngress.tlsCertificate["tls.key"] != None: - tls.key: #@ data.values.clusterIngress.tlsCertificate["tls.key"] - #! TODO: Customize certs name reference in eks - #! projectcontour/wildcard - #@ if/end hasattr(data.values.clusterIngress, "tlsCertificateRef") and data.values.clusterIngress.tlsCertificateRef != None: - tlsCertificateRef: - namespace: #@ (hasattr(data.values.clusterIngress.tlsCertificateRef, "namespace") and data.values.clusterIngress.tlsCertificateRef.namespace != None) and data.values.clusterIngress.tlsCertificateRef.namespace or "projectcontour" - #@ if/end hasattr(data.values.clusterIngress.tlsCertificateRef, "name") and data.values.clusterIngress.tlsCertificateRef.name != None: - name: #@ data.values.clusterIngress.tlsCertificateRef.name - #@ if/end hasattr(data.values.clusterIngress, "caCertificate") and data.values.clusterIngress.caCertificate != None: - caCertificate: #@ data.values.clusterIngress.caCertificate - #@ if/end hasattr(data.values.clusterIngress, "caCertificateRef") and data.values.clusterIngress.caCertificateRef != None: - caCertificateRef: - #@ if/end hasattr(data.values.clusterIngress.caCertificateRef, "namespace") and data.values.clusterIngress.caCertificateRef.namespace != None: - namespace: #@ data.values.clusterIngress.caCertificateRef.namespace - #@ if/end hasattr(data.values.clusterIngress.caCertificateRef, "name") and data.values.clusterIngress.caCertificateRef.name != None: - name: #@ data.values.clusterIngress.caCertificateRef.name - #@ if/end hasattr(data.values.clusterIngress, "caNodeInjector") and data.values.clusterIngress.caNodeInjector != None: - caNodeInjector: #@ data.values.clusterIngress.caNodeInjector -#@ if/end hasattr(data.values, "sessionCookies") and data.values.sessionCookies != None: -sessionCookies: #@ data.values.sessionCookies -#@ if/end hasattr(data.values, "clusterStorage") and data.values.clusterStorage != None: -clusterStorage: - #@ if/end hasattr(data.values.clusterStorage, "class") and data.values.clusterStorage["class"] != None: - class: #@ data.values.clusterStorage["class"] - #@ if/end hasattr(data.values.clusterStorage, "user") and data.values.clusterStorage.user != None: - user: #@ data.values.clusterStorage.user - #@ if/end hasattr(data.values.clusterStorage, "group") and data.values.clusterStorage.group != None: - group: #@ data.values.clusterStorage.group -#@ if/end hasattr(data.values, "clusterSecrets") and data.values.clusterSecrets != None: -clusterSecrets: #@ data.values.clusterSecrets -#@ if/end hasattr(data.values, "clusterSecurity") and data.values.clusterSecurity != None: -clusterSecurity: #@ data.values.clusterSecurity -#@ if/end hasattr(data.values, "workshopSecurity") and data.values.workshopSecurity != None: -workshopSecurity: #@ data.values.workshopSecurity -#@ if/end hasattr(data.values, "trainingPortal") and data.values.trainingPortal != None: -trainingPortal: - #@ if/end hasattr(data.values.trainingPortal, "credentials") and data.values.trainingPortal.credentials != None: - credentials: - #@ if/end hasattr(data.values.trainingPortal.credentials, "admin") and data.values.trainingPortal.credentials.admin != None: - admin: - #@ if/end hasattr(data.values.trainingPortal.credentials.admin, "username") and data.values.trainingPortal.credentials.admin.username != None: - username: #@ data.values.trainingPortal.credentials.admin.username - #@ if/end hasattr(data.values.trainingPortal.credentials.admin, "password") and data.values.trainingPortal.credentials.admin.password != None: - password: #@ data.values.trainingPortal.credentials.admin.password - #@ if/end hasattr(data.values.trainingPortal.credentials, "robot") and data.values.trainingPortal.credentials.robot != None: - robot: - #@ if/end hasattr(data.values.trainingPortal.credentials.robot, "username") and data.values.trainingPortal.credentials.robot.username != None: - username: #@ data.values.trainingPortal.credentials.robot.username - #@ if/end hasattr(data.values.trainingPortal.credentials.robot, "password") and data.values.trainingPortal.credentials.robot.password != None: - password: #@ data.values.trainingPortal.credentials.robot.password - #@ if/end hasattr(data.values.trainingPortal, "clients") and data.values.trainingPortal.clients != None: - clients: - #@ if/end hasattr(data.values.trainingPortal.clients, "robot") and data.values.trainingPortal.clients.robot != None: - robot: - #@ if/end hasattr(data.values.trainingPortal.clients.robot, "id") and data.values.trainingPortal.clients.robot.id != None: - id: #@ data.values.trainingPortal.clients.robot.id - #@ if/end hasattr(data.values.trainingPortal.clients.robot, "secret") and data.values.trainingPortal.clients.robot.secret != None: - secret: #@ data.values.trainingPortal.clients.robot.secret -#@ if/end hasattr(data.values, "dockerDaemon") and data.values.dockerDaemon != None: -dockerDaemon: - #@ if/end hasattr(data.values.dockerDaemon, "networkMTU") and data.values.dockerDaemon.networkMTU != None: - networkMTU: #@ data.values.dockerDaemon.networkMTU - #@ if/end hasattr(data.values.dockerDaemon, "proxyCache") and data.values.dockerDaemon.proxyCache != None: - proxyCache: - #@ if/end hasattr(data.values.dockerDaemon.proxyCache, "remoteURL") and data.values.dockerDaemon.proxyCache.remoteURL != None: - remoteURL: #@ data.values.dockerDaemon.proxyCache.remoteURL - #@ if/end hasattr(data.values.dockerDaemon.proxyCache, "username") and data.values.dockerDaemon.proxyCache.username != None: - username: #@ data.values.dockerDaemon.proxyCache.username - #@ if/end hasattr(data.values.dockerDaemon.proxyCache, "password") and data.values.dockerDaemon.proxyCache.password != None: - password: #@ data.values.dockerDaemon.proxyCache.password -#@ if/end hasattr(data.values, "clusterNetwork") and data.values.clusterNetwork != None: -clusterNetwork: #@ data.values.clusterNetwork -#@ if/end hasattr(data.values, "workshopAnalytics") and data.values.workshopAnalytics != None: -workshopAnalytics: - #@ if/end hasattr(data.values.workshopAnalytics, "google") and data.values.workshopAnalytics.google != None: - google: - #@ if/end hasattr(data.values.workshopAnalytics.google, "trackingId") and data.values.workshopAnalytics.google.trackingId != None: - trackingId: #@ data.values.workshopAnalytics.google.trackingId - #@ if/end hasattr(data.values.workshopAnalytics, "clarity") and data.values.workshopAnalytics.clarity != None: - clarity: - #@ if/end hasattr(data.values.workshopAnalytics.clarity, "trackingId") and data.values.workshopAnalytics.clarity.trackingId != None: - trackingId: #@ data.values.workshopAnalytics.clarity.trackingId - #@ if/end hasattr(data.values.workshopAnalytics, "amplitude") and data.values.workshopAnalytics.amplitude != None: - amplitude: - #@ if/end hasattr(data.values.workshopAnalytics.amplitude, "trackingId") and data.values.workshopAnalytics.amplitude.trackingId != None: - trackingId: #@ data.values.workshopAnalytics.amplitude.trackingId - #@ if/end hasattr(data.values.workshopAnalytics, "webhook") and data.values.workshopAnalytics.webhook != None: - webhook: - #@ if/end hasattr(data.values.workshopAnalytics.webhook, "url") and data.values.workshopAnalytics.webhook.url != None: - url: #@ data.values.workshopAnalytics.webhook.url -#@ if/end hasattr(data.values, "websiteStyling") and data.values.websiteStyling != None: -websiteStyling: - #@ if/end hasattr(data.values.websiteStyling, "workshopDashboard") and data.values.websiteStyling.workshopDashboard != None: - workshopDashboard: - #@ if/end hasattr(data.values.websiteStyling.workshopDashboard, "html") and data.values.websiteStyling.workshopDashboard.html != None: - html: #@ data.values.websiteStyling.workshopDashboard.html - #@ if/end hasattr(data.values.websiteStyling.workshopDashboard, "script") and data.values.websiteStyling.workshopDashboard.script != None: - script: #@ data.values.websiteStyling.workshopDashboard.script - #@ if/end hasattr(data.values.websiteStyling.workshopDashboard, "style") and data.values.websiteStyling.workshopDashboard.style != None: - style: #@ data.values.websiteStyling.workshopDashboard.style - #@ if/end hasattr(data.values.websiteStyling, "workshopInstructions") and data.values.websiteStyling.workshopInstructions != None: - workshopInstructions: - #@ if/end hasattr(data.values.websiteStyling.workshopInstructions, "html") and data.values.websiteStyling.workshopInstructions.html != None: - html: #@ data.values.websiteStyling.workshopInstructions.html - #@ if/end hasattr(data.values.websiteStyling.workshopInstructions, "script") and data.values.websiteStyling.workshopInstructions.script != None: - script: #@ data.values.websiteStyling.workshopInstructions.script - #@ if/end hasattr(data.values.websiteStyling.workshopInstructions, "style") and data.values.websiteStyling.workshopInstructions.style != None: - style: #@ data.values.websiteStyling.workshopInstructions.style - #@ if/end hasattr(data.values.websiteStyling, "workshopStarted") and data.values.websiteStyling.workshopStarted != None: - workshopStarted: - #@ if/end hasattr(data.values.websiteStyling.workshopStarted, "html") and data.values.websiteStyling.workshopStarted.html != None: - html: #@ data.values.websiteStyling.workshopStarted.html - #@ if/end hasattr(data.values.websiteStyling, "workshopFinished") and data.values.websiteStyling.workshopFinished != None: - workshopFinished: - #@ if/end hasattr(data.values.websiteStyling.workshopFinished, "html") and data.values.websiteStyling.workshopFinished.html != None: - html: #@ data.values.websiteStyling.workshopFinished.html - #@ if/end hasattr(data.values.websiteStyling, "trainingPortal") and data.values.websiteStyling.trainingPortal != None: - trainingPortal: - #@ if/end hasattr(data.values.websiteStyling.trainingPortal, "html") and data.values.websiteStyling.trainingPortal.html != None: - html: #@ data.values.websiteStyling.trainingPortal.html - #@ if/end hasattr(data.values.websiteStyling.trainingPortal, "script") and data.values.websiteStyling.trainingPortal.script != None: - script: #@ data.values.websiteStyling.trainingPortal.script - #@ if/end hasattr(data.values.websiteStyling.trainingPortal, "style") and data.values.websiteStyling.trainingPortal.style != None: - style: #@ data.values.websiteStyling.trainingPortal.style - #@ if/end hasattr(data.values.websiteStyling, "defaultTheme") and data.values.websiteStyling.defaultTheme != None: - defaultTheme: #@ data.values.websiteStyling.defaultTheme - #@ if/end hasattr(data.values.websiteStyling, "themeDataRefs") and data.values.websiteStyling.themeDataRefs != None: - themeDataRefs: #@ data.values.websiteStyling.themeDataRefs - #@ if/end hasattr(data.values.websiteStyling, "frameAncestors") and data.values.websiteStyling.frameAncestors != None: - frameAncestors: #@ data.values.websiteStyling.frameAncestors -#@ if/end hasattr(data.values, "imagePuller") and data.values.imagePuller != None: -imagePuller: - enabled: #@ data.values.imagePuller.enabled - #@ if hasattr(data.values.imagePuller, "prePullImages") and data.values.imagePuller.prePullImages != None: - #@overlay/replace - prePullImages: #@ data.values.imagePuller.prePullImages - #@ end -#@ if/end hasattr(data.values, "lookupService") and data.values.lookupService != None: -lookupService: - #@ if/end hasattr(data.values.lookupService, "enabled") and data.values.lookupService.enabled != None: - enabled: #@ data.values.lookupService.enabled - #@ if/end hasattr(data.values.lookupService, "ingressPrefix") and data.values.lookupService.ingressPrefix != None: - ingressPrefix: #@ data.values.lookupService.ingressPrefix -#@ end - -#@ def copy_core_educates_values(): -#@ if/end hasattr(data.values, "imageRegistry") and data.values.imageRegistry != None: -imageRegistry: - #@ if/end hasattr(data.values.imageRegistry, "namespace") and data.values.imageRegistry.namespace != None: - namespace: #@ data.values.imageRegistry.namespace - #@ if/end hasattr(data.values.imageRegistry, "host") and data.values.imageRegistry.host != None: - host: #@ data.values.imageRegistry.host -#@ if/end hasattr(data.values, "version") and data.values.version != None: -version: #@ data.values.version -#@ if/end hasattr(data.values, "imageVersions") and data.values.imageVersions != None: -imageVersions: #@ data.values.imageVersions -#@ end diff --git a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/infrastructure/custom/functions.star b/carvel-packages/installer/bundle/config/ytt/_ytt_lib/infrastructure/custom/functions.star deleted file mode 100644 index 6a078759f..000000000 --- a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/infrastructure/custom/functions.star +++ /dev/null @@ -1,18 +0,0 @@ -load("@ytt:data", "data") -load("defaults.star", "enabledByDefaultPackagesList") - -def isClusterPackageEnableByDefault(package): - return package in enabledByDefaultPackagesList -end - -def isClusterPackageEnabled(package): - if hasattr(data.values, "clusterPackages") and hasattr(data.values.clusterPackages, package) and hasattr(data.values.clusterPackages[package], "enabled"): - return data.values.clusterPackages[package].enabled - else: - return package in enabledByDefaultPackagesList - end -end - -def isClusterPackageExplicitDisabled(package): - return not isClusterPackageEnabled(package) -end \ No newline at end of file diff --git a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/infrastructure/eks/00-remove-toplevel-values.yaml b/carvel-packages/installer/bundle/config/ytt/_ytt_lib/infrastructure/eks/00-remove-toplevel-values.yaml deleted file mode 100644 index 931e60126..000000000 --- a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/infrastructure/eks/00-remove-toplevel-values.yaml +++ /dev/null @@ -1,50 +0,0 @@ -#@ load("@ytt:data", "data") -#@ load("@ytt:overlay", "overlay") - -#@overlay/remove -debug: - -#@overlay/remove -localKindCluster: -#@overlay/remove -localDNSResolver: - -#@overlay/remove -clusterInfrastructure: - -#@overlay/remove -sessionManager: -#@overlay/remove -imageRegistry: -#@overlay/remove -version: -#@overlay/remove -imageVersions: -#@overlay/remove -clusterRuntime: -#@overlay/remove -clusterIngress: -#@overlay/remove -sessionCookies: -#@overlay/remove -clusterStorage: -#@overlay/remove -clusterSecrets: -#@overlay/remove -clusterSecurity: -#@overlay/remove -workshopSecurity: -#@overlay/remove -trainingPortal: -#@overlay/remove -dockerDaemon: -#@overlay/remove -clusterNetwork: -#@overlay/remove -workshopAnalytics: -#@overlay/remove -websiteStyling: -#@overlay/remove -imagePuller: -#@overlay/remove -lookupService: diff --git a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/infrastructure/eks/10-default-settings-for-provider.yaml b/carvel-packages/installer/bundle/config/ytt/_ytt_lib/infrastructure/eks/10-default-settings-for-provider.yaml deleted file mode 100644 index 7a5cba988..000000000 --- a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/infrastructure/eks/10-default-settings-for-provider.yaml +++ /dev/null @@ -1,72 +0,0 @@ -#@ load("@ytt:data", "data") -#@ load("@ytt:overlay", "overlay") -#@ load("@ytt:assert", "assert") -#@ load("functions.star", "isClusterPackageEnableByDefault", "xgetattr") - -#@ (hasIrsaRoleExternalDns, _) = assert.try_to(lambda: len(data.values["clusterInfrastructure"]["aws"]["irsaRoles"]["external-dns"]) > 0) -#@ if hasIrsaRoleExternalDns: -#@ externalDnsIrsaRole = data.values["clusterInfrastructure"]["aws"]["irsaRoles"]["external-dns"] -#@ else: -#@ fail("external-dns is enabled and can not be configured. Missing irsaRole") -#@ end - -#@ (hasIrsaRoleCertManager, _) = assert.try_to(lambda: len(data.values["clusterInfrastructure"]["aws"]["irsaRoles"]["cert-manager"]) > 0) -#@ if hasIrsaRoleCertManager: -#@ certManagerIrsaRole = data.values["clusterInfrastructure"]["aws"]["irsaRoles"]["cert-manager"] -#@ else: -#@ fail("cert-manager is enabled and can not be configured. Missing irsaRole") -#@ end - - -#@overlay/match-child-defaults missing_ok=True -#@overlay/replace -clusterPackages: - contour: - enabled: #@ isClusterPackageEnableByDefault("contour") - settings: - infraProvider: aws - configFileContents: - defaultHttpVersions: - - "HTTP/1.1" - service: - type: LoadBalancer - externaldns: - domains: - - #@ data.values.clusterIngress.domain - cert-manager: - enabled: #@ isClusterPackageEnableByDefault("cert-manager") - settings: - serviceaccount: - annotations: - eks.amazonaws.com/role-arn: #@ certManagerIrsaRole - external-dns: - enabled: #@ isClusterPackageEnableByDefault("external-dns") - settings: - infraProvider: aws - serviceaccount: - annotations: - eks.amazonaws.com/role-arn: #@ externalDnsIrsaRole - aws: - args: - domain_filter: #@ data.values.clusterInfrastructure.aws.route53.hostedZone if hasattr(data.values.clusterInfrastructure.aws.route53, "hostedZone") else data.values.clusterIngress.domain - txt_owner_id: #@ data.values.clusterIngress.domain - policy: sync - certs: - enabled: #@ isClusterPackageEnableByDefault("certs") - settings: - certProvider: acme-aws - domains: - - #@ data.values.clusterIngress.domain - acme: - aws: - certs: - region: #@ data.values.clusterInfrastructure.aws.region - kyverno: - enabled: #@ isClusterPackageEnableByDefault("kyverno") - settings: {} - kapp-controller: - enabled: #@ isClusterPackageEnableByDefault("kapp-controller") - settings: {} - educates: - enabled: #@ isClusterPackageEnableByDefault("educates") - settings: #@ xgetattr(data.values, "clusterPackages.educates.settings") diff --git a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/infrastructure/eks/12-overlays.yaml b/carvel-packages/installer/bundle/config/ytt/_ytt_lib/infrastructure/eks/12-overlays.yaml deleted file mode 100644 index 43314cca6..000000000 --- a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/infrastructure/eks/12-overlays.yaml +++ /dev/null @@ -1,10 +0,0 @@ -#@ load("@ytt:overlay", "overlay") - -#@overlay/match-child-defaults missing_ok=True -clusterPackages: - educates: - settings: - clusterIngress: - tlsCertificateRef: - namespace: projectcontour - name: educateswildcard diff --git a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/infrastructure/eks/50-packages-enablement.yaml b/carvel-packages/installer/bundle/config/ytt/_ytt_lib/infrastructure/eks/50-packages-enablement.yaml deleted file mode 100644 index 0a383ee3e..000000000 --- a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/infrastructure/eks/50-packages-enablement.yaml +++ /dev/null @@ -1,28 +0,0 @@ -#@ load("@ytt:data", "data") -#@ load("@ytt:overlay", "overlay") - -#! This enables packages based on the user input - -#@overlay/match-child-defaults missing_ok=True -clusterPackages: - contour: - #@ if/end hasattr(data.values, "clusterPackages") and hasattr(data.values.clusterPackages, "contour") and hasattr(data.values.clusterPackages.contour, "enabled"): - enabled: #@ data.values.clusterPackages.contour.enabled - cert-manager: - #@ if/end hasattr(data.values, "clusterPackages") and hasattr(data.values.clusterPackages, "cert-manager") and hasattr(data.values.clusterPackages["cert-manager"], "enabled"): - enabled: #@ data.values.clusterPackages["cert-manager"].enabled - external-dns: - #@ if/end hasattr(data.values, "clusterPackages") and hasattr(data.values.clusterPackages, "external-dns") and hasattr(data.values.clusterPackages["external-dns"], "enabled"): - enabled: #@ data.values.clusterPackages["external-dns"].enabled - certs: - #@ if/end hasattr(data.values, "clusterPackages") and hasattr(data.values.clusterPackages, "certs") and hasattr(data.values.clusterPackages.certs, "enabled"): - enabled: #@ data.values.clusterPackages.certs.enabled - kyverno: - #@ if/end hasattr(data.values, "clusterPackages") and hasattr(data.values.clusterPackages, "kyverno") and hasattr(data.values.clusterPackages.kyverno, "enabled"): - enabled: #@ data.values.clusterPackages.kyverno.enabled - kapp-controller: - #@ if/end hasattr(data.values, "clusterPackages") and hasattr(data.values.clusterPackages, "kapp-controller") and hasattr(data.values.clusterPackages["kapp-controller"], "enabled"): - enabled: #@ data.values.clusterPackages["kapp-controller"].enabled - educates: - #@ if/end hasattr(data.values, "clusterPackages") and hasattr(data.values.clusterPackages, "educates") and hasattr(data.values.clusterPackages.educates, "enabled"): - enabled: #@ data.values.clusterPackages.educates.enabled diff --git a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/infrastructure/eks/80-copy-educates-config.yaml b/carvel-packages/installer/bundle/config/ytt/_ytt_lib/infrastructure/eks/80-copy-educates-config.yaml deleted file mode 100644 index 1afda1acb..000000000 --- a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/infrastructure/eks/80-copy-educates-config.yaml +++ /dev/null @@ -1,10 +0,0 @@ -#@ load("@ytt:data", "data") -#@ load("@ytt:overlay", "overlay") -#@ load("educates.lib.yaml", "copy_all_educates_values") - -#! This copies user provided values for the custom infrastructure provider. - -#@overlay/match-child-defaults missing_ok=True -clusterPackages: - educates: - settings: #@ copy_all_educates_values() diff --git a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/infrastructure/eks/99-remove-settings-disabled.yaml b/carvel-packages/installer/bundle/config/ytt/_ytt_lib/infrastructure/eks/99-remove-settings-disabled.yaml deleted file mode 100644 index 25b8297c8..000000000 --- a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/infrastructure/eks/99-remove-settings-disabled.yaml +++ /dev/null @@ -1,36 +0,0 @@ -#@ load("@ytt:data", "data") -#@ load("@ytt:overlay", "overlay") -#@ load("functions.star", "isClusterPackageExplicitDisabled") - -#! This removes settings for disabled packages - -#@overlay/match-child-defaults missing_ok=True -clusterPackages: - contour: - #@ if/end isClusterPackageExplicitDisabled("contour"): - #@overlay/replace - settings: {} - cert-manager: - #@ if/end isClusterPackageExplicitDisabled("cert-manager"): - #@overlay/replace - settings: {} - external-dns: - #@ if/end isClusterPackageExplicitDisabled("external-dns"): - #@overlay/replace - settings: {} - certs: - #@ if/end isClusterPackageExplicitDisabled("certs"): - #@overlay/replace - settings: {} - kyverno: - #@ if/end isClusterPackageExplicitDisabled("kyverno"): - #@overlay/replace - settings: {} - kapp-controller: - #@ if/end isClusterPackageExplicitDisabled("kapp-controller"): - #@overlay/replace - settings: {} - #! educates: - #! #@ if/end isClusterPackageExplicitDisabled("educates"): - #! #@overlay/replace - #! settings: {} diff --git a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/infrastructure/eks/README.md b/carvel-packages/installer/bundle/config/ytt/_ytt_lib/infrastructure/eks/README.md deleted file mode 100644 index a684b3aec..000000000 --- a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/infrastructure/eks/README.md +++ /dev/null @@ -1,3 +0,0 @@ -# EKS -For EKS we only allow the opinionated configuration for the packages, so, not settings are allowed -although enabling/disabling the package is allowed at users' risk. \ No newline at end of file diff --git a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/infrastructure/eks/defaults.star b/carvel-packages/installer/bundle/config/ytt/_ytt_lib/infrastructure/eks/defaults.star deleted file mode 100644 index 6b9484322..000000000 --- a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/infrastructure/eks/defaults.star +++ /dev/null @@ -1,10 +0,0 @@ -load("@ytt:data", "data") - -enabledByDefaultPackagesList = [ - "cert-manager", - "contour", - "external-dns", - "certs", - "kyverno", - "educates" -] \ No newline at end of file diff --git a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/infrastructure/eks/educates.lib.yaml b/carvel-packages/installer/bundle/config/ytt/_ytt_lib/infrastructure/eks/educates.lib.yaml deleted file mode 100644 index 8e2a52b45..000000000 --- a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/infrastructure/eks/educates.lib.yaml +++ /dev/null @@ -1,177 +0,0 @@ -#@ load("@ytt:data", "data") - -#! TODO: Customize certs name reference in eks -#@ def copy_all_educates_values(): - -#@ if/end hasattr(data.values, "sessionManager") and data.values.sessionManager != None: -sessionManager: - clusterAdmin: #@ data.values.sessionManager.clusterAdmin -#@ if/end hasattr(data.values, "imageRegistry") and data.values.imageRegistry != None: -imageRegistry: - #@ if/end hasattr(data.values.imageRegistry, "namespace") and data.values.imageRegistry.namespace != None: - namespace: #@ data.values.imageRegistry.namespace - #@ if/end hasattr(data.values.imageRegistry, "host") and data.values.imageRegistry.host != None: - host: #@ data.values.imageRegistry.host -#@ if/end hasattr(data.values, "version") and data.values.version != None: -version: #@ data.values.version -#@ if/end hasattr(data.values, "imageVersions") and data.values.imageVersions != None: -imageVersions: #@ data.values.imageVersions -#@ if/end hasattr(data.values, "clusterRuntime") and data.values.clusterRuntime != None: -clusterRuntime: #@ data.values.clusterRuntime -#@ if/end hasattr(data.values, "clusterIngress") and data.values.clusterIngress != None: -clusterIngress: - #@ if/end hasattr(data.values.clusterIngress, "domain") and data.values.clusterIngress.domain != None: - domain: #@ data.values.clusterIngress.domain - #@ if/end hasattr(data.values.clusterIngress, "class") and data.values.clusterIngress["class"] != None: - class: #@ data.values.clusterIngress["class"] - #@ if/end hasattr(data.values.clusterIngress, "protocol") and data.values.clusterIngress.protocol != None: - protocol: #@ data.values.clusterIngress.protocol - #@ if/end hasattr(data.values.clusterIngress, "tlsCertificate") and data.values.clusterIngress.tlsCertificate != None: - tlsCertificate: - #@ if/end hasattr(data.values.clusterIngress.tlsCertificate, "tls.crt") and data.values.clusterIngress.tlsCertificate["tls.crt"] != None: - tls.crt: #@ data.values.clusterIngress.tlsCertificate["tls.crt"] - #@ if/end hasattr(data.values.clusterIngress.tlsCertificate, "tls.key") and data.values.clusterIngress.tlsCertificate["tls.key"] != None: - tls.key: #@ data.values.clusterIngress.tlsCertificate["tls.key"] - #! TODO: Customize certs name reference in eks - #! projectcontour/wildcard - #@ if/end hasattr(data.values.clusterIngress, "tlsCertificateRef") and data.values.clusterIngress.tlsCertificateRef != None: - tlsCertificateRef: - namespace: #@ (hasattr(data.values.clusterIngress.tlsCertificateRef, "namespace") and data.values.clusterIngress.tlsCertificateRef.namespace != None) and data.values.clusterIngress.tlsCertificateRef.namespace or "projectcontour" - #@ if/end hasattr(data.values.clusterIngress.tlsCertificateRef, "name") and data.values.clusterIngress.tlsCertificateRef.name != None: - name: #@ data.values.clusterIngress.tlsCertificateRef.name - #@ if/end hasattr(data.values.clusterIngress, "caCertificate") and data.values.clusterIngress.caCertificate != None: - caCertificate: #@ data.values.clusterIngress.caCertificate - #@ if/end hasattr(data.values.clusterIngress, "caCertificateRef") and data.values.clusterIngress.caCertificateRef != None: - caCertificateRef: - #@ if/end hasattr(data.values.clusterIngress.caCertificateRef, "namespace") and data.values.clusterIngress.caCertificateRef.namespace != None: - namespace: #@ data.values.clusterIngress.caCertificateRef.namespace - #@ if/end hasattr(data.values.clusterIngress.caCertificateRef, "name") and data.values.clusterIngress.caCertificateRef.name != None: - name: #@ data.values.clusterIngress.caCertificateRef.name - #@ if/end hasattr(data.values.clusterIngress, "caNodeInjector") and data.values.clusterIngress.caNodeInjector != None: - caNodeInjector: #@ data.values.clusterIngress.caNodeInjector -#@ if/end hasattr(data.values, "sessionCookies") and data.values.sessionCookies != None: -sessionCookies: #@ data.values.sessionCookies -#@ if/end hasattr(data.values, "clusterStorage") and data.values.clusterStorage != None: -clusterStorage: - #@ if/end hasattr(data.values.clusterStorage, "class") and data.values.clusterStorage["class"] != None: - class: #@ data.values.clusterStorage["class"] - #@ if/end hasattr(data.values.clusterStorage, "user") and data.values.clusterStorage.user != None: - user: #@ data.values.clusterStorage.user - #@ if/end hasattr(data.values.clusterStorage, "group") and data.values.clusterStorage.group != None: - group: #@ data.values.clusterStorage.group -#@ if/end hasattr(data.values, "clusterSecrets") and data.values.clusterSecrets != None: -clusterSecrets: #@ data.values.clusterSecrets -#@ if/end hasattr(data.values, "clusterSecurity") and data.values.clusterSecurity != None: -clusterSecurity: #@ data.values.clusterSecurity -#@ if/end hasattr(data.values, "workshopSecurity") and data.values.workshopSecurity != None: -workshopSecurity: #@ data.values.workshopSecurity -#@ if/end hasattr(data.values, "trainingPortal") and data.values.trainingPortal != None: -trainingPortal: - #@ if/end hasattr(data.values.trainingPortal, "credentials") and data.values.trainingPortal.credentials != None: - credentials: - #@ if/end hasattr(data.values.trainingPortal.credentials, "admin") and data.values.trainingPortal.credentials.admin != None: - admin: - #@ if/end hasattr(data.values.trainingPortal.credentials.admin, "username") and data.values.trainingPortal.credentials.admin.username != None: - username: #@ data.values.trainingPortal.credentials.admin.username - #@ if/end hasattr(data.values.trainingPortal.credentials.admin, "password") and data.values.trainingPortal.credentials.admin.password != None: - password: #@ data.values.trainingPortal.credentials.admin.password - #@ if/end hasattr(data.values.trainingPortal.credentials, "robot") and data.values.trainingPortal.credentials.robot != None: - robot: - #@ if/end hasattr(data.values.trainingPortal.credentials.robot, "username") and data.values.trainingPortal.credentials.robot.username != None: - username: #@ data.values.trainingPortal.credentials.robot.username - #@ if/end hasattr(data.values.trainingPortal.credentials.robot, "password") and data.values.trainingPortal.credentials.robot.password != None: - password: #@ data.values.trainingPortal.credentials.robot.password - #@ if/end hasattr(data.values.trainingPortal, "clients") and data.values.trainingPortal.clients != None: - clients: - #@ if/end hasattr(data.values.trainingPortal.clients, "robot") and data.values.trainingPortal.clients.robot != None: - robot: - #@ if/end hasattr(data.values.trainingPortal.clients.robot, "id") and data.values.trainingPortal.clients.robot.id != None: - id: #@ data.values.trainingPortal.clients.robot.id - #@ if/end hasattr(data.values.trainingPortal.clients.robot, "secret") and data.values.trainingPortal.clients.robot.secret != None: - secret: #@ data.values.trainingPortal.clients.robot.secret -#@ if/end hasattr(data.values, "dockerDaemon") and data.values.dockerDaemon != None: -dockerDaemon: - #@ if/end hasattr(data.values.dockerDaemon, "networkMTU") and data.values.dockerDaemon.networkMTU != None: - networkMTU: #@ data.values.dockerDaemon.networkMTU - #@ if/end hasattr(data.values.dockerDaemon, "proxyCache") and data.values.dockerDaemon.proxyCache != None: - proxyCache: - #@ if/end hasattr(data.values.dockerDaemon.proxyCache, "remoteURL") and data.values.dockerDaemon.proxyCache.remoteURL != None: - remoteURL: #@ data.values.dockerDaemon.proxyCache.remoteURL - #@ if/end hasattr(data.values.dockerDaemon.proxyCache, "username") and data.values.dockerDaemon.proxyCache.username != None: - username: #@ data.values.dockerDaemon.proxyCache.username - #@ if/end hasattr(data.values.dockerDaemon.proxyCache, "password") and data.values.dockerDaemon.proxyCache.password != None: - password: #@ data.values.dockerDaemon.proxyCache.password -#@ if/end hasattr(data.values, "clusterNetwork") and data.values.clusterNetwork != None: -clusterNetwork: #@ data.values.clusterNetwork -#@ if/end hasattr(data.values, "workshopAnalytics") and data.values.workshopAnalytics != None: -workshopAnalytics: - #@ if/end hasattr(data.values.workshopAnalytics, "google") and data.values.workshopAnalytics.google != None: - google: - #@ if/end hasattr(data.values.workshopAnalytics.google, "trackingId") and data.values.workshopAnalytics.google.trackingId != None: - trackingId: #@ data.values.workshopAnalytics.google.trackingId - #@ if/end hasattr(data.values.workshopAnalytics, "clarity") and data.values.workshopAnalytics.clarity != None: - clarity: - #@ if/end hasattr(data.values.workshopAnalytics.clarity, "trackingId") and data.values.workshopAnalytics.clarity.trackingId != None: - trackingId: #@ data.values.workshopAnalytics.clarity.trackingId - #@ if/end hasattr(data.values.workshopAnalytics, "amplitude") and data.values.workshopAnalytics.amplitude != None: - amplitude: - #@ if/end hasattr(data.values.workshopAnalytics.amplitude, "trackingId") and data.values.workshopAnalytics.amplitude.trackingId != None: - trackingId: #@ data.values.workshopAnalytics.amplitude.trackingId - #@ if/end hasattr(data.values.workshopAnalytics, "webhook") and data.values.workshopAnalytics.webhook != None: - webhook: - #@ if/end hasattr(data.values.workshopAnalytics.webhook, "url") and data.values.workshopAnalytics.webhook.url != None: - url: #@ data.values.workshopAnalytics.webhook.url -#@ if/end hasattr(data.values, "websiteStyling") and data.values.websiteStyling != None: -websiteStyling: - #@ if/end hasattr(data.values.websiteStyling, "workshopDashboard") and data.values.websiteStyling.workshopDashboard != None: - workshopDashboard: - #@ if/end hasattr(data.values.websiteStyling.workshopDashboard, "html") and data.values.websiteStyling.workshopDashboard.html != None: - html: #@ data.values.websiteStyling.workshopDashboard.html - #@ if/end hasattr(data.values.websiteStyling.workshopDashboard, "script") and data.values.websiteStyling.workshopDashboard.script != None: - script: #@ data.values.websiteStyling.workshopDashboard.script - #@ if/end hasattr(data.values.websiteStyling.workshopDashboard, "style") and data.values.websiteStyling.workshopDashboard.style != None: - style: #@ data.values.websiteStyling.workshopDashboard.style - #@ if/end hasattr(data.values.websiteStyling, "workshopInstructions") and data.values.websiteStyling.workshopInstructions != None: - workshopInstructions: - #@ if/end hasattr(data.values.websiteStyling.workshopInstructions, "html") and data.values.websiteStyling.workshopInstructions.html != None: - html: #@ data.values.websiteStyling.workshopInstructions.html - #@ if/end hasattr(data.values.websiteStyling.workshopInstructions, "script") and data.values.websiteStyling.workshopInstructions.script != None: - script: #@ data.values.websiteStyling.workshopInstructions.script - #@ if/end hasattr(data.values.websiteStyling.workshopInstructions, "style") and data.values.websiteStyling.workshopInstructions.style != None: - style: #@ data.values.websiteStyling.workshopInstructions.style - #@ if/end hasattr(data.values.websiteStyling, "workshopStarted") and data.values.websiteStyling.workshopStarted != None: - workshopStarted: - #@ if/end hasattr(data.values.websiteStyling.workshopStarted, "html") and data.values.websiteStyling.workshopStarted.html != None: - html: #@ data.values.websiteStyling.workshopStarted.html - #@ if/end hasattr(data.values.websiteStyling, "workshopFinished") and data.values.websiteStyling.workshopFinished != None: - workshopFinished: - #@ if/end hasattr(data.values.websiteStyling.workshopFinished, "html") and data.values.websiteStyling.workshopFinished.html != None: - html: #@ data.values.websiteStyling.workshopFinished.html - #@ if/end hasattr(data.values.websiteStyling, "trainingPortal") and data.values.websiteStyling.trainingPortal != None: - trainingPortal: - #@ if/end hasattr(data.values.websiteStyling.trainingPortal, "html") and data.values.websiteStyling.trainingPortal.html != None: - html: #@ data.values.websiteStyling.trainingPortal.html - #@ if/end hasattr(data.values.websiteStyling.trainingPortal, "script") and data.values.websiteStyling.trainingPortal.script != None: - script: #@ data.values.websiteStyling.trainingPortal.script - #@ if/end hasattr(data.values.websiteStyling.trainingPortal, "style") and data.values.websiteStyling.trainingPortal.style != None: - style: #@ data.values.websiteStyling.trainingPortal.style - #@ if/end hasattr(data.values.websiteStyling, "defaultTheme") and data.values.websiteStyling.defaultTheme != None: - defaultTheme: #@ data.values.websiteStyling.defaultTheme - #@ if/end hasattr(data.values.websiteStyling, "themeDataRefs") and data.values.websiteStyling.themeDataRefs != None: - themeDataRefs: #@ data.values.websiteStyling.themeDataRefs - #@ if/end hasattr(data.values.websiteStyling, "frameAncestors") and data.values.websiteStyling.frameAncestors != None: - frameAncestors: #@ data.values.websiteStyling.frameAncestors -#@ if/end hasattr(data.values, "imagePuller") and data.values.imagePuller != None: -imagePuller: - enabled: #@ data.values.imagePuller.enabled - #@ if hasattr(data.values.imagePuller, "prePullImages") and data.values.imagePuller.prePullImages != None: - #@overlay/replace - prePullImages: #@ data.values.imagePuller.prePullImages - #@ end -#@ if/end hasattr(data.values, "lookupService") and data.values.lookupService != None: -lookupService: - #@ if/end hasattr(data.values.lookupService, "enabled") and data.values.lookupService.enabled != None: - enabled: #@ data.values.lookupService.enabled - #@ if/end hasattr(data.values.lookupService, "ingressPrefix") and data.values.lookupService.ingressPrefix != None: - ingressPrefix: #@ data.values.lookupService.ingressPrefix -#@ end diff --git a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/infrastructure/eks/functions.star b/carvel-packages/installer/bundle/config/ytt/_ytt_lib/infrastructure/eks/functions.star deleted file mode 100644 index 2c5b8bf26..000000000 --- a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/infrastructure/eks/functions.star +++ /dev/null @@ -1,35 +0,0 @@ -load("@ytt:data", "data") -load("defaults.star", "enabledByDefaultPackagesList") - -def isClusterPackageEnableByDefault(package): - return package in enabledByDefaultPackagesList -end - -def isClusterPackageEnabled(package): - if hasattr(data.values, "clusterPackages") and hasattr(data.values.clusterPackages, package) and hasattr(data.values.clusterPackages[package], "enabled"): - return data.values.clusterPackages[package].enabled - else: - return package in enabledByDefaultPackagesList - end -end - -def isClusterPackageExplicitDisabled(package): - return not isClusterPackageEnabled(package) -end - -def xgetattr(object, path, default=None): - def _lookup(object, key, default=None): - keys = key.split(".") - value = default - for key in keys: - value = getattr(object, key, None) - if value == None: - return default - end - object = value - end - return value - end - - return _lookup(object, path, default) -end diff --git a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/infrastructure/generic/00-remove-toplevel-values.yaml b/carvel-packages/installer/bundle/config/ytt/_ytt_lib/infrastructure/generic/00-remove-toplevel-values.yaml deleted file mode 100644 index 931e60126..000000000 --- a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/infrastructure/generic/00-remove-toplevel-values.yaml +++ /dev/null @@ -1,50 +0,0 @@ -#@ load("@ytt:data", "data") -#@ load("@ytt:overlay", "overlay") - -#@overlay/remove -debug: - -#@overlay/remove -localKindCluster: -#@overlay/remove -localDNSResolver: - -#@overlay/remove -clusterInfrastructure: - -#@overlay/remove -sessionManager: -#@overlay/remove -imageRegistry: -#@overlay/remove -version: -#@overlay/remove -imageVersions: -#@overlay/remove -clusterRuntime: -#@overlay/remove -clusterIngress: -#@overlay/remove -sessionCookies: -#@overlay/remove -clusterStorage: -#@overlay/remove -clusterSecrets: -#@overlay/remove -clusterSecurity: -#@overlay/remove -workshopSecurity: -#@overlay/remove -trainingPortal: -#@overlay/remove -dockerDaemon: -#@overlay/remove -clusterNetwork: -#@overlay/remove -workshopAnalytics: -#@overlay/remove -websiteStyling: -#@overlay/remove -imagePuller: -#@overlay/remove -lookupService: diff --git a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/infrastructure/generic/10-default-settings-for-provider.yaml b/carvel-packages/installer/bundle/config/ytt/_ytt_lib/infrastructure/generic/10-default-settings-for-provider.yaml deleted file mode 100644 index 5842bd68d..000000000 --- a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/infrastructure/generic/10-default-settings-for-provider.yaml +++ /dev/null @@ -1,31 +0,0 @@ -#@ load("@ytt:data", "data") -#@ load("@ytt:overlay", "overlay") -#@ load("functions.star", "xgetattr", "isClusterPackageEnableByDefault") - -#! This file contains default values for the custom infrastructure provider. -#! These are the values that will be set if not overridden by the user. - -#@overlay/match-child-defaults missing_ok=True -#@overlay/replace -clusterPackages: - contour: - enabled: #@ isClusterPackageEnableByDefault("contour") - settings: {} - cert-manager: - enabled: #@ isClusterPackageEnableByDefault("cert-manager") - settings: {} - external-dns: - enabled: #@ isClusterPackageEnableByDefault("external-dns") - settings: {} - certs: - enabled: #@ isClusterPackageEnableByDefault("certs") - settings: {} - kyverno: - enabled: #@ isClusterPackageEnableByDefault("kyverno") - settings: {} - kapp-controller: - enabled: #@ isClusterPackageEnableByDefault("kapp-controller") - settings: {} - educates: - enabled: #@ isClusterPackageEnableByDefault("educates") - settings: #@ xgetattr(data.values, "clusterPackages.educates.settings") diff --git a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/infrastructure/generic/50-packages-enablement.yaml b/carvel-packages/installer/bundle/config/ytt/_ytt_lib/infrastructure/generic/50-packages-enablement.yaml deleted file mode 100644 index d20814537..000000000 --- a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/infrastructure/generic/50-packages-enablement.yaml +++ /dev/null @@ -1,24 +0,0 @@ -#@ load("@ytt:data", "data") -#@ load("@ytt:overlay", "overlay") - -#! This enables packages based on the user input - -#@overlay/match-child-defaults missing_ok=True -clusterPackages: - #! contour enablement is immutable for generic provider (cannot be enabled via values) - cert-manager: - #@ if/end hasattr(data.values, "clusterPackages") and hasattr(data.values.clusterPackages, "cert-manager") and hasattr(data.values.clusterPackages["cert-manager"], "enabled"): - enabled: #@ data.values.clusterPackages["cert-manager"].enabled - external-dns: - #@ if/end hasattr(data.values, "clusterPackages") and hasattr(data.values.clusterPackages, "external-dns") and hasattr(data.values.clusterPackages["external-dns"], "enabled"): - enabled: #@ data.values.clusterPackages["external-dns"].enabled - certs: - #@ if/end hasattr(data.values, "clusterPackages") and hasattr(data.values.clusterPackages, "certs") and hasattr(data.values.clusterPackages.certs, "enabled"): - enabled: #@ data.values.clusterPackages.certs.enabled - kyverno: - #@ if/end hasattr(data.values, "clusterPackages") and hasattr(data.values.clusterPackages, "kyverno") and hasattr(data.values.clusterPackages.kyverno, "enabled"): - enabled: #@ data.values.clusterPackages.kyverno.enabled - kapp-controller: - #@ if/end hasattr(data.values, "clusterPackages") and hasattr(data.values.clusterPackages, "kapp-controller") and hasattr(data.values.clusterPackages["kapp-controller"], "enabled"): - enabled: #@ data.values.clusterPackages["kapp-controller"].enabled - #! educates enablement is immutable for generic provider (always enabled) diff --git a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/infrastructure/generic/80-copy-educates-config.yaml b/carvel-packages/installer/bundle/config/ytt/_ytt_lib/infrastructure/generic/80-copy-educates-config.yaml deleted file mode 100644 index 1afda1acb..000000000 --- a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/infrastructure/generic/80-copy-educates-config.yaml +++ /dev/null @@ -1,10 +0,0 @@ -#@ load("@ytt:data", "data") -#@ load("@ytt:overlay", "overlay") -#@ load("educates.lib.yaml", "copy_all_educates_values") - -#! This copies user provided values for the custom infrastructure provider. - -#@overlay/match-child-defaults missing_ok=True -clusterPackages: - educates: - settings: #@ copy_all_educates_values() diff --git a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/infrastructure/generic/99-remove-settings-disabled.yaml b/carvel-packages/installer/bundle/config/ytt/_ytt_lib/infrastructure/generic/99-remove-settings-disabled.yaml deleted file mode 100644 index 25b8297c8..000000000 --- a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/infrastructure/generic/99-remove-settings-disabled.yaml +++ /dev/null @@ -1,36 +0,0 @@ -#@ load("@ytt:data", "data") -#@ load("@ytt:overlay", "overlay") -#@ load("functions.star", "isClusterPackageExplicitDisabled") - -#! This removes settings for disabled packages - -#@overlay/match-child-defaults missing_ok=True -clusterPackages: - contour: - #@ if/end isClusterPackageExplicitDisabled("contour"): - #@overlay/replace - settings: {} - cert-manager: - #@ if/end isClusterPackageExplicitDisabled("cert-manager"): - #@overlay/replace - settings: {} - external-dns: - #@ if/end isClusterPackageExplicitDisabled("external-dns"): - #@overlay/replace - settings: {} - certs: - #@ if/end isClusterPackageExplicitDisabled("certs"): - #@overlay/replace - settings: {} - kyverno: - #@ if/end isClusterPackageExplicitDisabled("kyverno"): - #@overlay/replace - settings: {} - kapp-controller: - #@ if/end isClusterPackageExplicitDisabled("kapp-controller"): - #@overlay/replace - settings: {} - #! educates: - #! #@ if/end isClusterPackageExplicitDisabled("educates"): - #! #@overlay/replace - #! settings: {} diff --git a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/infrastructure/generic/README.md b/carvel-packages/installer/bundle/config/ytt/_ytt_lib/infrastructure/generic/README.md deleted file mode 100644 index d439c6d28..000000000 --- a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/infrastructure/generic/README.md +++ /dev/null @@ -1,4 +0,0 @@ -# vcluster -By default, only kyverno and educates will be installed -We only allow to enabling/disabling kyverno -We copy all educates main config to the clusterPackage diff --git a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/infrastructure/generic/defaults.star b/carvel-packages/installer/bundle/config/ytt/_ytt_lib/infrastructure/generic/defaults.star deleted file mode 100644 index e0e228579..000000000 --- a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/infrastructure/generic/defaults.star +++ /dev/null @@ -1,6 +0,0 @@ -load("@ytt:data", "data") - -enabledByDefaultPackagesList = [ - "kyverno", - "educates" -] \ No newline at end of file diff --git a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/infrastructure/generic/educates.lib.yaml b/carvel-packages/installer/bundle/config/ytt/_ytt_lib/infrastructure/generic/educates.lib.yaml deleted file mode 100644 index 3513efbd6..000000000 --- a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/infrastructure/generic/educates.lib.yaml +++ /dev/null @@ -1,176 +0,0 @@ -#@ load("@ytt:data", "data") - -#@ def copy_all_educates_values(): - -#@ if/end hasattr(data.values, "sessionManager") and data.values.sessionManager != None: -sessionManager: - clusterAdmin: #@ data.values.sessionManager.clusterAdmin -#@ if/end hasattr(data.values, "imageRegistry") and data.values.imageRegistry != None: -imageRegistry: - #@ if/end hasattr(data.values.imageRegistry, "namespace") and data.values.imageRegistry.namespace != None: - namespace: #@ data.values.imageRegistry.namespace - #@ if/end hasattr(data.values.imageRegistry, "host") and data.values.imageRegistry.host != None: - host: #@ data.values.imageRegistry.host -#@ if/end hasattr(data.values, "version") and data.values.version != None: -version: #@ data.values.version -#@ if/end hasattr(data.values, "imageVersions") and data.values.imageVersions != None: -imageVersions: #@ data.values.imageVersions -#@ if/end hasattr(data.values, "clusterRuntime") and data.values.clusterRuntime != None: -clusterRuntime: #@ data.values.clusterRuntime -#@ if/end hasattr(data.values, "clusterIngress") and data.values.clusterIngress != None: -clusterIngress: - #@ if/end hasattr(data.values.clusterIngress, "domain") and data.values.clusterIngress.domain != None: - domain: #@ data.values.clusterIngress.domain - #@ if/end hasattr(data.values.clusterIngress, "class") and data.values.clusterIngress["class"] != None: - class: #@ data.values.clusterIngress["class"] - #@ if/end hasattr(data.values.clusterIngress, "protocol") and data.values.clusterIngress.protocol != None: - protocol: #@ data.values.clusterIngress.protocol - #@ if/end hasattr(data.values.clusterIngress, "tlsCertificate") and data.values.clusterIngress.tlsCertificate != None: - tlsCertificate: - #@ if/end hasattr(data.values.clusterIngress.tlsCertificate, "tls.crt") and data.values.clusterIngress.tlsCertificate["tls.crt"] != None: - tls.crt: #@ data.values.clusterIngress.tlsCertificate["tls.crt"] - #@ if/end hasattr(data.values.clusterIngress.tlsCertificate, "tls.key") and data.values.clusterIngress.tlsCertificate["tls.key"] != None: - tls.key: #@ data.values.clusterIngress.tlsCertificate["tls.key"] - #! TODO: Customize certs name reference in eks - #! projectcontour/wildcard - #@ if/end hasattr(data.values.clusterIngress, "tlsCertificateRef") and data.values.clusterIngress.tlsCertificateRef != None: - tlsCertificateRef: - namespace: #@ (hasattr(data.values.clusterIngress.tlsCertificateRef, "namespace") and data.values.clusterIngress.tlsCertificateRef.namespace != None) and data.values.clusterIngress.tlsCertificateRef.namespace or "projectcontour" - #@ if/end hasattr(data.values.clusterIngress.tlsCertificateRef, "name") and data.values.clusterIngress.tlsCertificateRef.name != None: - name: #@ data.values.clusterIngress.tlsCertificateRef.name - #@ if/end hasattr(data.values.clusterIngress, "caCertificate") and data.values.clusterIngress.caCertificate != None: - caCertificate: #@ data.values.clusterIngress.caCertificate - #@ if/end hasattr(data.values.clusterIngress, "caCertificateRef") and data.values.clusterIngress.caCertificateRef != None: - caCertificateRef: - #@ if/end hasattr(data.values.clusterIngress.caCertificateRef, "namespace") and data.values.clusterIngress.caCertificateRef.namespace != None: - namespace: #@ data.values.clusterIngress.caCertificateRef.namespace - #@ if/end hasattr(data.values.clusterIngress.caCertificateRef, "name") and data.values.clusterIngress.caCertificateRef.name != None: - name: #@ data.values.clusterIngress.caCertificateRef.name - #@ if/end hasattr(data.values.clusterIngress, "caNodeInjector") and data.values.clusterIngress.caNodeInjector != None: - caNodeInjector: #@ data.values.clusterIngress.caNodeInjector -#@ if/end hasattr(data.values, "sessionCookies") and data.values.sessionCookies != None: -sessionCookies: #@ data.values.sessionCookies -#@ if/end hasattr(data.values, "clusterStorage") and data.values.clusterStorage != None: -clusterStorage: - #@ if/end hasattr(data.values.clusterStorage, "class") and data.values.clusterStorage["class"] != None: - class: #@ data.values.clusterStorage["class"] - #@ if/end hasattr(data.values.clusterStorage, "user") and data.values.clusterStorage.user != None: - user: #@ data.values.clusterStorage.user - #@ if/end hasattr(data.values.clusterStorage, "group") and data.values.clusterStorage.group != None: - group: #@ data.values.clusterStorage.group -#@ if/end hasattr(data.values, "clusterSecrets") and data.values.clusterSecrets != None: -clusterSecrets: #@ data.values.clusterSecrets -#@ if/end hasattr(data.values, "clusterSecurity") and data.values.clusterSecurity != None: -clusterSecurity: #@ data.values.clusterSecurity -#@ if/end hasattr(data.values, "workshopSecurity") and data.values.workshopSecurity != None: -workshopSecurity: #@ data.values.workshopSecurity -#@ if/end hasattr(data.values, "trainingPortal") and data.values.trainingPortal != None: -trainingPortal: - #@ if/end hasattr(data.values.trainingPortal, "credentials") and data.values.trainingPortal.credentials != None: - credentials: - #@ if/end hasattr(data.values.trainingPortal.credentials, "admin") and data.values.trainingPortal.credentials.admin != None: - admin: - #@ if/end hasattr(data.values.trainingPortal.credentials.admin, "username") and data.values.trainingPortal.credentials.admin.username != None: - username: #@ data.values.trainingPortal.credentials.admin.username - #@ if/end hasattr(data.values.trainingPortal.credentials.admin, "password") and data.values.trainingPortal.credentials.admin.password != None: - password: #@ data.values.trainingPortal.credentials.admin.password - #@ if/end hasattr(data.values.trainingPortal.credentials, "robot") and data.values.trainingPortal.credentials.robot != None: - robot: - #@ if/end hasattr(data.values.trainingPortal.credentials.robot, "username") and data.values.trainingPortal.credentials.robot.username != None: - username: #@ data.values.trainingPortal.credentials.robot.username - #@ if/end hasattr(data.values.trainingPortal.credentials.robot, "password") and data.values.trainingPortal.credentials.robot.password != None: - password: #@ data.values.trainingPortal.credentials.robot.password - #@ if/end hasattr(data.values.trainingPortal, "clients") and data.values.trainingPortal.clients != None: - clients: - #@ if/end hasattr(data.values.trainingPortal.clients, "robot") and data.values.trainingPortal.clients.robot != None: - robot: - #@ if/end hasattr(data.values.trainingPortal.clients.robot, "id") and data.values.trainingPortal.clients.robot.id != None: - id: #@ data.values.trainingPortal.clients.robot.id - #@ if/end hasattr(data.values.trainingPortal.clients.robot, "secret") and data.values.trainingPortal.clients.robot.secret != None: - secret: #@ data.values.trainingPortal.clients.robot.secret -#@ if/end hasattr(data.values, "dockerDaemon") and data.values.dockerDaemon != None: -dockerDaemon: - #@ if/end hasattr(data.values.dockerDaemon, "networkMTU") and data.values.dockerDaemon.networkMTU != None: - networkMTU: #@ data.values.dockerDaemon.networkMTU - #@ if/end hasattr(data.values.dockerDaemon, "proxyCache") and data.values.dockerDaemon.proxyCache != None: - proxyCache: - #@ if/end hasattr(data.values.dockerDaemon.proxyCache, "remoteURL") and data.values.dockerDaemon.proxyCache.remoteURL != None: - remoteURL: #@ data.values.dockerDaemon.proxyCache.remoteURL - #@ if/end hasattr(data.values.dockerDaemon.proxyCache, "username") and data.values.dockerDaemon.proxyCache.username != None: - username: #@ data.values.dockerDaemon.proxyCache.username - #@ if/end hasattr(data.values.dockerDaemon.proxyCache, "password") and data.values.dockerDaemon.proxyCache.password != None: - password: #@ data.values.dockerDaemon.proxyCache.password -#@ if/end hasattr(data.values, "clusterNetwork") and data.values.clusterNetwork != None: -clusterNetwork: #@ data.values.clusterNetwork -#@ if/end hasattr(data.values, "workshopAnalytics") and data.values.workshopAnalytics != None: -workshopAnalytics: - #@ if/end hasattr(data.values.workshopAnalytics, "google") and data.values.workshopAnalytics.google != None: - google: - #@ if/end hasattr(data.values.workshopAnalytics.google, "trackingId") and data.values.workshopAnalytics.google.trackingId != None: - trackingId: #@ data.values.workshopAnalytics.google.trackingId - #@ if/end hasattr(data.values.workshopAnalytics, "clarity") and data.values.workshopAnalytics.clarity != None: - clarity: - #@ if/end hasattr(data.values.workshopAnalytics.clarity, "trackingId") and data.values.workshopAnalytics.clarity.trackingId != None: - trackingId: #@ data.values.workshopAnalytics.clarity.trackingId - #@ if/end hasattr(data.values.workshopAnalytics, "amplitude") and data.values.workshopAnalytics.amplitude != None: - amplitude: - #@ if/end hasattr(data.values.workshopAnalytics.amplitude, "trackingId") and data.values.workshopAnalytics.amplitude.trackingId != None: - trackingId: #@ data.values.workshopAnalytics.amplitude.trackingId - #@ if/end hasattr(data.values.workshopAnalytics, "webhook") and data.values.workshopAnalytics.webhook != None: - webhook: - #@ if/end hasattr(data.values.workshopAnalytics.webhook, "url") and data.values.workshopAnalytics.webhook.url != None: - url: #@ data.values.workshopAnalytics.webhook.url -#@ if/end hasattr(data.values, "websiteStyling") and data.values.websiteStyling != None: -websiteStyling: - #@ if/end hasattr(data.values.websiteStyling, "workshopDashboard") and data.values.websiteStyling.workshopDashboard != None: - workshopDashboard: - #@ if/end hasattr(data.values.websiteStyling.workshopDashboard, "html") and data.values.websiteStyling.workshopDashboard.html != None: - html: #@ data.values.websiteStyling.workshopDashboard.html - #@ if/end hasattr(data.values.websiteStyling.workshopDashboard, "script") and data.values.websiteStyling.workshopDashboard.script != None: - script: #@ data.values.websiteStyling.workshopDashboard.script - #@ if/end hasattr(data.values.websiteStyling.workshopDashboard, "style") and data.values.websiteStyling.workshopDashboard.style != None: - style: #@ data.values.websiteStyling.workshopDashboard.style - #@ if/end hasattr(data.values.websiteStyling, "workshopInstructions") and data.values.websiteStyling.workshopInstructions != None: - workshopInstructions: - #@ if/end hasattr(data.values.websiteStyling.workshopInstructions, "html") and data.values.websiteStyling.workshopInstructions.html != None: - html: #@ data.values.websiteStyling.workshopInstructions.html - #@ if/end hasattr(data.values.websiteStyling.workshopInstructions, "script") and data.values.websiteStyling.workshopInstructions.script != None: - script: #@ data.values.websiteStyling.workshopInstructions.script - #@ if/end hasattr(data.values.websiteStyling.workshopInstructions, "style") and data.values.websiteStyling.workshopInstructions.style != None: - style: #@ data.values.websiteStyling.workshopInstructions.style - #@ if/end hasattr(data.values.websiteStyling, "workshopStarted") and data.values.websiteStyling.workshopStarted != None: - workshopStarted: - #@ if/end hasattr(data.values.websiteStyling.workshopStarted, "html") and data.values.websiteStyling.workshopStarted.html != None: - html: #@ data.values.websiteStyling.workshopStarted.html - #@ if/end hasattr(data.values.websiteStyling, "workshopFinished") and data.values.websiteStyling.workshopFinished != None: - workshopFinished: - #@ if/end hasattr(data.values.websiteStyling.workshopFinished, "html") and data.values.websiteStyling.workshopFinished.html != None: - html: #@ data.values.websiteStyling.workshopFinished.html - #@ if/end hasattr(data.values.websiteStyling, "trainingPortal") and data.values.websiteStyling.trainingPortal != None: - trainingPortal: - #@ if/end hasattr(data.values.websiteStyling.trainingPortal, "html") and data.values.websiteStyling.trainingPortal.html != None: - html: #@ data.values.websiteStyling.trainingPortal.html - #@ if/end hasattr(data.values.websiteStyling.trainingPortal, "script") and data.values.websiteStyling.trainingPortal.script != None: - script: #@ data.values.websiteStyling.trainingPortal.script - #@ if/end hasattr(data.values.websiteStyling.trainingPortal, "style") and data.values.websiteStyling.trainingPortal.style != None: - style: #@ data.values.websiteStyling.trainingPortal.style - #@ if/end hasattr(data.values.websiteStyling, "defaultTheme") and data.values.websiteStyling.defaultTheme != None: - defaultTheme: #@ data.values.websiteStyling.defaultTheme - #@ if/end hasattr(data.values.websiteStyling, "themeDataRefs") and data.values.websiteStyling.themeDataRefs != None: - themeDataRefs: #@ data.values.websiteStyling.themeDataRefs - #@ if/end hasattr(data.values.websiteStyling, "frameAncestors") and data.values.websiteStyling.frameAncestors != None: - frameAncestors: #@ data.values.websiteStyling.frameAncestors -#@ if/end hasattr(data.values, "imagePuller") and data.values.imagePuller != None: -imagePuller: - enabled: #@ data.values.imagePuller.enabled - #@ if hasattr(data.values.imagePuller, "prePullImages") and data.values.imagePuller.prePullImages != None: - #@overlay/replace - prePullImages: #@ data.values.imagePuller.prePullImages - #@ end -#@ if/end hasattr(data.values, "lookupService") and data.values.lookupService != None: -lookupService: - #@ if/end hasattr(data.values.lookupService, "enabled") and data.values.lookupService.enabled != None: - enabled: #@ data.values.lookupService.enabled - #@ if/end hasattr(data.values.lookupService, "ingressPrefix") and data.values.lookupService.ingressPrefix != None: - ingressPrefix: #@ data.values.lookupService.ingressPrefix -#@ end diff --git a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/infrastructure/generic/functions.star b/carvel-packages/installer/bundle/config/ytt/_ytt_lib/infrastructure/generic/functions.star deleted file mode 100644 index 78ebaa3e7..000000000 --- a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/infrastructure/generic/functions.star +++ /dev/null @@ -1,35 +0,0 @@ -load("@ytt:data", "data") -load("defaults.star", "enabledByDefaultPackagesList") - -def isClusterPackageEnableByDefault(package): - return package in enabledByDefaultPackagesList -end - -def isClusterPackageEnabled(package): - if hasattr(data.values, "clusterPackages") and hasattr(data.values.clusterPackages, package) and hasattr(data.values.clusterPackages[package], "enabled"): - return data.values.clusterPackages[package].enabled - else: - return package in enabledByDefaultPackagesList - end -end - -def isClusterPackageExplicitDisabled(package): - return not isClusterPackageEnabled(package) -end - -def xgetattr(object, path, default=None): - def _lookup(object, key, default=None): - keys = key.split(".") - value = default - for key in keys: - value = getattr(object, key, None) - if value == None: - return default - end - object = value - end - return value - end - - return _lookup(object, path, default) -end \ No newline at end of file diff --git a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/infrastructure/gke/00-remove-toplevel-values.yaml b/carvel-packages/installer/bundle/config/ytt/_ytt_lib/infrastructure/gke/00-remove-toplevel-values.yaml deleted file mode 100644 index 931e60126..000000000 --- a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/infrastructure/gke/00-remove-toplevel-values.yaml +++ /dev/null @@ -1,50 +0,0 @@ -#@ load("@ytt:data", "data") -#@ load("@ytt:overlay", "overlay") - -#@overlay/remove -debug: - -#@overlay/remove -localKindCluster: -#@overlay/remove -localDNSResolver: - -#@overlay/remove -clusterInfrastructure: - -#@overlay/remove -sessionManager: -#@overlay/remove -imageRegistry: -#@overlay/remove -version: -#@overlay/remove -imageVersions: -#@overlay/remove -clusterRuntime: -#@overlay/remove -clusterIngress: -#@overlay/remove -sessionCookies: -#@overlay/remove -clusterStorage: -#@overlay/remove -clusterSecrets: -#@overlay/remove -clusterSecurity: -#@overlay/remove -workshopSecurity: -#@overlay/remove -trainingPortal: -#@overlay/remove -dockerDaemon: -#@overlay/remove -clusterNetwork: -#@overlay/remove -workshopAnalytics: -#@overlay/remove -websiteStyling: -#@overlay/remove -imagePuller: -#@overlay/remove -lookupService: diff --git a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/infrastructure/gke/10-default-settings-for-provider.yaml b/carvel-packages/installer/bundle/config/ytt/_ytt_lib/infrastructure/gke/10-default-settings-for-provider.yaml deleted file mode 100644 index 819bee1cb..000000000 --- a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/infrastructure/gke/10-default-settings-for-provider.yaml +++ /dev/null @@ -1,72 +0,0 @@ -#@ load("@ytt:data", "data") -#@ load("@ytt:overlay", "overlay") -#@ load("@ytt:assert", "assert") -#@ load("functions.star", "isClusterPackageEnableByDefault", "xgetattr") - -#@ (hasWorkloadIdentityExternalDns, _) = assert.try_to(lambda: len(data.values["clusterInfrastructure"]["gcp"]["workloadIdentity"]["external-dns"]) > 0) -#@ if hasWorkloadIdentityExternalDns: -#@ externalDnsWorkloadIdentity = data.values["clusterInfrastructure"]["gcp"]["workloadIdentity"]["external-dns"] -#@ else: -#@ fail("external-dns is enabled and can not be configured. Missing WorkloadIdentity") -#@ end - -#@ (hasWorkloadIdentityCertManager, _) = assert.try_to(lambda: len(data.values["clusterInfrastructure"]["gcp"]["workloadIdentity"]["cert-manager"]) > 0) -#@ if hasWorkloadIdentityCertManager: -#@ certManagerWorkloadIdentity = data.values["clusterInfrastructure"]["gcp"]["workloadIdentity"]["cert-manager"] -#@ else: -#@ fail("cert-manager is enabled and can not be configured. Missing workloadIdentity") -#@ end - -#@overlay/match-child-defaults missing_ok=True -#@overlay/replace -clusterPackages: - contour: - enabled: #@ isClusterPackageEnableByDefault("contour") - settings: - infraProvider: gcp - configFileContents: - defaultHttpVersions: - - "HTTP/1.1" - service: - type: LoadBalancer - externaldns: - domains: - - #@ data.values.clusterIngress.domain - cert-manager: - enabled: #@ isClusterPackageEnableByDefault("cert-manager") - settings: - serviceaccount: - annotations: - iam.gke.io/gcp-service-account: #@ certManagerWorkloadIdentity - external-dns: - enabled: #@ isClusterPackageEnableByDefault("external-dns") - settings: - infraProvider: gcp - serviceaccount: - annotations: - iam.gke.io/gcp-service-account: #@ externalDnsWorkloadIdentity - gcp: - args: - project: #@ data.values.clusterInfrastructure.gcp.project - domain_filter: #@ data.values.clusterInfrastructure.gcp.cloudDNS.zone if hasattr(data.values.clusterInfrastructure.gcp.cloudDNS, "zone") else data.values.clusterIngress.domain - txt_owner_id: #@ data.values.clusterIngress.domain - policy: sync - certs: - enabled: #@ isClusterPackageEnableByDefault("certs") - settings: - certProvider: acme-gcp - domains: - - #@ data.values.clusterIngress.domain - acme: - gcp: - project: #@ data.values.clusterInfrastructure.gcp.project - kyverno: - enabled: #@ isClusterPackageEnableByDefault("kyverno") - settings: {} - kapp-controller: - enabled: #@ isClusterPackageEnableByDefault("kapp-controller") - settings: {} - educates: - enabled: #@ isClusterPackageEnableByDefault("educates") - settings: #@ xgetattr(data.values, "clusterPackages.educates.settings") - diff --git a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/infrastructure/gke/12-overlays.yaml b/carvel-packages/installer/bundle/config/ytt/_ytt_lib/infrastructure/gke/12-overlays.yaml deleted file mode 100644 index 43314cca6..000000000 --- a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/infrastructure/gke/12-overlays.yaml +++ /dev/null @@ -1,10 +0,0 @@ -#@ load("@ytt:overlay", "overlay") - -#@overlay/match-child-defaults missing_ok=True -clusterPackages: - educates: - settings: - clusterIngress: - tlsCertificateRef: - namespace: projectcontour - name: educateswildcard diff --git a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/infrastructure/gke/50-packages-enablement.yaml b/carvel-packages/installer/bundle/config/ytt/_ytt_lib/infrastructure/gke/50-packages-enablement.yaml deleted file mode 100644 index 0a383ee3e..000000000 --- a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/infrastructure/gke/50-packages-enablement.yaml +++ /dev/null @@ -1,28 +0,0 @@ -#@ load("@ytt:data", "data") -#@ load("@ytt:overlay", "overlay") - -#! This enables packages based on the user input - -#@overlay/match-child-defaults missing_ok=True -clusterPackages: - contour: - #@ if/end hasattr(data.values, "clusterPackages") and hasattr(data.values.clusterPackages, "contour") and hasattr(data.values.clusterPackages.contour, "enabled"): - enabled: #@ data.values.clusterPackages.contour.enabled - cert-manager: - #@ if/end hasattr(data.values, "clusterPackages") and hasattr(data.values.clusterPackages, "cert-manager") and hasattr(data.values.clusterPackages["cert-manager"], "enabled"): - enabled: #@ data.values.clusterPackages["cert-manager"].enabled - external-dns: - #@ if/end hasattr(data.values, "clusterPackages") and hasattr(data.values.clusterPackages, "external-dns") and hasattr(data.values.clusterPackages["external-dns"], "enabled"): - enabled: #@ data.values.clusterPackages["external-dns"].enabled - certs: - #@ if/end hasattr(data.values, "clusterPackages") and hasattr(data.values.clusterPackages, "certs") and hasattr(data.values.clusterPackages.certs, "enabled"): - enabled: #@ data.values.clusterPackages.certs.enabled - kyverno: - #@ if/end hasattr(data.values, "clusterPackages") and hasattr(data.values.clusterPackages, "kyverno") and hasattr(data.values.clusterPackages.kyverno, "enabled"): - enabled: #@ data.values.clusterPackages.kyverno.enabled - kapp-controller: - #@ if/end hasattr(data.values, "clusterPackages") and hasattr(data.values.clusterPackages, "kapp-controller") and hasattr(data.values.clusterPackages["kapp-controller"], "enabled"): - enabled: #@ data.values.clusterPackages["kapp-controller"].enabled - educates: - #@ if/end hasattr(data.values, "clusterPackages") and hasattr(data.values.clusterPackages, "educates") and hasattr(data.values.clusterPackages.educates, "enabled"): - enabled: #@ data.values.clusterPackages.educates.enabled diff --git a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/infrastructure/gke/80-copy-educates-config.yaml b/carvel-packages/installer/bundle/config/ytt/_ytt_lib/infrastructure/gke/80-copy-educates-config.yaml deleted file mode 100644 index 1afda1acb..000000000 --- a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/infrastructure/gke/80-copy-educates-config.yaml +++ /dev/null @@ -1,10 +0,0 @@ -#@ load("@ytt:data", "data") -#@ load("@ytt:overlay", "overlay") -#@ load("educates.lib.yaml", "copy_all_educates_values") - -#! This copies user provided values for the custom infrastructure provider. - -#@overlay/match-child-defaults missing_ok=True -clusterPackages: - educates: - settings: #@ copy_all_educates_values() diff --git a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/infrastructure/gke/99-remove-settings-disabled.yaml b/carvel-packages/installer/bundle/config/ytt/_ytt_lib/infrastructure/gke/99-remove-settings-disabled.yaml deleted file mode 100644 index 25b8297c8..000000000 --- a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/infrastructure/gke/99-remove-settings-disabled.yaml +++ /dev/null @@ -1,36 +0,0 @@ -#@ load("@ytt:data", "data") -#@ load("@ytt:overlay", "overlay") -#@ load("functions.star", "isClusterPackageExplicitDisabled") - -#! This removes settings for disabled packages - -#@overlay/match-child-defaults missing_ok=True -clusterPackages: - contour: - #@ if/end isClusterPackageExplicitDisabled("contour"): - #@overlay/replace - settings: {} - cert-manager: - #@ if/end isClusterPackageExplicitDisabled("cert-manager"): - #@overlay/replace - settings: {} - external-dns: - #@ if/end isClusterPackageExplicitDisabled("external-dns"): - #@overlay/replace - settings: {} - certs: - #@ if/end isClusterPackageExplicitDisabled("certs"): - #@overlay/replace - settings: {} - kyverno: - #@ if/end isClusterPackageExplicitDisabled("kyverno"): - #@overlay/replace - settings: {} - kapp-controller: - #@ if/end isClusterPackageExplicitDisabled("kapp-controller"): - #@overlay/replace - settings: {} - #! educates: - #! #@ if/end isClusterPackageExplicitDisabled("educates"): - #! #@overlay/replace - #! settings: {} diff --git a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/infrastructure/gke/README.md b/carvel-packages/installer/bundle/config/ytt/_ytt_lib/infrastructure/gke/README.md deleted file mode 100644 index 33b182298..000000000 --- a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/infrastructure/gke/README.md +++ /dev/null @@ -1,3 +0,0 @@ -# GKE -For GKE we only allow the opinionated configuration for the packages, so, not settings are allowed -although enabling/disabling the package is allowed at users' risk. \ No newline at end of file diff --git a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/infrastructure/gke/defaults.star b/carvel-packages/installer/bundle/config/ytt/_ytt_lib/infrastructure/gke/defaults.star deleted file mode 100644 index 6b9484322..000000000 --- a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/infrastructure/gke/defaults.star +++ /dev/null @@ -1,10 +0,0 @@ -load("@ytt:data", "data") - -enabledByDefaultPackagesList = [ - "cert-manager", - "contour", - "external-dns", - "certs", - "kyverno", - "educates" -] \ No newline at end of file diff --git a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/infrastructure/gke/educates.lib.yaml b/carvel-packages/installer/bundle/config/ytt/_ytt_lib/infrastructure/gke/educates.lib.yaml deleted file mode 100644 index 8e2a52b45..000000000 --- a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/infrastructure/gke/educates.lib.yaml +++ /dev/null @@ -1,177 +0,0 @@ -#@ load("@ytt:data", "data") - -#! TODO: Customize certs name reference in eks -#@ def copy_all_educates_values(): - -#@ if/end hasattr(data.values, "sessionManager") and data.values.sessionManager != None: -sessionManager: - clusterAdmin: #@ data.values.sessionManager.clusterAdmin -#@ if/end hasattr(data.values, "imageRegistry") and data.values.imageRegistry != None: -imageRegistry: - #@ if/end hasattr(data.values.imageRegistry, "namespace") and data.values.imageRegistry.namespace != None: - namespace: #@ data.values.imageRegistry.namespace - #@ if/end hasattr(data.values.imageRegistry, "host") and data.values.imageRegistry.host != None: - host: #@ data.values.imageRegistry.host -#@ if/end hasattr(data.values, "version") and data.values.version != None: -version: #@ data.values.version -#@ if/end hasattr(data.values, "imageVersions") and data.values.imageVersions != None: -imageVersions: #@ data.values.imageVersions -#@ if/end hasattr(data.values, "clusterRuntime") and data.values.clusterRuntime != None: -clusterRuntime: #@ data.values.clusterRuntime -#@ if/end hasattr(data.values, "clusterIngress") and data.values.clusterIngress != None: -clusterIngress: - #@ if/end hasattr(data.values.clusterIngress, "domain") and data.values.clusterIngress.domain != None: - domain: #@ data.values.clusterIngress.domain - #@ if/end hasattr(data.values.clusterIngress, "class") and data.values.clusterIngress["class"] != None: - class: #@ data.values.clusterIngress["class"] - #@ if/end hasattr(data.values.clusterIngress, "protocol") and data.values.clusterIngress.protocol != None: - protocol: #@ data.values.clusterIngress.protocol - #@ if/end hasattr(data.values.clusterIngress, "tlsCertificate") and data.values.clusterIngress.tlsCertificate != None: - tlsCertificate: - #@ if/end hasattr(data.values.clusterIngress.tlsCertificate, "tls.crt") and data.values.clusterIngress.tlsCertificate["tls.crt"] != None: - tls.crt: #@ data.values.clusterIngress.tlsCertificate["tls.crt"] - #@ if/end hasattr(data.values.clusterIngress.tlsCertificate, "tls.key") and data.values.clusterIngress.tlsCertificate["tls.key"] != None: - tls.key: #@ data.values.clusterIngress.tlsCertificate["tls.key"] - #! TODO: Customize certs name reference in eks - #! projectcontour/wildcard - #@ if/end hasattr(data.values.clusterIngress, "tlsCertificateRef") and data.values.clusterIngress.tlsCertificateRef != None: - tlsCertificateRef: - namespace: #@ (hasattr(data.values.clusterIngress.tlsCertificateRef, "namespace") and data.values.clusterIngress.tlsCertificateRef.namespace != None) and data.values.clusterIngress.tlsCertificateRef.namespace or "projectcontour" - #@ if/end hasattr(data.values.clusterIngress.tlsCertificateRef, "name") and data.values.clusterIngress.tlsCertificateRef.name != None: - name: #@ data.values.clusterIngress.tlsCertificateRef.name - #@ if/end hasattr(data.values.clusterIngress, "caCertificate") and data.values.clusterIngress.caCertificate != None: - caCertificate: #@ data.values.clusterIngress.caCertificate - #@ if/end hasattr(data.values.clusterIngress, "caCertificateRef") and data.values.clusterIngress.caCertificateRef != None: - caCertificateRef: - #@ if/end hasattr(data.values.clusterIngress.caCertificateRef, "namespace") and data.values.clusterIngress.caCertificateRef.namespace != None: - namespace: #@ data.values.clusterIngress.caCertificateRef.namespace - #@ if/end hasattr(data.values.clusterIngress.caCertificateRef, "name") and data.values.clusterIngress.caCertificateRef.name != None: - name: #@ data.values.clusterIngress.caCertificateRef.name - #@ if/end hasattr(data.values.clusterIngress, "caNodeInjector") and data.values.clusterIngress.caNodeInjector != None: - caNodeInjector: #@ data.values.clusterIngress.caNodeInjector -#@ if/end hasattr(data.values, "sessionCookies") and data.values.sessionCookies != None: -sessionCookies: #@ data.values.sessionCookies -#@ if/end hasattr(data.values, "clusterStorage") and data.values.clusterStorage != None: -clusterStorage: - #@ if/end hasattr(data.values.clusterStorage, "class") and data.values.clusterStorage["class"] != None: - class: #@ data.values.clusterStorage["class"] - #@ if/end hasattr(data.values.clusterStorage, "user") and data.values.clusterStorage.user != None: - user: #@ data.values.clusterStorage.user - #@ if/end hasattr(data.values.clusterStorage, "group") and data.values.clusterStorage.group != None: - group: #@ data.values.clusterStorage.group -#@ if/end hasattr(data.values, "clusterSecrets") and data.values.clusterSecrets != None: -clusterSecrets: #@ data.values.clusterSecrets -#@ if/end hasattr(data.values, "clusterSecurity") and data.values.clusterSecurity != None: -clusterSecurity: #@ data.values.clusterSecurity -#@ if/end hasattr(data.values, "workshopSecurity") and data.values.workshopSecurity != None: -workshopSecurity: #@ data.values.workshopSecurity -#@ if/end hasattr(data.values, "trainingPortal") and data.values.trainingPortal != None: -trainingPortal: - #@ if/end hasattr(data.values.trainingPortal, "credentials") and data.values.trainingPortal.credentials != None: - credentials: - #@ if/end hasattr(data.values.trainingPortal.credentials, "admin") and data.values.trainingPortal.credentials.admin != None: - admin: - #@ if/end hasattr(data.values.trainingPortal.credentials.admin, "username") and data.values.trainingPortal.credentials.admin.username != None: - username: #@ data.values.trainingPortal.credentials.admin.username - #@ if/end hasattr(data.values.trainingPortal.credentials.admin, "password") and data.values.trainingPortal.credentials.admin.password != None: - password: #@ data.values.trainingPortal.credentials.admin.password - #@ if/end hasattr(data.values.trainingPortal.credentials, "robot") and data.values.trainingPortal.credentials.robot != None: - robot: - #@ if/end hasattr(data.values.trainingPortal.credentials.robot, "username") and data.values.trainingPortal.credentials.robot.username != None: - username: #@ data.values.trainingPortal.credentials.robot.username - #@ if/end hasattr(data.values.trainingPortal.credentials.robot, "password") and data.values.trainingPortal.credentials.robot.password != None: - password: #@ data.values.trainingPortal.credentials.robot.password - #@ if/end hasattr(data.values.trainingPortal, "clients") and data.values.trainingPortal.clients != None: - clients: - #@ if/end hasattr(data.values.trainingPortal.clients, "robot") and data.values.trainingPortal.clients.robot != None: - robot: - #@ if/end hasattr(data.values.trainingPortal.clients.robot, "id") and data.values.trainingPortal.clients.robot.id != None: - id: #@ data.values.trainingPortal.clients.robot.id - #@ if/end hasattr(data.values.trainingPortal.clients.robot, "secret") and data.values.trainingPortal.clients.robot.secret != None: - secret: #@ data.values.trainingPortal.clients.robot.secret -#@ if/end hasattr(data.values, "dockerDaemon") and data.values.dockerDaemon != None: -dockerDaemon: - #@ if/end hasattr(data.values.dockerDaemon, "networkMTU") and data.values.dockerDaemon.networkMTU != None: - networkMTU: #@ data.values.dockerDaemon.networkMTU - #@ if/end hasattr(data.values.dockerDaemon, "proxyCache") and data.values.dockerDaemon.proxyCache != None: - proxyCache: - #@ if/end hasattr(data.values.dockerDaemon.proxyCache, "remoteURL") and data.values.dockerDaemon.proxyCache.remoteURL != None: - remoteURL: #@ data.values.dockerDaemon.proxyCache.remoteURL - #@ if/end hasattr(data.values.dockerDaemon.proxyCache, "username") and data.values.dockerDaemon.proxyCache.username != None: - username: #@ data.values.dockerDaemon.proxyCache.username - #@ if/end hasattr(data.values.dockerDaemon.proxyCache, "password") and data.values.dockerDaemon.proxyCache.password != None: - password: #@ data.values.dockerDaemon.proxyCache.password -#@ if/end hasattr(data.values, "clusterNetwork") and data.values.clusterNetwork != None: -clusterNetwork: #@ data.values.clusterNetwork -#@ if/end hasattr(data.values, "workshopAnalytics") and data.values.workshopAnalytics != None: -workshopAnalytics: - #@ if/end hasattr(data.values.workshopAnalytics, "google") and data.values.workshopAnalytics.google != None: - google: - #@ if/end hasattr(data.values.workshopAnalytics.google, "trackingId") and data.values.workshopAnalytics.google.trackingId != None: - trackingId: #@ data.values.workshopAnalytics.google.trackingId - #@ if/end hasattr(data.values.workshopAnalytics, "clarity") and data.values.workshopAnalytics.clarity != None: - clarity: - #@ if/end hasattr(data.values.workshopAnalytics.clarity, "trackingId") and data.values.workshopAnalytics.clarity.trackingId != None: - trackingId: #@ data.values.workshopAnalytics.clarity.trackingId - #@ if/end hasattr(data.values.workshopAnalytics, "amplitude") and data.values.workshopAnalytics.amplitude != None: - amplitude: - #@ if/end hasattr(data.values.workshopAnalytics.amplitude, "trackingId") and data.values.workshopAnalytics.amplitude.trackingId != None: - trackingId: #@ data.values.workshopAnalytics.amplitude.trackingId - #@ if/end hasattr(data.values.workshopAnalytics, "webhook") and data.values.workshopAnalytics.webhook != None: - webhook: - #@ if/end hasattr(data.values.workshopAnalytics.webhook, "url") and data.values.workshopAnalytics.webhook.url != None: - url: #@ data.values.workshopAnalytics.webhook.url -#@ if/end hasattr(data.values, "websiteStyling") and data.values.websiteStyling != None: -websiteStyling: - #@ if/end hasattr(data.values.websiteStyling, "workshopDashboard") and data.values.websiteStyling.workshopDashboard != None: - workshopDashboard: - #@ if/end hasattr(data.values.websiteStyling.workshopDashboard, "html") and data.values.websiteStyling.workshopDashboard.html != None: - html: #@ data.values.websiteStyling.workshopDashboard.html - #@ if/end hasattr(data.values.websiteStyling.workshopDashboard, "script") and data.values.websiteStyling.workshopDashboard.script != None: - script: #@ data.values.websiteStyling.workshopDashboard.script - #@ if/end hasattr(data.values.websiteStyling.workshopDashboard, "style") and data.values.websiteStyling.workshopDashboard.style != None: - style: #@ data.values.websiteStyling.workshopDashboard.style - #@ if/end hasattr(data.values.websiteStyling, "workshopInstructions") and data.values.websiteStyling.workshopInstructions != None: - workshopInstructions: - #@ if/end hasattr(data.values.websiteStyling.workshopInstructions, "html") and data.values.websiteStyling.workshopInstructions.html != None: - html: #@ data.values.websiteStyling.workshopInstructions.html - #@ if/end hasattr(data.values.websiteStyling.workshopInstructions, "script") and data.values.websiteStyling.workshopInstructions.script != None: - script: #@ data.values.websiteStyling.workshopInstructions.script - #@ if/end hasattr(data.values.websiteStyling.workshopInstructions, "style") and data.values.websiteStyling.workshopInstructions.style != None: - style: #@ data.values.websiteStyling.workshopInstructions.style - #@ if/end hasattr(data.values.websiteStyling, "workshopStarted") and data.values.websiteStyling.workshopStarted != None: - workshopStarted: - #@ if/end hasattr(data.values.websiteStyling.workshopStarted, "html") and data.values.websiteStyling.workshopStarted.html != None: - html: #@ data.values.websiteStyling.workshopStarted.html - #@ if/end hasattr(data.values.websiteStyling, "workshopFinished") and data.values.websiteStyling.workshopFinished != None: - workshopFinished: - #@ if/end hasattr(data.values.websiteStyling.workshopFinished, "html") and data.values.websiteStyling.workshopFinished.html != None: - html: #@ data.values.websiteStyling.workshopFinished.html - #@ if/end hasattr(data.values.websiteStyling, "trainingPortal") and data.values.websiteStyling.trainingPortal != None: - trainingPortal: - #@ if/end hasattr(data.values.websiteStyling.trainingPortal, "html") and data.values.websiteStyling.trainingPortal.html != None: - html: #@ data.values.websiteStyling.trainingPortal.html - #@ if/end hasattr(data.values.websiteStyling.trainingPortal, "script") and data.values.websiteStyling.trainingPortal.script != None: - script: #@ data.values.websiteStyling.trainingPortal.script - #@ if/end hasattr(data.values.websiteStyling.trainingPortal, "style") and data.values.websiteStyling.trainingPortal.style != None: - style: #@ data.values.websiteStyling.trainingPortal.style - #@ if/end hasattr(data.values.websiteStyling, "defaultTheme") and data.values.websiteStyling.defaultTheme != None: - defaultTheme: #@ data.values.websiteStyling.defaultTheme - #@ if/end hasattr(data.values.websiteStyling, "themeDataRefs") and data.values.websiteStyling.themeDataRefs != None: - themeDataRefs: #@ data.values.websiteStyling.themeDataRefs - #@ if/end hasattr(data.values.websiteStyling, "frameAncestors") and data.values.websiteStyling.frameAncestors != None: - frameAncestors: #@ data.values.websiteStyling.frameAncestors -#@ if/end hasattr(data.values, "imagePuller") and data.values.imagePuller != None: -imagePuller: - enabled: #@ data.values.imagePuller.enabled - #@ if hasattr(data.values.imagePuller, "prePullImages") and data.values.imagePuller.prePullImages != None: - #@overlay/replace - prePullImages: #@ data.values.imagePuller.prePullImages - #@ end -#@ if/end hasattr(data.values, "lookupService") and data.values.lookupService != None: -lookupService: - #@ if/end hasattr(data.values.lookupService, "enabled") and data.values.lookupService.enabled != None: - enabled: #@ data.values.lookupService.enabled - #@ if/end hasattr(data.values.lookupService, "ingressPrefix") and data.values.lookupService.ingressPrefix != None: - ingressPrefix: #@ data.values.lookupService.ingressPrefix -#@ end diff --git a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/infrastructure/gke/functions.star b/carvel-packages/installer/bundle/config/ytt/_ytt_lib/infrastructure/gke/functions.star deleted file mode 100644 index 2c5b8bf26..000000000 --- a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/infrastructure/gke/functions.star +++ /dev/null @@ -1,35 +0,0 @@ -load("@ytt:data", "data") -load("defaults.star", "enabledByDefaultPackagesList") - -def isClusterPackageEnableByDefault(package): - return package in enabledByDefaultPackagesList -end - -def isClusterPackageEnabled(package): - if hasattr(data.values, "clusterPackages") and hasattr(data.values.clusterPackages, package) and hasattr(data.values.clusterPackages[package], "enabled"): - return data.values.clusterPackages[package].enabled - else: - return package in enabledByDefaultPackagesList - end -end - -def isClusterPackageExplicitDisabled(package): - return not isClusterPackageEnabled(package) -end - -def xgetattr(object, path, default=None): - def _lookup(object, key, default=None): - keys = key.split(".") - value = default - for key in keys: - value = getattr(object, key, None) - if value == None: - return default - end - object = value - end - return value - end - - return _lookup(object, path, default) -end diff --git a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/infrastructure/kind/00-remove-toplevel-values.yaml b/carvel-packages/installer/bundle/config/ytt/_ytt_lib/infrastructure/kind/00-remove-toplevel-values.yaml deleted file mode 100644 index 931e60126..000000000 --- a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/infrastructure/kind/00-remove-toplevel-values.yaml +++ /dev/null @@ -1,50 +0,0 @@ -#@ load("@ytt:data", "data") -#@ load("@ytt:overlay", "overlay") - -#@overlay/remove -debug: - -#@overlay/remove -localKindCluster: -#@overlay/remove -localDNSResolver: - -#@overlay/remove -clusterInfrastructure: - -#@overlay/remove -sessionManager: -#@overlay/remove -imageRegistry: -#@overlay/remove -version: -#@overlay/remove -imageVersions: -#@overlay/remove -clusterRuntime: -#@overlay/remove -clusterIngress: -#@overlay/remove -sessionCookies: -#@overlay/remove -clusterStorage: -#@overlay/remove -clusterSecrets: -#@overlay/remove -clusterSecurity: -#@overlay/remove -workshopSecurity: -#@overlay/remove -trainingPortal: -#@overlay/remove -dockerDaemon: -#@overlay/remove -clusterNetwork: -#@overlay/remove -workshopAnalytics: -#@overlay/remove -websiteStyling: -#@overlay/remove -imagePuller: -#@overlay/remove -lookupService: diff --git a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/infrastructure/kind/10-default-settings-for-provider.yaml b/carvel-packages/installer/bundle/config/ytt/_ytt_lib/infrastructure/kind/10-default-settings-for-provider.yaml deleted file mode 100644 index 0c03d83c2..000000000 --- a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/infrastructure/kind/10-default-settings-for-provider.yaml +++ /dev/null @@ -1,41 +0,0 @@ -#@ load("@ytt:data", "data") -#@ load("@ytt:overlay", "overlay") -#@ load("functions.star", "xgetattr", "isClusterPackageEnableByDefault") -#@ load("educates.lib.yaml", "copy_all_educates_values") - -#! This file contains default values for the custom infrastructure provider. -#! These are the values that will be set if not overridden by the user. - -#@overlay/match-child-defaults missing_ok=True -#@overlay/replace -clusterPackages: - contour: - enabled: #@ isClusterPackageEnableByDefault("contour") - settings: - infraProvider: kind - contour: - replicas: 1 - configFileContents: - defaultHttpVersions: - - "HTTP/1.1" - service: - type: ClusterIP - useHostPorts: true - cert-manager: - enabled: #@ isClusterPackageEnableByDefault("cert-manager") - settings: {} - external-dns: - enabled: #@ isClusterPackageEnableByDefault("external-dns") - settings: {} - certs: - enabled: #@ isClusterPackageEnableByDefault("certs") - settings: {} - kyverno: - enabled: #@ isClusterPackageEnableByDefault("kyverno") - settings: {} - kapp-controller: - enabled: #@ isClusterPackageEnableByDefault("kapp-controller") - settings: {} - educates: - enabled: #@ isClusterPackageEnableByDefault("educates") - settings: #@ xgetattr(data.values, "clusterPackages.educates.settings") diff --git a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/infrastructure/kind/50-packages-enablement.yaml b/carvel-packages/installer/bundle/config/ytt/_ytt_lib/infrastructure/kind/50-packages-enablement.yaml deleted file mode 100644 index 0a383ee3e..000000000 --- a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/infrastructure/kind/50-packages-enablement.yaml +++ /dev/null @@ -1,28 +0,0 @@ -#@ load("@ytt:data", "data") -#@ load("@ytt:overlay", "overlay") - -#! This enables packages based on the user input - -#@overlay/match-child-defaults missing_ok=True -clusterPackages: - contour: - #@ if/end hasattr(data.values, "clusterPackages") and hasattr(data.values.clusterPackages, "contour") and hasattr(data.values.clusterPackages.contour, "enabled"): - enabled: #@ data.values.clusterPackages.contour.enabled - cert-manager: - #@ if/end hasattr(data.values, "clusterPackages") and hasattr(data.values.clusterPackages, "cert-manager") and hasattr(data.values.clusterPackages["cert-manager"], "enabled"): - enabled: #@ data.values.clusterPackages["cert-manager"].enabled - external-dns: - #@ if/end hasattr(data.values, "clusterPackages") and hasattr(data.values.clusterPackages, "external-dns") and hasattr(data.values.clusterPackages["external-dns"], "enabled"): - enabled: #@ data.values.clusterPackages["external-dns"].enabled - certs: - #@ if/end hasattr(data.values, "clusterPackages") and hasattr(data.values.clusterPackages, "certs") and hasattr(data.values.clusterPackages.certs, "enabled"): - enabled: #@ data.values.clusterPackages.certs.enabled - kyverno: - #@ if/end hasattr(data.values, "clusterPackages") and hasattr(data.values.clusterPackages, "kyverno") and hasattr(data.values.clusterPackages.kyverno, "enabled"): - enabled: #@ data.values.clusterPackages.kyverno.enabled - kapp-controller: - #@ if/end hasattr(data.values, "clusterPackages") and hasattr(data.values.clusterPackages, "kapp-controller") and hasattr(data.values.clusterPackages["kapp-controller"], "enabled"): - enabled: #@ data.values.clusterPackages["kapp-controller"].enabled - educates: - #@ if/end hasattr(data.values, "clusterPackages") and hasattr(data.values.clusterPackages, "educates") and hasattr(data.values.clusterPackages.educates, "enabled"): - enabled: #@ data.values.clusterPackages.educates.enabled diff --git a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/infrastructure/kind/80-remove-settings-disabled.yaml b/carvel-packages/installer/bundle/config/ytt/_ytt_lib/infrastructure/kind/80-remove-settings-disabled.yaml deleted file mode 100644 index c140d8f3b..000000000 --- a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/infrastructure/kind/80-remove-settings-disabled.yaml +++ /dev/null @@ -1,32 +0,0 @@ -#@ load("@ytt:data", "data") -#@ load("@ytt:overlay", "overlay") -#@ load("functions.star", "isClusterPackageExplicitDisabled") - -#! This removes settings for disabled packages - -#@overlay/match-child-defaults missing_ok=True -clusterPackages: - contour: - #@ if/end isClusterPackageExplicitDisabled("contour"): - #@overlay/replace - settings: {} - cert-manager: - #@ if/end isClusterPackageExplicitDisabled("cert-manager"): - #@overlay/replace - settings: {} - external-dns: - #@ if/end isClusterPackageExplicitDisabled("external-dns"): - #@overlay/replace - settings: {} - certs: - #@ if/end isClusterPackageExplicitDisabled("certs"): - #@overlay/replace - settings: {} - kyverno: - #@ if/end isClusterPackageExplicitDisabled("kyverno"): - #@overlay/replace - settings: {} - kapp-controller: - #@ if/end isClusterPackageExplicitDisabled("kapp-controller"): - #@overlay/replace - settings: {} diff --git a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/infrastructure/kind/89-copy-educates-config.yaml b/carvel-packages/installer/bundle/config/ytt/_ytt_lib/infrastructure/kind/89-copy-educates-config.yaml deleted file mode 100644 index 1afda1acb..000000000 --- a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/infrastructure/kind/89-copy-educates-config.yaml +++ /dev/null @@ -1,10 +0,0 @@ -#@ load("@ytt:data", "data") -#@ load("@ytt:overlay", "overlay") -#@ load("educates.lib.yaml", "copy_all_educates_values") - -#! This copies user provided values for the custom infrastructure provider. - -#@overlay/match-child-defaults missing_ok=True -clusterPackages: - educates: - settings: #@ copy_all_educates_values() diff --git a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/infrastructure/kind/90-overlays.yaml b/carvel-packages/installer/bundle/config/ytt/_ytt_lib/infrastructure/kind/90-overlays.yaml deleted file mode 100644 index 68ef912cb..000000000 --- a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/infrastructure/kind/90-overlays.yaml +++ /dev/null @@ -1,35 +0,0 @@ -#@ load("@ytt:data", "data") -#@ load("@ytt:overlay", "overlay") -#@ load("@ytt:assert", "assert") -#@ load("/functions.star", "isGlobalCaCertificateRefEnabled") - -#@overlay/match-child-defaults missing_ok=True -clusterPackages: -#@ if isGlobalCaCertificateRefEnabled(): - cert-manager: - enabled: true - settings: - clusterResourceNamespace: #@ data.values.clusterInfrastructure.caCertificateRef.namespace - certs: - enabled: true - settings: - domains: - - #@ data.values.clusterIngress.domain - certProvider: "local" #! TODO: This can be provided (provides the wildcard) or local (for rootCA) - local: - caCertificateRef: - name: #@ data.values.clusterInfrastructure.caCertificateRef.name - namespace: #@ data.values.clusterInfrastructure.caCertificateRef.namespace - wildcardCertificateNamespace: #@ data.values.clusterInfrastructure.caCertificateRef.namespace - certmanagerClusterResourceNamespace: #@ data.values.clusterInfrastructure.caCertificateRef.namespace - educates: - enabled: true - settings: - clusterIngress: - caCertificateRef: - namespace: #@ data.values.clusterInfrastructure.caCertificateRef.namespace - name: #@ data.values.clusterInfrastructure.caCertificateRef.name - #! NOTE: Nodes Operating System must be based of Debian in order to allow NodeInjector - caNodeInjector: - enabled: true -#@ end diff --git a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/infrastructure/kind/95-remove-educates-settings-disabled.yaml b/carvel-packages/installer/bundle/config/ytt/_ytt_lib/infrastructure/kind/95-remove-educates-settings-disabled.yaml deleted file mode 100644 index 90408bef5..000000000 --- a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/infrastructure/kind/95-remove-educates-settings-disabled.yaml +++ /dev/null @@ -1,15 +0,0 @@ -#@ load("@ytt:data", "data") -#@ load("@ytt:overlay", "overlay") -#@ load("functions.star", "isClusterPackageExplicitDisabled") - -#! This removes settings for disabled packages - -#@overlay/match-child-defaults missing_ok=True -clusterPackages: - educates: - #@ if isClusterPackageExplicitDisabled("educates"): - #@overlay/replace - enabled: false - #@overlay/replace - settings: {} - #@ end \ No newline at end of file diff --git a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/infrastructure/kind/README.md b/carvel-packages/installer/bundle/config/ytt/_ytt_lib/infrastructure/kind/README.md deleted file mode 100644 index 0efd3905c..000000000 --- a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/infrastructure/kind/README.md +++ /dev/null @@ -1,3 +0,0 @@ -# Kind -For Kind we only allow the opinionated configuration for the packages, so, not settings are allowed -although enabling/disabling the package is allowed at users' risk. \ No newline at end of file diff --git a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/infrastructure/kind/defaults.star b/carvel-packages/installer/bundle/config/ytt/_ytt_lib/infrastructure/kind/defaults.star deleted file mode 100644 index 84dc02e44..000000000 --- a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/infrastructure/kind/defaults.star +++ /dev/null @@ -1,7 +0,0 @@ -load("@ytt:data", "data") - -enabledByDefaultPackagesList = [ - "contour", - "kyverno", - "educates" -] \ No newline at end of file diff --git a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/infrastructure/kind/educates.lib.yaml b/carvel-packages/installer/bundle/config/ytt/_ytt_lib/infrastructure/kind/educates.lib.yaml deleted file mode 100644 index f5b882a80..000000000 --- a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/infrastructure/kind/educates.lib.yaml +++ /dev/null @@ -1,175 +0,0 @@ -#@ load("@ytt:data", "data") - -#@ def copy_all_educates_values(): - -#@ if/end hasattr(data.values, "sessionManager") and data.values.sessionManager != None: -sessionManager: - clusterAdmin: #@ data.values.sessionManager.clusterAdmin -#@ if/end hasattr(data.values, "imageRegistry") and data.values.imageRegistry != None: -imageRegistry: - #@ if/end hasattr(data.values.imageRegistry, "namespace") and data.values.imageRegistry.namespace != None: - namespace: #@ data.values.imageRegistry.namespace - #@ if/end hasattr(data.values.imageRegistry, "host") and data.values.imageRegistry.host != None: - host: #@ data.values.imageRegistry.host -#@ if/end hasattr(data.values, "version") and data.values.version != None: -version: #@ data.values.version -#@ if/end hasattr(data.values, "imageVersions") and data.values.imageVersions != None: -imageVersions: #@ data.values.imageVersions -#@ if/end hasattr(data.values, "clusterRuntime") and data.values.clusterRuntime != None: -clusterRuntime: #@ data.values.clusterRuntime -#@ if/end hasattr(data.values, "clusterIngress") and data.values.clusterIngress != None: -clusterIngress: - #@ if/end hasattr(data.values.clusterIngress, "domain") and data.values.clusterIngress.domain != None: - domain: #@ data.values.clusterIngress.domain - #@ if/end hasattr(data.values.clusterIngress, "class") and data.values.clusterIngress["class"] != None: - class: #@ data.values.clusterIngress["class"] - #@ if/end hasattr(data.values.clusterIngress, "protocol") and data.values.clusterIngress.protocol != None: - protocol: #@ data.values.clusterIngress.protocol - #@ if/end hasattr(data.values.clusterIngress, "tlsCertificate") and data.values.clusterIngress.tlsCertificate != None: - tlsCertificate: - #@ if/end hasattr(data.values.clusterIngress.tlsCertificate, "tls.crt") and data.values.clusterIngress.tlsCertificate["tls.crt"] != None: - tls.crt: #@ data.values.clusterIngress.tlsCertificate["tls.crt"] - #@ if/end hasattr(data.values.clusterIngress.tlsCertificate, "tls.key") and data.values.clusterIngress.tlsCertificate["tls.key"] != None: - tls.key: #@ data.values.clusterIngress.tlsCertificate["tls.key"] - #@ if/end hasattr(data.values.clusterIngress, "tlsCertificateRef") and data.values.clusterIngress.tlsCertificateRef != None: - tlsCertificateRef: - #@ if/end hasattr(data.values.clusterIngress.tlsCertificateRef, "namespace") and data.values.clusterIngress.tlsCertificateRef.namespace != None: - namespace: #@ data.values.clusterIngress.tlsCertificateRef.namespace - #@ if/end hasattr(data.values.clusterIngress.tlsCertificateRef, "name") and data.values.clusterIngress.tlsCertificateRef.name != None: - name: #@ data.values.clusterIngress.tlsCertificateRef.name - #@ if/end hasattr(data.values.clusterIngress, "caCertificate") and data.values.clusterIngress.caCertificate != None: - caCertificate: #@ data.values.clusterIngress.caCertificate - #@ if/end hasattr(data.values.clusterIngress, "caCertificateRef") and data.values.clusterIngress.caCertificateRef != None: - caCertificateRef: - #@ if/end hasattr(data.values.clusterIngress.caCertificateRef, "namespace") and data.values.clusterIngress.caCertificateRef.namespace != None: - namespace: #@ data.values.clusterIngress.caCertificateRef.namespace - #@ if/end hasattr(data.values.clusterIngress.caCertificateRef, "name") and data.values.clusterIngress.caCertificateRef.name != None: - name: #@ data.values.clusterIngress.caCertificateRef.name - #@ if/end hasattr(data.values.clusterIngress, "caNodeInjector") and data.values.clusterIngress.caNodeInjector != None: - caNodeInjector: #@ data.values.clusterIngress.caNodeInjector -#@ if/end hasattr(data.values, "sessionCookies") and data.values.sessionCookies != None: -sessionCookies: #@ data.values.sessionCookies -#@ if/end hasattr(data.values, "clusterStorage") and data.values.clusterStorage != None: -clusterStorage: - #@ if/end hasattr(data.values.clusterStorage, "class") and data.values.clusterStorage["class"] != None: - class: #@ data.values.clusterStorage["class"] - #@ if/end hasattr(data.values.clusterStorage, "user") and data.values.clusterStorage.user != None: - user: #@ data.values.clusterStorage.user - #@ if/end hasattr(data.values.clusterStorage, "group") and data.values.clusterStorage.group != None: - group: #@ data.values.clusterStorage.group -#@ if/end hasattr(data.values, "clusterSecrets") and data.values.clusterSecrets != None: -clusterSecrets: #@ data.values.clusterSecrets -#@ if/end hasattr(data.values, "clusterSecurity") and data.values.clusterSecurity != None: -clusterSecurity: #@ data.values.clusterSecurity -#@ if/end hasattr(data.values, "workshopSecurity") and data.values.workshopSecurity != None: -workshopSecurity: #@ data.values.workshopSecurity -#@ if/end hasattr(data.values, "trainingPortal") and data.values.trainingPortal != None: -trainingPortal: - #@ if/end hasattr(data.values.trainingPortal, "credentials") and data.values.trainingPortal.credentials != None: - credentials: - #@ if/end hasattr(data.values.trainingPortal.credentials, "admin") and data.values.trainingPortal.credentials.admin != None: - admin: - #@ if/end hasattr(data.values.trainingPortal.credentials.admin, "username") and data.values.trainingPortal.credentials.admin.username != None: - username: #@ data.values.trainingPortal.credentials.admin.username - #@ if/end hasattr(data.values.trainingPortal.credentials.admin, "password") and data.values.trainingPortal.credentials.admin.password != None: - password: #@ data.values.trainingPortal.credentials.admin.password - #@ if/end hasattr(data.values.trainingPortal.credentials, "robot") and data.values.trainingPortal.credentials.robot != None: - robot: - #@ if/end hasattr(data.values.trainingPortal.credentials.robot, "username") and data.values.trainingPortal.credentials.robot.username != None: - username: #@ data.values.trainingPortal.credentials.robot.username - #@ if/end hasattr(data.values.trainingPortal.credentials.robot, "password") and data.values.trainingPortal.credentials.robot.password != None: - password: #@ data.values.trainingPortal.credentials.robot.password - #@ if/end hasattr(data.values.trainingPortal, "clients") and data.values.trainingPortal.clients != None: - clients: - #@ if/end hasattr(data.values.trainingPortal.clients, "robot") and data.values.trainingPortal.clients.robot != None: - robot: - #@ if/end hasattr(data.values.trainingPortal.clients.robot, "id") and data.values.trainingPortal.clients.robot.id != None: - id: #@ data.values.trainingPortal.clients.robot.id - #@ if/end hasattr(data.values.trainingPortal.clients.robot, "secret") and data.values.trainingPortal.clients.robot.secret != None: - secret: #@ data.values.trainingPortal.clients.robot.secret -#@ if/end hasattr(data.values, "dockerDaemon") and data.values.dockerDaemon != None: -dockerDaemon: - #@ if/end hasattr(data.values.dockerDaemon, "networkMTU") and data.values.dockerDaemon.networkMTU != None: - networkMTU: #@ data.values.dockerDaemon.networkMTU - #@ if/end hasattr(data.values.dockerDaemon, "proxyCache") and data.values.dockerDaemon.proxyCache != None: - proxyCache: - #@ if/end hasattr(data.values.dockerDaemon.proxyCache, "remoteURL") and data.values.dockerDaemon.proxyCache.remoteURL != None: - remoteURL: #@ data.values.dockerDaemon.proxyCache.remoteURL - #@ if/end hasattr(data.values.dockerDaemon.proxyCache, "username") and data.values.dockerDaemon.proxyCache.username != None: - username: #@ data.values.dockerDaemon.proxyCache.username - #@ if/end hasattr(data.values.dockerDaemon.proxyCache, "password") and data.values.dockerDaemon.proxyCache.password != None: - password: #@ data.values.dockerDaemon.proxyCache.password -#@ if/end hasattr(data.values, "clusterNetwork") and data.values.clusterNetwork != None: -clusterNetwork: #@ data.values.clusterNetwork -#@ if/end hasattr(data.values, "workshopAnalytics") and data.values.workshopAnalytics != None: -workshopAnalytics: - #@ if/end hasattr(data.values.workshopAnalytics, "google") and data.values.workshopAnalytics.google != None: - google: - #@ if/end hasattr(data.values.workshopAnalytics.google, "trackingId") and data.values.workshopAnalytics.google.trackingId != None: - trackingId: #@ data.values.workshopAnalytics.google.trackingId - #@ if/end hasattr(data.values.workshopAnalytics, "clarity") and data.values.workshopAnalytics.clarity != None: - clarity: - #@ if/end hasattr(data.values.workshopAnalytics.clarity, "trackingId") and data.values.workshopAnalytics.clarity.trackingId != None: - trackingId: #@ data.values.workshopAnalytics.clarity.trackingId - #@ if/end hasattr(data.values.workshopAnalytics, "amplitude") and data.values.workshopAnalytics.amplitude != None: - amplitude: - #@ if/end hasattr(data.values.workshopAnalytics.amplitude, "trackingId") and data.values.workshopAnalytics.amplitude.trackingId != None: - trackingId: #@ data.values.workshopAnalytics.amplitude.trackingId - #@ if/end hasattr(data.values.workshopAnalytics, "webhook") and data.values.workshopAnalytics.webhook != None: - webhook: - #@ if/end hasattr(data.values.workshopAnalytics.webhook, "url") and data.values.workshopAnalytics.webhook.url != None: - url: #@ data.values.workshopAnalytics.webhook.url -#@ if/end hasattr(data.values, "websiteStyling") and data.values.websiteStyling != None: -websiteStyling: - #@ if/end hasattr(data.values.websiteStyling, "workshopDashboard") and data.values.websiteStyling.workshopDashboard != None: - workshopDashboard: - #@ if/end hasattr(data.values.websiteStyling.workshopDashboard, "html") and data.values.websiteStyling.workshopDashboard.html != None: - html: #@ data.values.websiteStyling.workshopDashboard.html - #@ if/end hasattr(data.values.websiteStyling.workshopDashboard, "script") and data.values.websiteStyling.workshopDashboard.script != None: - script: #@ data.values.websiteStyling.workshopDashboard.script - #@ if/end hasattr(data.values.websiteStyling.workshopDashboard, "style") and data.values.websiteStyling.workshopDashboard.style != None: - style: #@ data.values.websiteStyling.workshopDashboard.style - #@ if/end hasattr(data.values.websiteStyling, "workshopInstructions") and data.values.websiteStyling.workshopInstructions != None: - workshopInstructions: - #@ if/end hasattr(data.values.websiteStyling.workshopInstructions, "html") and data.values.websiteStyling.workshopInstructions.html != None: - html: #@ data.values.websiteStyling.workshopInstructions.html - #@ if/end hasattr(data.values.websiteStyling.workshopInstructions, "script") and data.values.websiteStyling.workshopInstructions.script != None: - script: #@ data.values.websiteStyling.workshopInstructions.script - #@ if/end hasattr(data.values.websiteStyling.workshopInstructions, "style") and data.values.websiteStyling.workshopInstructions.style != None: - style: #@ data.values.websiteStyling.workshopInstructions.style - #@ if/end hasattr(data.values.websiteStyling, "workshopStarted") and data.values.websiteStyling.workshopStarted != None: - workshopStarted: - #@ if/end hasattr(data.values.websiteStyling.workshopStarted, "html") and data.values.websiteStyling.workshopStarted.html != None: - html: #@ data.values.websiteStyling.workshopStarted.html - #@ if/end hasattr(data.values.websiteStyling, "workshopFinished") and data.values.websiteStyling.workshopFinished != None: - workshopFinished: - #@ if/end hasattr(data.values.websiteStyling.workshopFinished, "html") and data.values.websiteStyling.workshopFinished.html != None: - html: #@ data.values.websiteStyling.workshopFinished.html - #@ if/end hasattr(data.values.websiteStyling, "trainingPortal") and data.values.websiteStyling.trainingPortal != None: - trainingPortal: - #@ if/end hasattr(data.values.websiteStyling.trainingPortal, "html") and data.values.websiteStyling.trainingPortal.html != None: - html: #@ data.values.websiteStyling.trainingPortal.html - #@ if/end hasattr(data.values.websiteStyling.trainingPortal, "script") and data.values.websiteStyling.trainingPortal.script != None: - script: #@ data.values.websiteStyling.trainingPortal.script - #@ if/end hasattr(data.values.websiteStyling.trainingPortal, "style") and data.values.websiteStyling.trainingPortal.style != None: - style: #@ data.values.websiteStyling.trainingPortal.style - #@ if/end hasattr(data.values.websiteStyling, "defaultTheme") and data.values.websiteStyling.defaultTheme != None: - defaultTheme: #@ data.values.websiteStyling.defaultTheme - #@ if/end hasattr(data.values.websiteStyling, "themeDataRefs") and data.values.websiteStyling.themeDataRefs != None: - themeDataRefs: #@ data.values.websiteStyling.themeDataRefs - #@ if/end hasattr(data.values.websiteStyling, "frameAncestors") and data.values.websiteStyling.frameAncestors != None: - frameAncestors: #@ data.values.websiteStyling.frameAncestors -#@ if/end hasattr(data.values, "imagePuller") and data.values.imagePuller != None: -imagePuller: - enabled: #@ data.values.imagePuller.enabled - #@ if hasattr(data.values.imagePuller, "prePullImages") and data.values.imagePuller.prePullImages != None: - #@overlay/replace - prePullImages: #@ data.values.imagePuller.prePullImages - #@ end -#@ if/end hasattr(data.values, "lookupService") and data.values.lookupService != None: -lookupService: - #@ if/end hasattr(data.values.lookupService, "enabled") and data.values.lookupService.enabled != None: - enabled: #@ data.values.lookupService.enabled - #@ if/end hasattr(data.values.lookupService, "ingressPrefix") and data.values.lookupService.ingressPrefix != None: - ingressPrefix: #@ data.values.lookupService.ingressPrefix -#@ end diff --git a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/infrastructure/kind/functions.star b/carvel-packages/installer/bundle/config/ytt/_ytt_lib/infrastructure/kind/functions.star deleted file mode 100644 index 774574200..000000000 --- a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/infrastructure/kind/functions.star +++ /dev/null @@ -1,55 +0,0 @@ -load("@ytt:data", "data") -load("defaults.star", "enabledByDefaultPackagesList") - -def isClusterPackageEnableByDefault(package): - return package in enabledByDefaultPackagesList -end - -def isClusterPackageEnabled(package): - if hasattr(data.values, "clusterPackages") and hasattr(data.values.clusterPackages, package) and hasattr(data.values.clusterPackages[package], "enabled"): - return data.values.clusterPackages[package].enabled - else: - return package in enabledByDefaultPackagesList - end -end - -def isClusterPackageExplicitDisabled(package): - return not isClusterPackageEnabled(package) -end - -def isGlobalCaCertificateRefEnabled(): - return (hasattr(data.values.clusterInfrastructure, "caCertificateRef") and - hasattr(data.values.clusterInfrastructure.caCertificateRef, "namespace") and - hasattr(data.values.clusterInfrastructure.caCertificateRef, "name")) -end - -def isEducatesTLSCertRefEnabled(): - return (hasattr(data.values.clusterPackages.educates.settings, "clusterIngress") and - hasattr(data.values.clusterPackages.educates.settings.clusterIngress, "tlsCertificateRef") and - hasattr(data.values.clusterPackages.educates.settings.clusterIngress.tlsCertificateRef, "namespace") and - hasattr(data.values.clusterPackages.educates.settings.clusterIngress.tlsCertificateRef, "name")) -end - -def isEducatesCARefEnabled(): - return (hasattr(data.values.clusterPackages.educates.settings, "clusterIngress") and - hasattr(data.values.clusterPackages.educates.settings.clusterIngress, "caCertificateRef") and - hasattr(data.values.clusterPackages.educates.settings.clusterIngress.caCertificateRef, "namespace") and - hasattr(data.values.clusterPackages.educates.settings.clusterIngress.caCertificateRef, "name")) -end - -def xgetattr(object, path, default=None): - def _lookup(object, key, default=None): - keys = key.split(".") - value = default - for key in keys: - value = getattr(object, key, None) - if value == None: - return default - end - object = value - end - return value - end - - return _lookup(object, path, default) -end \ No newline at end of file diff --git a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/infrastructure/minikube/00-remove-toplevel-values.yaml b/carvel-packages/installer/bundle/config/ytt/_ytt_lib/infrastructure/minikube/00-remove-toplevel-values.yaml deleted file mode 100644 index 931e60126..000000000 --- a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/infrastructure/minikube/00-remove-toplevel-values.yaml +++ /dev/null @@ -1,50 +0,0 @@ -#@ load("@ytt:data", "data") -#@ load("@ytt:overlay", "overlay") - -#@overlay/remove -debug: - -#@overlay/remove -localKindCluster: -#@overlay/remove -localDNSResolver: - -#@overlay/remove -clusterInfrastructure: - -#@overlay/remove -sessionManager: -#@overlay/remove -imageRegistry: -#@overlay/remove -version: -#@overlay/remove -imageVersions: -#@overlay/remove -clusterRuntime: -#@overlay/remove -clusterIngress: -#@overlay/remove -sessionCookies: -#@overlay/remove -clusterStorage: -#@overlay/remove -clusterSecrets: -#@overlay/remove -clusterSecurity: -#@overlay/remove -workshopSecurity: -#@overlay/remove -trainingPortal: -#@overlay/remove -dockerDaemon: -#@overlay/remove -clusterNetwork: -#@overlay/remove -workshopAnalytics: -#@overlay/remove -websiteStyling: -#@overlay/remove -imagePuller: -#@overlay/remove -lookupService: diff --git a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/infrastructure/minikube/10-default-settings-for-provider.yaml b/carvel-packages/installer/bundle/config/ytt/_ytt_lib/infrastructure/minikube/10-default-settings-for-provider.yaml deleted file mode 100644 index 16eeb2694..000000000 --- a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/infrastructure/minikube/10-default-settings-for-provider.yaml +++ /dev/null @@ -1,40 +0,0 @@ -#@ load("@ytt:data", "data") -#@ load("@ytt:overlay", "overlay") -#@ load("functions.star", "xgetattr", "isClusterPackageEnableByDefault") - -#! This file contains default values for the custom infrastructure provider. -#! These are the values that will be set if not overridden by the user. - -#@overlay/match-child-defaults missing_ok=True -#@overlay/replace -clusterPackages: - contour: - enabled: #@ isClusterPackageEnableByDefault("contour") - settings: - infraProvider: minikube - contour: - replicas: 1 - configFileContents: - defaultHttpVersions: - - "HTTP/1.1" - service: - type: ClusterIP - useHostPorts: true - cert-manager: - enabled: #@ isClusterPackageEnableByDefault("cert-manager") - settings: {} - external-dns: - enabled: #@ isClusterPackageEnableByDefault("external-dns") - settings: {} - certs: - enabled: #@ isClusterPackageEnableByDefault("certs") - settings: {} - kyverno: - enabled: #@ isClusterPackageEnableByDefault("kyverno") - settings: {} - kapp-controller: - enabled: #@ isClusterPackageEnableByDefault("kapp-controller") - settings: {} - educates: - enabled: #@ isClusterPackageEnableByDefault("educates") - settings: #@ xgetattr(data.values, "clusterPackages.educates.settings") diff --git a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/infrastructure/minikube/50-packages-enablement.yaml b/carvel-packages/installer/bundle/config/ytt/_ytt_lib/infrastructure/minikube/50-packages-enablement.yaml deleted file mode 100644 index fc2812d2b..000000000 --- a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/infrastructure/minikube/50-packages-enablement.yaml +++ /dev/null @@ -1,13 +0,0 @@ -#@ load("@ytt:data", "data") -#@ load("@ytt:overlay", "overlay") - -#! This enables packages based on the user input - -#@overlay/match-child-defaults missing_ok=True -clusterPackages: - contour: - #@ if/end hasattr(data.values, "clusterPackages") and hasattr(data.values.clusterPackages, "contour") and hasattr(data.values.clusterPackages.contour, "enabled"): - enabled: #@ data.values.clusterPackages.contour.enabled - kyverno: - #@ if/end hasattr(data.values, "clusterPackages") and hasattr(data.values.clusterPackages, "kyverno") and hasattr(data.values.clusterPackages.kyverno, "enabled"): - enabled: #@ data.values.clusterPackages.kyverno.enabled diff --git a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/infrastructure/minikube/80-copy-educates-config.yaml b/carvel-packages/installer/bundle/config/ytt/_ytt_lib/infrastructure/minikube/80-copy-educates-config.yaml deleted file mode 100644 index 1afda1acb..000000000 --- a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/infrastructure/minikube/80-copy-educates-config.yaml +++ /dev/null @@ -1,10 +0,0 @@ -#@ load("@ytt:data", "data") -#@ load("@ytt:overlay", "overlay") -#@ load("educates.lib.yaml", "copy_all_educates_values") - -#! This copies user provided values for the custom infrastructure provider. - -#@overlay/match-child-defaults missing_ok=True -clusterPackages: - educates: - settings: #@ copy_all_educates_values() diff --git a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/infrastructure/minikube/99-remove-settings-disabled.yaml b/carvel-packages/installer/bundle/config/ytt/_ytt_lib/infrastructure/minikube/99-remove-settings-disabled.yaml deleted file mode 100644 index 25b8297c8..000000000 --- a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/infrastructure/minikube/99-remove-settings-disabled.yaml +++ /dev/null @@ -1,36 +0,0 @@ -#@ load("@ytt:data", "data") -#@ load("@ytt:overlay", "overlay") -#@ load("functions.star", "isClusterPackageExplicitDisabled") - -#! This removes settings for disabled packages - -#@overlay/match-child-defaults missing_ok=True -clusterPackages: - contour: - #@ if/end isClusterPackageExplicitDisabled("contour"): - #@overlay/replace - settings: {} - cert-manager: - #@ if/end isClusterPackageExplicitDisabled("cert-manager"): - #@overlay/replace - settings: {} - external-dns: - #@ if/end isClusterPackageExplicitDisabled("external-dns"): - #@overlay/replace - settings: {} - certs: - #@ if/end isClusterPackageExplicitDisabled("certs"): - #@overlay/replace - settings: {} - kyverno: - #@ if/end isClusterPackageExplicitDisabled("kyverno"): - #@overlay/replace - settings: {} - kapp-controller: - #@ if/end isClusterPackageExplicitDisabled("kapp-controller"): - #@overlay/replace - settings: {} - #! educates: - #! #@ if/end isClusterPackageExplicitDisabled("educates"): - #! #@overlay/replace - #! settings: {} diff --git a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/infrastructure/minikube/README.md b/carvel-packages/installer/bundle/config/ytt/_ytt_lib/infrastructure/minikube/README.md deleted file mode 100644 index 11f2bd151..000000000 --- a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/infrastructure/minikube/README.md +++ /dev/null @@ -1,4 +0,0 @@ -# minikube -By default, contour, kyverno and educates will be installed -We only allow to enabling/disabling contour and kyverno -We copy all educates main config to the clusterPackage diff --git a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/infrastructure/minikube/defaults.star b/carvel-packages/installer/bundle/config/ytt/_ytt_lib/infrastructure/minikube/defaults.star deleted file mode 100644 index b2b3d9e1d..000000000 --- a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/infrastructure/minikube/defaults.star +++ /dev/null @@ -1,7 +0,0 @@ -load("@ytt:data", "data") - -enabledByDefaultPackagesList = [ - "contour", - "kyverno", - "educates" -] diff --git a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/infrastructure/minikube/educates.lib.yaml b/carvel-packages/installer/bundle/config/ytt/_ytt_lib/infrastructure/minikube/educates.lib.yaml deleted file mode 100644 index 3513efbd6..000000000 --- a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/infrastructure/minikube/educates.lib.yaml +++ /dev/null @@ -1,176 +0,0 @@ -#@ load("@ytt:data", "data") - -#@ def copy_all_educates_values(): - -#@ if/end hasattr(data.values, "sessionManager") and data.values.sessionManager != None: -sessionManager: - clusterAdmin: #@ data.values.sessionManager.clusterAdmin -#@ if/end hasattr(data.values, "imageRegistry") and data.values.imageRegistry != None: -imageRegistry: - #@ if/end hasattr(data.values.imageRegistry, "namespace") and data.values.imageRegistry.namespace != None: - namespace: #@ data.values.imageRegistry.namespace - #@ if/end hasattr(data.values.imageRegistry, "host") and data.values.imageRegistry.host != None: - host: #@ data.values.imageRegistry.host -#@ if/end hasattr(data.values, "version") and data.values.version != None: -version: #@ data.values.version -#@ if/end hasattr(data.values, "imageVersions") and data.values.imageVersions != None: -imageVersions: #@ data.values.imageVersions -#@ if/end hasattr(data.values, "clusterRuntime") and data.values.clusterRuntime != None: -clusterRuntime: #@ data.values.clusterRuntime -#@ if/end hasattr(data.values, "clusterIngress") and data.values.clusterIngress != None: -clusterIngress: - #@ if/end hasattr(data.values.clusterIngress, "domain") and data.values.clusterIngress.domain != None: - domain: #@ data.values.clusterIngress.domain - #@ if/end hasattr(data.values.clusterIngress, "class") and data.values.clusterIngress["class"] != None: - class: #@ data.values.clusterIngress["class"] - #@ if/end hasattr(data.values.clusterIngress, "protocol") and data.values.clusterIngress.protocol != None: - protocol: #@ data.values.clusterIngress.protocol - #@ if/end hasattr(data.values.clusterIngress, "tlsCertificate") and data.values.clusterIngress.tlsCertificate != None: - tlsCertificate: - #@ if/end hasattr(data.values.clusterIngress.tlsCertificate, "tls.crt") and data.values.clusterIngress.tlsCertificate["tls.crt"] != None: - tls.crt: #@ data.values.clusterIngress.tlsCertificate["tls.crt"] - #@ if/end hasattr(data.values.clusterIngress.tlsCertificate, "tls.key") and data.values.clusterIngress.tlsCertificate["tls.key"] != None: - tls.key: #@ data.values.clusterIngress.tlsCertificate["tls.key"] - #! TODO: Customize certs name reference in eks - #! projectcontour/wildcard - #@ if/end hasattr(data.values.clusterIngress, "tlsCertificateRef") and data.values.clusterIngress.tlsCertificateRef != None: - tlsCertificateRef: - namespace: #@ (hasattr(data.values.clusterIngress.tlsCertificateRef, "namespace") and data.values.clusterIngress.tlsCertificateRef.namespace != None) and data.values.clusterIngress.tlsCertificateRef.namespace or "projectcontour" - #@ if/end hasattr(data.values.clusterIngress.tlsCertificateRef, "name") and data.values.clusterIngress.tlsCertificateRef.name != None: - name: #@ data.values.clusterIngress.tlsCertificateRef.name - #@ if/end hasattr(data.values.clusterIngress, "caCertificate") and data.values.clusterIngress.caCertificate != None: - caCertificate: #@ data.values.clusterIngress.caCertificate - #@ if/end hasattr(data.values.clusterIngress, "caCertificateRef") and data.values.clusterIngress.caCertificateRef != None: - caCertificateRef: - #@ if/end hasattr(data.values.clusterIngress.caCertificateRef, "namespace") and data.values.clusterIngress.caCertificateRef.namespace != None: - namespace: #@ data.values.clusterIngress.caCertificateRef.namespace - #@ if/end hasattr(data.values.clusterIngress.caCertificateRef, "name") and data.values.clusterIngress.caCertificateRef.name != None: - name: #@ data.values.clusterIngress.caCertificateRef.name - #@ if/end hasattr(data.values.clusterIngress, "caNodeInjector") and data.values.clusterIngress.caNodeInjector != None: - caNodeInjector: #@ data.values.clusterIngress.caNodeInjector -#@ if/end hasattr(data.values, "sessionCookies") and data.values.sessionCookies != None: -sessionCookies: #@ data.values.sessionCookies -#@ if/end hasattr(data.values, "clusterStorage") and data.values.clusterStorage != None: -clusterStorage: - #@ if/end hasattr(data.values.clusterStorage, "class") and data.values.clusterStorage["class"] != None: - class: #@ data.values.clusterStorage["class"] - #@ if/end hasattr(data.values.clusterStorage, "user") and data.values.clusterStorage.user != None: - user: #@ data.values.clusterStorage.user - #@ if/end hasattr(data.values.clusterStorage, "group") and data.values.clusterStorage.group != None: - group: #@ data.values.clusterStorage.group -#@ if/end hasattr(data.values, "clusterSecrets") and data.values.clusterSecrets != None: -clusterSecrets: #@ data.values.clusterSecrets -#@ if/end hasattr(data.values, "clusterSecurity") and data.values.clusterSecurity != None: -clusterSecurity: #@ data.values.clusterSecurity -#@ if/end hasattr(data.values, "workshopSecurity") and data.values.workshopSecurity != None: -workshopSecurity: #@ data.values.workshopSecurity -#@ if/end hasattr(data.values, "trainingPortal") and data.values.trainingPortal != None: -trainingPortal: - #@ if/end hasattr(data.values.trainingPortal, "credentials") and data.values.trainingPortal.credentials != None: - credentials: - #@ if/end hasattr(data.values.trainingPortal.credentials, "admin") and data.values.trainingPortal.credentials.admin != None: - admin: - #@ if/end hasattr(data.values.trainingPortal.credentials.admin, "username") and data.values.trainingPortal.credentials.admin.username != None: - username: #@ data.values.trainingPortal.credentials.admin.username - #@ if/end hasattr(data.values.trainingPortal.credentials.admin, "password") and data.values.trainingPortal.credentials.admin.password != None: - password: #@ data.values.trainingPortal.credentials.admin.password - #@ if/end hasattr(data.values.trainingPortal.credentials, "robot") and data.values.trainingPortal.credentials.robot != None: - robot: - #@ if/end hasattr(data.values.trainingPortal.credentials.robot, "username") and data.values.trainingPortal.credentials.robot.username != None: - username: #@ data.values.trainingPortal.credentials.robot.username - #@ if/end hasattr(data.values.trainingPortal.credentials.robot, "password") and data.values.trainingPortal.credentials.robot.password != None: - password: #@ data.values.trainingPortal.credentials.robot.password - #@ if/end hasattr(data.values.trainingPortal, "clients") and data.values.trainingPortal.clients != None: - clients: - #@ if/end hasattr(data.values.trainingPortal.clients, "robot") and data.values.trainingPortal.clients.robot != None: - robot: - #@ if/end hasattr(data.values.trainingPortal.clients.robot, "id") and data.values.trainingPortal.clients.robot.id != None: - id: #@ data.values.trainingPortal.clients.robot.id - #@ if/end hasattr(data.values.trainingPortal.clients.robot, "secret") and data.values.trainingPortal.clients.robot.secret != None: - secret: #@ data.values.trainingPortal.clients.robot.secret -#@ if/end hasattr(data.values, "dockerDaemon") and data.values.dockerDaemon != None: -dockerDaemon: - #@ if/end hasattr(data.values.dockerDaemon, "networkMTU") and data.values.dockerDaemon.networkMTU != None: - networkMTU: #@ data.values.dockerDaemon.networkMTU - #@ if/end hasattr(data.values.dockerDaemon, "proxyCache") and data.values.dockerDaemon.proxyCache != None: - proxyCache: - #@ if/end hasattr(data.values.dockerDaemon.proxyCache, "remoteURL") and data.values.dockerDaemon.proxyCache.remoteURL != None: - remoteURL: #@ data.values.dockerDaemon.proxyCache.remoteURL - #@ if/end hasattr(data.values.dockerDaemon.proxyCache, "username") and data.values.dockerDaemon.proxyCache.username != None: - username: #@ data.values.dockerDaemon.proxyCache.username - #@ if/end hasattr(data.values.dockerDaemon.proxyCache, "password") and data.values.dockerDaemon.proxyCache.password != None: - password: #@ data.values.dockerDaemon.proxyCache.password -#@ if/end hasattr(data.values, "clusterNetwork") and data.values.clusterNetwork != None: -clusterNetwork: #@ data.values.clusterNetwork -#@ if/end hasattr(data.values, "workshopAnalytics") and data.values.workshopAnalytics != None: -workshopAnalytics: - #@ if/end hasattr(data.values.workshopAnalytics, "google") and data.values.workshopAnalytics.google != None: - google: - #@ if/end hasattr(data.values.workshopAnalytics.google, "trackingId") and data.values.workshopAnalytics.google.trackingId != None: - trackingId: #@ data.values.workshopAnalytics.google.trackingId - #@ if/end hasattr(data.values.workshopAnalytics, "clarity") and data.values.workshopAnalytics.clarity != None: - clarity: - #@ if/end hasattr(data.values.workshopAnalytics.clarity, "trackingId") and data.values.workshopAnalytics.clarity.trackingId != None: - trackingId: #@ data.values.workshopAnalytics.clarity.trackingId - #@ if/end hasattr(data.values.workshopAnalytics, "amplitude") and data.values.workshopAnalytics.amplitude != None: - amplitude: - #@ if/end hasattr(data.values.workshopAnalytics.amplitude, "trackingId") and data.values.workshopAnalytics.amplitude.trackingId != None: - trackingId: #@ data.values.workshopAnalytics.amplitude.trackingId - #@ if/end hasattr(data.values.workshopAnalytics, "webhook") and data.values.workshopAnalytics.webhook != None: - webhook: - #@ if/end hasattr(data.values.workshopAnalytics.webhook, "url") and data.values.workshopAnalytics.webhook.url != None: - url: #@ data.values.workshopAnalytics.webhook.url -#@ if/end hasattr(data.values, "websiteStyling") and data.values.websiteStyling != None: -websiteStyling: - #@ if/end hasattr(data.values.websiteStyling, "workshopDashboard") and data.values.websiteStyling.workshopDashboard != None: - workshopDashboard: - #@ if/end hasattr(data.values.websiteStyling.workshopDashboard, "html") and data.values.websiteStyling.workshopDashboard.html != None: - html: #@ data.values.websiteStyling.workshopDashboard.html - #@ if/end hasattr(data.values.websiteStyling.workshopDashboard, "script") and data.values.websiteStyling.workshopDashboard.script != None: - script: #@ data.values.websiteStyling.workshopDashboard.script - #@ if/end hasattr(data.values.websiteStyling.workshopDashboard, "style") and data.values.websiteStyling.workshopDashboard.style != None: - style: #@ data.values.websiteStyling.workshopDashboard.style - #@ if/end hasattr(data.values.websiteStyling, "workshopInstructions") and data.values.websiteStyling.workshopInstructions != None: - workshopInstructions: - #@ if/end hasattr(data.values.websiteStyling.workshopInstructions, "html") and data.values.websiteStyling.workshopInstructions.html != None: - html: #@ data.values.websiteStyling.workshopInstructions.html - #@ if/end hasattr(data.values.websiteStyling.workshopInstructions, "script") and data.values.websiteStyling.workshopInstructions.script != None: - script: #@ data.values.websiteStyling.workshopInstructions.script - #@ if/end hasattr(data.values.websiteStyling.workshopInstructions, "style") and data.values.websiteStyling.workshopInstructions.style != None: - style: #@ data.values.websiteStyling.workshopInstructions.style - #@ if/end hasattr(data.values.websiteStyling, "workshopStarted") and data.values.websiteStyling.workshopStarted != None: - workshopStarted: - #@ if/end hasattr(data.values.websiteStyling.workshopStarted, "html") and data.values.websiteStyling.workshopStarted.html != None: - html: #@ data.values.websiteStyling.workshopStarted.html - #@ if/end hasattr(data.values.websiteStyling, "workshopFinished") and data.values.websiteStyling.workshopFinished != None: - workshopFinished: - #@ if/end hasattr(data.values.websiteStyling.workshopFinished, "html") and data.values.websiteStyling.workshopFinished.html != None: - html: #@ data.values.websiteStyling.workshopFinished.html - #@ if/end hasattr(data.values.websiteStyling, "trainingPortal") and data.values.websiteStyling.trainingPortal != None: - trainingPortal: - #@ if/end hasattr(data.values.websiteStyling.trainingPortal, "html") and data.values.websiteStyling.trainingPortal.html != None: - html: #@ data.values.websiteStyling.trainingPortal.html - #@ if/end hasattr(data.values.websiteStyling.trainingPortal, "script") and data.values.websiteStyling.trainingPortal.script != None: - script: #@ data.values.websiteStyling.trainingPortal.script - #@ if/end hasattr(data.values.websiteStyling.trainingPortal, "style") and data.values.websiteStyling.trainingPortal.style != None: - style: #@ data.values.websiteStyling.trainingPortal.style - #@ if/end hasattr(data.values.websiteStyling, "defaultTheme") and data.values.websiteStyling.defaultTheme != None: - defaultTheme: #@ data.values.websiteStyling.defaultTheme - #@ if/end hasattr(data.values.websiteStyling, "themeDataRefs") and data.values.websiteStyling.themeDataRefs != None: - themeDataRefs: #@ data.values.websiteStyling.themeDataRefs - #@ if/end hasattr(data.values.websiteStyling, "frameAncestors") and data.values.websiteStyling.frameAncestors != None: - frameAncestors: #@ data.values.websiteStyling.frameAncestors -#@ if/end hasattr(data.values, "imagePuller") and data.values.imagePuller != None: -imagePuller: - enabled: #@ data.values.imagePuller.enabled - #@ if hasattr(data.values.imagePuller, "prePullImages") and data.values.imagePuller.prePullImages != None: - #@overlay/replace - prePullImages: #@ data.values.imagePuller.prePullImages - #@ end -#@ if/end hasattr(data.values, "lookupService") and data.values.lookupService != None: -lookupService: - #@ if/end hasattr(data.values.lookupService, "enabled") and data.values.lookupService.enabled != None: - enabled: #@ data.values.lookupService.enabled - #@ if/end hasattr(data.values.lookupService, "ingressPrefix") and data.values.lookupService.ingressPrefix != None: - ingressPrefix: #@ data.values.lookupService.ingressPrefix -#@ end diff --git a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/infrastructure/minikube/functions.star b/carvel-packages/installer/bundle/config/ytt/_ytt_lib/infrastructure/minikube/functions.star deleted file mode 100644 index 78ebaa3e7..000000000 --- a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/infrastructure/minikube/functions.star +++ /dev/null @@ -1,35 +0,0 @@ -load("@ytt:data", "data") -load("defaults.star", "enabledByDefaultPackagesList") - -def isClusterPackageEnableByDefault(package): - return package in enabledByDefaultPackagesList -end - -def isClusterPackageEnabled(package): - if hasattr(data.values, "clusterPackages") and hasattr(data.values.clusterPackages, package) and hasattr(data.values.clusterPackages[package], "enabled"): - return data.values.clusterPackages[package].enabled - else: - return package in enabledByDefaultPackagesList - end -end - -def isClusterPackageExplicitDisabled(package): - return not isClusterPackageEnabled(package) -end - -def xgetattr(object, path, default=None): - def _lookup(object, key, default=None): - keys = key.split(".") - value = default - for key in keys: - value = getattr(object, key, None) - if value == None: - return default - end - object = value - end - return value - end - - return _lookup(object, path, default) -end \ No newline at end of file diff --git a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/infrastructure/openshift/00-remove-toplevel-values.yaml b/carvel-packages/installer/bundle/config/ytt/_ytt_lib/infrastructure/openshift/00-remove-toplevel-values.yaml deleted file mode 100644 index 931e60126..000000000 --- a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/infrastructure/openshift/00-remove-toplevel-values.yaml +++ /dev/null @@ -1,50 +0,0 @@ -#@ load("@ytt:data", "data") -#@ load("@ytt:overlay", "overlay") - -#@overlay/remove -debug: - -#@overlay/remove -localKindCluster: -#@overlay/remove -localDNSResolver: - -#@overlay/remove -clusterInfrastructure: - -#@overlay/remove -sessionManager: -#@overlay/remove -imageRegistry: -#@overlay/remove -version: -#@overlay/remove -imageVersions: -#@overlay/remove -clusterRuntime: -#@overlay/remove -clusterIngress: -#@overlay/remove -sessionCookies: -#@overlay/remove -clusterStorage: -#@overlay/remove -clusterSecrets: -#@overlay/remove -clusterSecurity: -#@overlay/remove -workshopSecurity: -#@overlay/remove -trainingPortal: -#@overlay/remove -dockerDaemon: -#@overlay/remove -clusterNetwork: -#@overlay/remove -workshopAnalytics: -#@overlay/remove -websiteStyling: -#@overlay/remove -imagePuller: -#@overlay/remove -lookupService: diff --git a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/infrastructure/openshift/10-default-settings-for-provider.yaml b/carvel-packages/installer/bundle/config/ytt/_ytt_lib/infrastructure/openshift/10-default-settings-for-provider.yaml deleted file mode 100644 index 5842bd68d..000000000 --- a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/infrastructure/openshift/10-default-settings-for-provider.yaml +++ /dev/null @@ -1,31 +0,0 @@ -#@ load("@ytt:data", "data") -#@ load("@ytt:overlay", "overlay") -#@ load("functions.star", "xgetattr", "isClusterPackageEnableByDefault") - -#! This file contains default values for the custom infrastructure provider. -#! These are the values that will be set if not overridden by the user. - -#@overlay/match-child-defaults missing_ok=True -#@overlay/replace -clusterPackages: - contour: - enabled: #@ isClusterPackageEnableByDefault("contour") - settings: {} - cert-manager: - enabled: #@ isClusterPackageEnableByDefault("cert-manager") - settings: {} - external-dns: - enabled: #@ isClusterPackageEnableByDefault("external-dns") - settings: {} - certs: - enabled: #@ isClusterPackageEnableByDefault("certs") - settings: {} - kyverno: - enabled: #@ isClusterPackageEnableByDefault("kyverno") - settings: {} - kapp-controller: - enabled: #@ isClusterPackageEnableByDefault("kapp-controller") - settings: {} - educates: - enabled: #@ isClusterPackageEnableByDefault("educates") - settings: #@ xgetattr(data.values, "clusterPackages.educates.settings") diff --git a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/infrastructure/openshift/50-packages-enablement.yaml b/carvel-packages/installer/bundle/config/ytt/_ytt_lib/infrastructure/openshift/50-packages-enablement.yaml deleted file mode 100644 index 8d4b7d343..000000000 --- a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/infrastructure/openshift/50-packages-enablement.yaml +++ /dev/null @@ -1,10 +0,0 @@ -#@ load("@ytt:data", "data") -#@ load("@ytt:overlay", "overlay") - -#! This enables packages based on the user input - -#@overlay/match-child-defaults missing_ok=True -clusterPackages: - kyverno: - #@ if/end hasattr(data.values, "clusterPackages") and hasattr(data.values.clusterPackages, "kyverno") and hasattr(data.values.clusterPackages.kyverno, "enabled"): - enabled: #@ data.values.clusterPackages.kyverno.enabled \ No newline at end of file diff --git a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/infrastructure/openshift/80-copy-educates-config.yaml b/carvel-packages/installer/bundle/config/ytt/_ytt_lib/infrastructure/openshift/80-copy-educates-config.yaml deleted file mode 100644 index 1afda1acb..000000000 --- a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/infrastructure/openshift/80-copy-educates-config.yaml +++ /dev/null @@ -1,10 +0,0 @@ -#@ load("@ytt:data", "data") -#@ load("@ytt:overlay", "overlay") -#@ load("educates.lib.yaml", "copy_all_educates_values") - -#! This copies user provided values for the custom infrastructure provider. - -#@overlay/match-child-defaults missing_ok=True -clusterPackages: - educates: - settings: #@ copy_all_educates_values() diff --git a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/infrastructure/openshift/99-remove-settings-disabled.yaml b/carvel-packages/installer/bundle/config/ytt/_ytt_lib/infrastructure/openshift/99-remove-settings-disabled.yaml deleted file mode 100644 index 25b8297c8..000000000 --- a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/infrastructure/openshift/99-remove-settings-disabled.yaml +++ /dev/null @@ -1,36 +0,0 @@ -#@ load("@ytt:data", "data") -#@ load("@ytt:overlay", "overlay") -#@ load("functions.star", "isClusterPackageExplicitDisabled") - -#! This removes settings for disabled packages - -#@overlay/match-child-defaults missing_ok=True -clusterPackages: - contour: - #@ if/end isClusterPackageExplicitDisabled("contour"): - #@overlay/replace - settings: {} - cert-manager: - #@ if/end isClusterPackageExplicitDisabled("cert-manager"): - #@overlay/replace - settings: {} - external-dns: - #@ if/end isClusterPackageExplicitDisabled("external-dns"): - #@overlay/replace - settings: {} - certs: - #@ if/end isClusterPackageExplicitDisabled("certs"): - #@overlay/replace - settings: {} - kyverno: - #@ if/end isClusterPackageExplicitDisabled("kyverno"): - #@overlay/replace - settings: {} - kapp-controller: - #@ if/end isClusterPackageExplicitDisabled("kapp-controller"): - #@overlay/replace - settings: {} - #! educates: - #! #@ if/end isClusterPackageExplicitDisabled("educates"): - #! #@overlay/replace - #! settings: {} diff --git a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/infrastructure/openshift/README.md b/carvel-packages/installer/bundle/config/ytt/_ytt_lib/infrastructure/openshift/README.md deleted file mode 100644 index 03738962a..000000000 --- a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/infrastructure/openshift/README.md +++ /dev/null @@ -1,4 +0,0 @@ -# openshift -By default, only kyverno and educates will be installed -We only allow to enabling/disabling kyverno -We copy all educates main config to the clusterPackage diff --git a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/infrastructure/openshift/defaults.star b/carvel-packages/installer/bundle/config/ytt/_ytt_lib/infrastructure/openshift/defaults.star deleted file mode 100644 index e0e228579..000000000 --- a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/infrastructure/openshift/defaults.star +++ /dev/null @@ -1,6 +0,0 @@ -load("@ytt:data", "data") - -enabledByDefaultPackagesList = [ - "kyverno", - "educates" -] \ No newline at end of file diff --git a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/infrastructure/openshift/educates.lib.yaml b/carvel-packages/installer/bundle/config/ytt/_ytt_lib/infrastructure/openshift/educates.lib.yaml deleted file mode 100644 index f47b947a3..000000000 --- a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/infrastructure/openshift/educates.lib.yaml +++ /dev/null @@ -1,177 +0,0 @@ -#@ load("@ytt:data", "data") - -#@ def copy_all_educates_values(): - -#@ if/end hasattr(data.values, "sessionManager") and data.values.sessionManager != None: -sessionManager: - clusterAdmin: #@ data.values.sessionManager.clusterAdmin -#@ if/end hasattr(data.values, "imageRegistry") and data.values.imageRegistry != None: -imageRegistry: - #@ if/end hasattr(data.values.imageRegistry, "namespace") and data.values.imageRegistry.namespace != None: - namespace: #@ data.values.imageRegistry.namespace - #@ if/end hasattr(data.values.imageRegistry, "host") and data.values.imageRegistry.host != None: - host: #@ data.values.imageRegistry.host -#@ if/end hasattr(data.values, "version") and data.values.version != None: -version: #@ data.values.version -#@ if/end hasattr(data.values, "imageVersions") and data.values.imageVersions != None: -imageVersions: #@ data.values.imageVersions -#@ if/end hasattr(data.values, "clusterRuntime") and data.values.clusterRuntime != None: -clusterRuntime: #@ data.values.clusterRuntime -#@ if/end hasattr(data.values, "clusterIngress") and data.values.clusterIngress != None: -clusterIngress: - #@ if/end hasattr(data.values.clusterIngress, "domain") and data.values.clusterIngress.domain != None: - domain: #@ data.values.clusterIngress.domain - #@ if/end hasattr(data.values.clusterIngress, "class") and data.values.clusterIngress["class"] != None: - class: #@ data.values.clusterIngress["class"] - #@ if/end hasattr(data.values.clusterIngress, "protocol") and data.values.clusterIngress.protocol != None: - protocol: #@ data.values.clusterIngress.protocol - #@ if/end hasattr(data.values.clusterIngress, "tlsCertificate") and data.values.clusterIngress.tlsCertificate != None: - tlsCertificate: - #@ if/end hasattr(data.values.clusterIngress.tlsCertificate, "tls.crt") and data.values.clusterIngress.tlsCertificate["tls.crt"] != None: - tls.crt: #@ data.values.clusterIngress.tlsCertificate["tls.crt"] - #@ if/end hasattr(data.values.clusterIngress.tlsCertificate, "tls.key") and data.values.clusterIngress.tlsCertificate["tls.key"] != None: - tls.key: #@ data.values.clusterIngress.tlsCertificate["tls.key"] - #! TODO: Customize certs name reference in eks - #! projectcontour/wildcard - #@ if/end hasattr(data.values.clusterIngress, "tlsCertificateRef") and data.values.clusterIngress.tlsCertificateRef != None: - tlsCertificateRef: - namespace: #@ (hasattr(data.values.clusterIngress.tlsCertificateRef, "namespace") and data.values.clusterIngress.tlsCertificateRef.namespace != None) and data.values.clusterIngress.tlsCertificateRef.namespace or "projectcontour" - #@ if/end hasattr(data.values.clusterIngress.tlsCertificateRef, "name") and data.values.clusterIngress.tlsCertificateRef.name != None: - name: #@ data.values.clusterIngress.tlsCertificateRef.name - #@ if/end hasattr(data.values.clusterIngress, "caCertificate") and data.values.clusterIngress.caCertificate != None: - caCertificate: #@ data.values.clusterIngress.caCertificate - #@ if/end hasattr(data.values.clusterIngress, "caCertificateRef") and data.values.clusterIngress.caCertificateRef != None: - caCertificateRef: - #@ if/end hasattr(data.values.clusterIngress.caCertificateRef, "namespace") and data.values.clusterIngress.caCertificateRef.namespace != None: - namespace: #@ data.values.clusterIngress.caCertificateRef.namespace - #@ if/end hasattr(data.values.clusterIngress.caCertificateRef, "name") and data.values.clusterIngress.caCertificateRef.name != None: - name: #@ data.values.clusterIngress.caCertificateRef.name - #@ if/end hasattr(data.values.clusterIngress, "caNodeInjector") and data.values.clusterIngress.caNodeInjector != None: - caNodeInjector: #@ data.values.clusterIngress.caNodeInjector -#@ if/end hasattr(data.values, "sessionCookies") and data.values.sessionCookies != None: -sessionCookies: #@ data.values.sessionCookies -#@ if/end hasattr(data.values, "clusterStorage") and data.values.clusterStorage != None: -clusterStorage: - #@ if/end hasattr(data.values.clusterStorage, "class") and data.values.clusterStorage["class"] != None: - class: #@ data.values.clusterStorage["class"] - #@ if/end hasattr(data.values.clusterStorage, "user") and data.values.clusterStorage.user != None: - user: #@ data.values.clusterStorage.user - #@ if/end hasattr(data.values.clusterStorage, "group") and data.values.clusterStorage.group != None: - group: #@ data.values.clusterStorage.group -#@ if/end hasattr(data.values, "clusterSecrets") and data.values.clusterSecrets != None: -clusterSecrets: #@ data.values.clusterSecrets -#! Policy engine must always be security-context-constraints on openshift -clusterSecurity: - policyEngine: security-context-constraints -#@ if/end hasattr(data.values, "workshopSecurity") and data.values.workshopSecurity != None: -workshopSecurity: #@ data.values.workshopSecurity -#@ if/end hasattr(data.values, "trainingPortal") and data.values.trainingPortal != None: -trainingPortal: - #@ if/end hasattr(data.values.trainingPortal, "credentials") and data.values.trainingPortal.credentials != None: - credentials: - #@ if/end hasattr(data.values.trainingPortal.credentials, "admin") and data.values.trainingPortal.credentials.admin != None: - admin: - #@ if/end hasattr(data.values.trainingPortal.credentials.admin, "username") and data.values.trainingPortal.credentials.admin.username != None: - username: #@ data.values.trainingPortal.credentials.admin.username - #@ if/end hasattr(data.values.trainingPortal.credentials.admin, "password") and data.values.trainingPortal.credentials.admin.password != None: - password: #@ data.values.trainingPortal.credentials.admin.password - #@ if/end hasattr(data.values.trainingPortal.credentials, "robot") and data.values.trainingPortal.credentials.robot != None: - robot: - #@ if/end hasattr(data.values.trainingPortal.credentials.robot, "username") and data.values.trainingPortal.credentials.robot.username != None: - username: #@ data.values.trainingPortal.credentials.robot.username - #@ if/end hasattr(data.values.trainingPortal.credentials.robot, "password") and data.values.trainingPortal.credentials.robot.password != None: - password: #@ data.values.trainingPortal.credentials.robot.password - #@ if/end hasattr(data.values.trainingPortal, "clients") and data.values.trainingPortal.clients != None: - clients: - #@ if/end hasattr(data.values.trainingPortal.clients, "robot") and data.values.trainingPortal.clients.robot != None: - robot: - #@ if/end hasattr(data.values.trainingPortal.clients.robot, "id") and data.values.trainingPortal.clients.robot.id != None: - id: #@ data.values.trainingPortal.clients.robot.id - #@ if/end hasattr(data.values.trainingPortal.clients.robot, "secret") and data.values.trainingPortal.clients.robot.secret != None: - secret: #@ data.values.trainingPortal.clients.robot.secret -#@ if/end hasattr(data.values, "dockerDaemon") and data.values.dockerDaemon != None: -dockerDaemon: - #@ if/end hasattr(data.values.dockerDaemon, "networkMTU") and data.values.dockerDaemon.networkMTU != None: - networkMTU: #@ data.values.dockerDaemon.networkMTU - #@ if/end hasattr(data.values.dockerDaemon, "proxyCache") and data.values.dockerDaemon.proxyCache != None: - proxyCache: - #@ if/end hasattr(data.values.dockerDaemon.proxyCache, "remoteURL") and data.values.dockerDaemon.proxyCache.remoteURL != None: - remoteURL: #@ data.values.dockerDaemon.proxyCache.remoteURL - #@ if/end hasattr(data.values.dockerDaemon.proxyCache, "username") and data.values.dockerDaemon.proxyCache.username != None: - username: #@ data.values.dockerDaemon.proxyCache.username - #@ if/end hasattr(data.values.dockerDaemon.proxyCache, "password") and data.values.dockerDaemon.proxyCache.password != None: - password: #@ data.values.dockerDaemon.proxyCache.password -#@ if/end hasattr(data.values, "clusterNetwork") and data.values.clusterNetwork != None: -clusterNetwork: #@ data.values.clusterNetwork -#@ if/end hasattr(data.values, "workshopAnalytics") and data.values.workshopAnalytics != None: -workshopAnalytics: - #@ if/end hasattr(data.values.workshopAnalytics, "google") and data.values.workshopAnalytics.google != None: - google: - #@ if/end hasattr(data.values.workshopAnalytics.google, "trackingId") and data.values.workshopAnalytics.google.trackingId != None: - trackingId: #@ data.values.workshopAnalytics.google.trackingId - #@ if/end hasattr(data.values.workshopAnalytics, "clarity") and data.values.workshopAnalytics.clarity != None: - clarity: - #@ if/end hasattr(data.values.workshopAnalytics.clarity, "trackingId") and data.values.workshopAnalytics.clarity.trackingId != None: - trackingId: #@ data.values.workshopAnalytics.clarity.trackingId - #@ if/end hasattr(data.values.workshopAnalytics, "amplitude") and data.values.workshopAnalytics.amplitude != None: - amplitude: - #@ if/end hasattr(data.values.workshopAnalytics.amplitude, "trackingId") and data.values.workshopAnalytics.amplitude.trackingId != None: - trackingId: #@ data.values.workshopAnalytics.amplitude.trackingId - #@ if/end hasattr(data.values.workshopAnalytics, "webhook") and data.values.workshopAnalytics.webhook != None: - webhook: - #@ if/end hasattr(data.values.workshopAnalytics.webhook, "url") and data.values.workshopAnalytics.webhook.url != None: - url: #@ data.values.workshopAnalytics.webhook.url -#@ if/end hasattr(data.values, "websiteStyling") and data.values.websiteStyling != None: -websiteStyling: - #@ if/end hasattr(data.values.websiteStyling, "workshopDashboard") and data.values.websiteStyling.workshopDashboard != None: - workshopDashboard: - #@ if/end hasattr(data.values.websiteStyling.workshopDashboard, "html") and data.values.websiteStyling.workshopDashboard.html != None: - html: #@ data.values.websiteStyling.workshopDashboard.html - #@ if/end hasattr(data.values.websiteStyling.workshopDashboard, "script") and data.values.websiteStyling.workshopDashboard.script != None: - script: #@ data.values.websiteStyling.workshopDashboard.script - #@ if/end hasattr(data.values.websiteStyling.workshopDashboard, "style") and data.values.websiteStyling.workshopDashboard.style != None: - style: #@ data.values.websiteStyling.workshopDashboard.style - #@ if/end hasattr(data.values.websiteStyling, "workshopInstructions") and data.values.websiteStyling.workshopInstructions != None: - workshopInstructions: - #@ if/end hasattr(data.values.websiteStyling.workshopInstructions, "html") and data.values.websiteStyling.workshopInstructions.html != None: - html: #@ data.values.websiteStyling.workshopInstructions.html - #@ if/end hasattr(data.values.websiteStyling.workshopInstructions, "script") and data.values.websiteStyling.workshopInstructions.script != None: - script: #@ data.values.websiteStyling.workshopInstructions.script - #@ if/end hasattr(data.values.websiteStyling.workshopInstructions, "style") and data.values.websiteStyling.workshopInstructions.style != None: - style: #@ data.values.websiteStyling.workshopInstructions.style - #@ if/end hasattr(data.values.websiteStyling, "workshopStarted") and data.values.websiteStyling.workshopStarted != None: - workshopStarted: - #@ if/end hasattr(data.values.websiteStyling.workshopStarted, "html") and data.values.websiteStyling.workshopStarted.html != None: - html: #@ data.values.websiteStyling.workshopStarted.html - #@ if/end hasattr(data.values.websiteStyling, "workshopFinished") and data.values.websiteStyling.workshopFinished != None: - workshopFinished: - #@ if/end hasattr(data.values.websiteStyling.workshopFinished, "html") and data.values.websiteStyling.workshopFinished.html != None: - html: #@ data.values.websiteStyling.workshopFinished.html - #@ if/end hasattr(data.values.websiteStyling, "trainingPortal") and data.values.websiteStyling.trainingPortal != None: - trainingPortal: - #@ if/end hasattr(data.values.websiteStyling.trainingPortal, "html") and data.values.websiteStyling.trainingPortal.html != None: - html: #@ data.values.websiteStyling.trainingPortal.html - #@ if/end hasattr(data.values.websiteStyling.trainingPortal, "script") and data.values.websiteStyling.trainingPortal.script != None: - script: #@ data.values.websiteStyling.trainingPortal.script - #@ if/end hasattr(data.values.websiteStyling.trainingPortal, "style") and data.values.websiteStyling.trainingPortal.style != None: - style: #@ data.values.websiteStyling.trainingPortal.style - #@ if/end hasattr(data.values.websiteStyling, "defaultTheme") and data.values.websiteStyling.defaultTheme != None: - defaultTheme: #@ data.values.websiteStyling.defaultTheme - #@ if/end hasattr(data.values.websiteStyling, "themeDataRefs") and data.values.websiteStyling.themeDataRefs != None: - themeDataRefs: #@ data.values.websiteStyling.themeDataRefs - #@ if/end hasattr(data.values.websiteStyling, "frameAncestors") and data.values.websiteStyling.frameAncestors != None: - frameAncestors: #@ data.values.websiteStyling.frameAncestors -#@ if/end hasattr(data.values, "imagePuller") and data.values.imagePuller != None: -imagePuller: - enabled: #@ data.values.imagePuller.enabled - #@ if hasattr(data.values.imagePuller, "prePullImages") and data.values.imagePuller.prePullImages != None: - #@overlay/replace - prePullImages: #@ data.values.imagePuller.prePullImages - #@ end -#@ if/end hasattr(data.values, "lookupService") and data.values.lookupService != None: -lookupService: - #@ if/end hasattr(data.values.lookupService, "enabled") and data.values.lookupService.enabled != None: - enabled: #@ data.values.lookupService.enabled - #@ if/end hasattr(data.values.lookupService, "ingressPrefix") and data.values.lookupService.ingressPrefix != None: - ingressPrefix: #@ data.values.lookupService.ingressPrefix -#@ end diff --git a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/infrastructure/openshift/functions.star b/carvel-packages/installer/bundle/config/ytt/_ytt_lib/infrastructure/openshift/functions.star deleted file mode 100644 index 78ebaa3e7..000000000 --- a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/infrastructure/openshift/functions.star +++ /dev/null @@ -1,35 +0,0 @@ -load("@ytt:data", "data") -load("defaults.star", "enabledByDefaultPackagesList") - -def isClusterPackageEnableByDefault(package): - return package in enabledByDefaultPackagesList -end - -def isClusterPackageEnabled(package): - if hasattr(data.values, "clusterPackages") and hasattr(data.values.clusterPackages, package) and hasattr(data.values.clusterPackages[package], "enabled"): - return data.values.clusterPackages[package].enabled - else: - return package in enabledByDefaultPackagesList - end -end - -def isClusterPackageExplicitDisabled(package): - return not isClusterPackageEnabled(package) -end - -def xgetattr(object, path, default=None): - def _lookup(object, key, default=None): - keys = key.split(".") - value = default - for key in keys: - value = getattr(object, key, None) - if value == None: - return default - end - object = value - end - return value - end - - return _lookup(object, path, default) -end \ No newline at end of file diff --git a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/infrastructure/vcluster/00-remove-toplevel-values.yaml b/carvel-packages/installer/bundle/config/ytt/_ytt_lib/infrastructure/vcluster/00-remove-toplevel-values.yaml deleted file mode 100644 index 931e60126..000000000 --- a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/infrastructure/vcluster/00-remove-toplevel-values.yaml +++ /dev/null @@ -1,50 +0,0 @@ -#@ load("@ytt:data", "data") -#@ load("@ytt:overlay", "overlay") - -#@overlay/remove -debug: - -#@overlay/remove -localKindCluster: -#@overlay/remove -localDNSResolver: - -#@overlay/remove -clusterInfrastructure: - -#@overlay/remove -sessionManager: -#@overlay/remove -imageRegistry: -#@overlay/remove -version: -#@overlay/remove -imageVersions: -#@overlay/remove -clusterRuntime: -#@overlay/remove -clusterIngress: -#@overlay/remove -sessionCookies: -#@overlay/remove -clusterStorage: -#@overlay/remove -clusterSecrets: -#@overlay/remove -clusterSecurity: -#@overlay/remove -workshopSecurity: -#@overlay/remove -trainingPortal: -#@overlay/remove -dockerDaemon: -#@overlay/remove -clusterNetwork: -#@overlay/remove -workshopAnalytics: -#@overlay/remove -websiteStyling: -#@overlay/remove -imagePuller: -#@overlay/remove -lookupService: diff --git a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/infrastructure/vcluster/10-default-settings-for-provider.yaml b/carvel-packages/installer/bundle/config/ytt/_ytt_lib/infrastructure/vcluster/10-default-settings-for-provider.yaml deleted file mode 100644 index 5842bd68d..000000000 --- a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/infrastructure/vcluster/10-default-settings-for-provider.yaml +++ /dev/null @@ -1,31 +0,0 @@ -#@ load("@ytt:data", "data") -#@ load("@ytt:overlay", "overlay") -#@ load("functions.star", "xgetattr", "isClusterPackageEnableByDefault") - -#! This file contains default values for the custom infrastructure provider. -#! These are the values that will be set if not overridden by the user. - -#@overlay/match-child-defaults missing_ok=True -#@overlay/replace -clusterPackages: - contour: - enabled: #@ isClusterPackageEnableByDefault("contour") - settings: {} - cert-manager: - enabled: #@ isClusterPackageEnableByDefault("cert-manager") - settings: {} - external-dns: - enabled: #@ isClusterPackageEnableByDefault("external-dns") - settings: {} - certs: - enabled: #@ isClusterPackageEnableByDefault("certs") - settings: {} - kyverno: - enabled: #@ isClusterPackageEnableByDefault("kyverno") - settings: {} - kapp-controller: - enabled: #@ isClusterPackageEnableByDefault("kapp-controller") - settings: {} - educates: - enabled: #@ isClusterPackageEnableByDefault("educates") - settings: #@ xgetattr(data.values, "clusterPackages.educates.settings") diff --git a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/infrastructure/vcluster/50-packages-enablement.yaml b/carvel-packages/installer/bundle/config/ytt/_ytt_lib/infrastructure/vcluster/50-packages-enablement.yaml deleted file mode 100644 index 2080d7d4d..000000000 --- a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/infrastructure/vcluster/50-packages-enablement.yaml +++ /dev/null @@ -1,28 +0,0 @@ -#@ load("@ytt:data", "data") -#@ load("@ytt:overlay", "overlay") - -#! This enables packages based on the user input - -#@overlay/match-child-defaults missing_ok=True -clusterPackages: -#! contour: -#! #@ if/end hasattr(data.values, "clusterPackages") and hasattr(data.values.clusterPackages, "contour") and hasattr(data.values.clusterPackages.contour, "enabled"): -#! enabled: #@ data.values.clusterPackages.contour.enabled - cert-manager: - #@ if/end hasattr(data.values, "clusterPackages") and hasattr(data.values.clusterPackages, "cert-manager") and hasattr(data.values.clusterPackages["cert-manager"], "enabled"): - enabled: #@ data.values.clusterPackages["cert-manager"].enabled - external-dns: - #@ if/end hasattr(data.values, "clusterPackages") and hasattr(data.values.clusterPackages, "external-dns") and hasattr(data.values.clusterPackages["external-dns"], "enabled"): - enabled: #@ data.values.clusterPackages["external-dns"].enabled - certs: - #@ if/end hasattr(data.values, "clusterPackages") and hasattr(data.values.clusterPackages, "certs") and hasattr(data.values.clusterPackages.certs, "enabled"): - enabled: #@ data.values.clusterPackages.certs.enabled - kyverno: - #@ if/end hasattr(data.values, "clusterPackages") and hasattr(data.values.clusterPackages, "kyverno") and hasattr(data.values.clusterPackages.kyverno, "enabled"): - enabled: #@ data.values.clusterPackages.kyverno.enabled - kapp-controller: - #@ if/end hasattr(data.values, "clusterPackages") and hasattr(data.values.clusterPackages, "kapp-controller") and hasattr(data.values.clusterPackages["kapp-controller"], "enabled"): - enabled: #@ data.values.clusterPackages["kapp-controller"].enabled - educates: - #@ if/end hasattr(data.values, "clusterPackages") and hasattr(data.values.clusterPackages, "educates") and hasattr(data.values.clusterPackages.educates, "enabled"): - enabled: #@ data.values.clusterPackages.educates.enabled diff --git a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/infrastructure/vcluster/80-copy-educates-config.yaml b/carvel-packages/installer/bundle/config/ytt/_ytt_lib/infrastructure/vcluster/80-copy-educates-config.yaml deleted file mode 100644 index 1afda1acb..000000000 --- a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/infrastructure/vcluster/80-copy-educates-config.yaml +++ /dev/null @@ -1,10 +0,0 @@ -#@ load("@ytt:data", "data") -#@ load("@ytt:overlay", "overlay") -#@ load("educates.lib.yaml", "copy_all_educates_values") - -#! This copies user provided values for the custom infrastructure provider. - -#@overlay/match-child-defaults missing_ok=True -clusterPackages: - educates: - settings: #@ copy_all_educates_values() diff --git a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/infrastructure/vcluster/90-overlays.yaml b/carvel-packages/installer/bundle/config/ytt/_ytt_lib/infrastructure/vcluster/90-overlays.yaml deleted file mode 100644 index 121477b68..000000000 --- a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/infrastructure/vcluster/90-overlays.yaml +++ /dev/null @@ -1,16 +0,0 @@ -#@ load("@ytt:data", "data") -#@ load("@ytt:overlay", "overlay") - -#! This file is used to set the default values for the vcluster installation -#! Add to this file all the defaults that you don't want to be overidden by the user -#! These values will override all the values provided by the user either in the global configuration -#! or the clusterPackages.educates configuration - -#@overlay/match-child-defaults missing_ok=True -clusterPackages: - educates: - settings: - imagePuller: - enabled: false - #@overlay/replace - prePullImages: [] diff --git a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/infrastructure/vcluster/99-remove-settings-disabled.yaml b/carvel-packages/installer/bundle/config/ytt/_ytt_lib/infrastructure/vcluster/99-remove-settings-disabled.yaml deleted file mode 100644 index 25b8297c8..000000000 --- a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/infrastructure/vcluster/99-remove-settings-disabled.yaml +++ /dev/null @@ -1,36 +0,0 @@ -#@ load("@ytt:data", "data") -#@ load("@ytt:overlay", "overlay") -#@ load("functions.star", "isClusterPackageExplicitDisabled") - -#! This removes settings for disabled packages - -#@overlay/match-child-defaults missing_ok=True -clusterPackages: - contour: - #@ if/end isClusterPackageExplicitDisabled("contour"): - #@overlay/replace - settings: {} - cert-manager: - #@ if/end isClusterPackageExplicitDisabled("cert-manager"): - #@overlay/replace - settings: {} - external-dns: - #@ if/end isClusterPackageExplicitDisabled("external-dns"): - #@overlay/replace - settings: {} - certs: - #@ if/end isClusterPackageExplicitDisabled("certs"): - #@overlay/replace - settings: {} - kyverno: - #@ if/end isClusterPackageExplicitDisabled("kyverno"): - #@overlay/replace - settings: {} - kapp-controller: - #@ if/end isClusterPackageExplicitDisabled("kapp-controller"): - #@overlay/replace - settings: {} - #! educates: - #! #@ if/end isClusterPackageExplicitDisabled("educates"): - #! #@overlay/replace - #! settings: {} diff --git a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/infrastructure/vcluster/README.md b/carvel-packages/installer/bundle/config/ytt/_ytt_lib/infrastructure/vcluster/README.md deleted file mode 100644 index 360ccfe91..000000000 --- a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/infrastructure/vcluster/README.md +++ /dev/null @@ -1,6 +0,0 @@ -# generic -By default, only kyverno and educates will be installed -We only allow to enabling/disabling packages at users' risk (except for contour and lookup-service) -No configuration is provided for these packages. - -TODO: Revisit the configuration for some of the packages. Should we allow for enabling external-dns, certs,...? \ No newline at end of file diff --git a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/infrastructure/vcluster/defaults.star b/carvel-packages/installer/bundle/config/ytt/_ytt_lib/infrastructure/vcluster/defaults.star deleted file mode 100644 index 8d7aa8e01..000000000 --- a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/infrastructure/vcluster/defaults.star +++ /dev/null @@ -1,6 +0,0 @@ -load("@ytt:data", "data") - -enabledByDefaultPackagesList = [ - "kyverno", - "educates" -] \ No newline at end of file diff --git a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/infrastructure/vcluster/educates.lib.yaml b/carvel-packages/installer/bundle/config/ytt/_ytt_lib/infrastructure/vcluster/educates.lib.yaml deleted file mode 100644 index 3513efbd6..000000000 --- a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/infrastructure/vcluster/educates.lib.yaml +++ /dev/null @@ -1,176 +0,0 @@ -#@ load("@ytt:data", "data") - -#@ def copy_all_educates_values(): - -#@ if/end hasattr(data.values, "sessionManager") and data.values.sessionManager != None: -sessionManager: - clusterAdmin: #@ data.values.sessionManager.clusterAdmin -#@ if/end hasattr(data.values, "imageRegistry") and data.values.imageRegistry != None: -imageRegistry: - #@ if/end hasattr(data.values.imageRegistry, "namespace") and data.values.imageRegistry.namespace != None: - namespace: #@ data.values.imageRegistry.namespace - #@ if/end hasattr(data.values.imageRegistry, "host") and data.values.imageRegistry.host != None: - host: #@ data.values.imageRegistry.host -#@ if/end hasattr(data.values, "version") and data.values.version != None: -version: #@ data.values.version -#@ if/end hasattr(data.values, "imageVersions") and data.values.imageVersions != None: -imageVersions: #@ data.values.imageVersions -#@ if/end hasattr(data.values, "clusterRuntime") and data.values.clusterRuntime != None: -clusterRuntime: #@ data.values.clusterRuntime -#@ if/end hasattr(data.values, "clusterIngress") and data.values.clusterIngress != None: -clusterIngress: - #@ if/end hasattr(data.values.clusterIngress, "domain") and data.values.clusterIngress.domain != None: - domain: #@ data.values.clusterIngress.domain - #@ if/end hasattr(data.values.clusterIngress, "class") and data.values.clusterIngress["class"] != None: - class: #@ data.values.clusterIngress["class"] - #@ if/end hasattr(data.values.clusterIngress, "protocol") and data.values.clusterIngress.protocol != None: - protocol: #@ data.values.clusterIngress.protocol - #@ if/end hasattr(data.values.clusterIngress, "tlsCertificate") and data.values.clusterIngress.tlsCertificate != None: - tlsCertificate: - #@ if/end hasattr(data.values.clusterIngress.tlsCertificate, "tls.crt") and data.values.clusterIngress.tlsCertificate["tls.crt"] != None: - tls.crt: #@ data.values.clusterIngress.tlsCertificate["tls.crt"] - #@ if/end hasattr(data.values.clusterIngress.tlsCertificate, "tls.key") and data.values.clusterIngress.tlsCertificate["tls.key"] != None: - tls.key: #@ data.values.clusterIngress.tlsCertificate["tls.key"] - #! TODO: Customize certs name reference in eks - #! projectcontour/wildcard - #@ if/end hasattr(data.values.clusterIngress, "tlsCertificateRef") and data.values.clusterIngress.tlsCertificateRef != None: - tlsCertificateRef: - namespace: #@ (hasattr(data.values.clusterIngress.tlsCertificateRef, "namespace") and data.values.clusterIngress.tlsCertificateRef.namespace != None) and data.values.clusterIngress.tlsCertificateRef.namespace or "projectcontour" - #@ if/end hasattr(data.values.clusterIngress.tlsCertificateRef, "name") and data.values.clusterIngress.tlsCertificateRef.name != None: - name: #@ data.values.clusterIngress.tlsCertificateRef.name - #@ if/end hasattr(data.values.clusterIngress, "caCertificate") and data.values.clusterIngress.caCertificate != None: - caCertificate: #@ data.values.clusterIngress.caCertificate - #@ if/end hasattr(data.values.clusterIngress, "caCertificateRef") and data.values.clusterIngress.caCertificateRef != None: - caCertificateRef: - #@ if/end hasattr(data.values.clusterIngress.caCertificateRef, "namespace") and data.values.clusterIngress.caCertificateRef.namespace != None: - namespace: #@ data.values.clusterIngress.caCertificateRef.namespace - #@ if/end hasattr(data.values.clusterIngress.caCertificateRef, "name") and data.values.clusterIngress.caCertificateRef.name != None: - name: #@ data.values.clusterIngress.caCertificateRef.name - #@ if/end hasattr(data.values.clusterIngress, "caNodeInjector") and data.values.clusterIngress.caNodeInjector != None: - caNodeInjector: #@ data.values.clusterIngress.caNodeInjector -#@ if/end hasattr(data.values, "sessionCookies") and data.values.sessionCookies != None: -sessionCookies: #@ data.values.sessionCookies -#@ if/end hasattr(data.values, "clusterStorage") and data.values.clusterStorage != None: -clusterStorage: - #@ if/end hasattr(data.values.clusterStorage, "class") and data.values.clusterStorage["class"] != None: - class: #@ data.values.clusterStorage["class"] - #@ if/end hasattr(data.values.clusterStorage, "user") and data.values.clusterStorage.user != None: - user: #@ data.values.clusterStorage.user - #@ if/end hasattr(data.values.clusterStorage, "group") and data.values.clusterStorage.group != None: - group: #@ data.values.clusterStorage.group -#@ if/end hasattr(data.values, "clusterSecrets") and data.values.clusterSecrets != None: -clusterSecrets: #@ data.values.clusterSecrets -#@ if/end hasattr(data.values, "clusterSecurity") and data.values.clusterSecurity != None: -clusterSecurity: #@ data.values.clusterSecurity -#@ if/end hasattr(data.values, "workshopSecurity") and data.values.workshopSecurity != None: -workshopSecurity: #@ data.values.workshopSecurity -#@ if/end hasattr(data.values, "trainingPortal") and data.values.trainingPortal != None: -trainingPortal: - #@ if/end hasattr(data.values.trainingPortal, "credentials") and data.values.trainingPortal.credentials != None: - credentials: - #@ if/end hasattr(data.values.trainingPortal.credentials, "admin") and data.values.trainingPortal.credentials.admin != None: - admin: - #@ if/end hasattr(data.values.trainingPortal.credentials.admin, "username") and data.values.trainingPortal.credentials.admin.username != None: - username: #@ data.values.trainingPortal.credentials.admin.username - #@ if/end hasattr(data.values.trainingPortal.credentials.admin, "password") and data.values.trainingPortal.credentials.admin.password != None: - password: #@ data.values.trainingPortal.credentials.admin.password - #@ if/end hasattr(data.values.trainingPortal.credentials, "robot") and data.values.trainingPortal.credentials.robot != None: - robot: - #@ if/end hasattr(data.values.trainingPortal.credentials.robot, "username") and data.values.trainingPortal.credentials.robot.username != None: - username: #@ data.values.trainingPortal.credentials.robot.username - #@ if/end hasattr(data.values.trainingPortal.credentials.robot, "password") and data.values.trainingPortal.credentials.robot.password != None: - password: #@ data.values.trainingPortal.credentials.robot.password - #@ if/end hasattr(data.values.trainingPortal, "clients") and data.values.trainingPortal.clients != None: - clients: - #@ if/end hasattr(data.values.trainingPortal.clients, "robot") and data.values.trainingPortal.clients.robot != None: - robot: - #@ if/end hasattr(data.values.trainingPortal.clients.robot, "id") and data.values.trainingPortal.clients.robot.id != None: - id: #@ data.values.trainingPortal.clients.robot.id - #@ if/end hasattr(data.values.trainingPortal.clients.robot, "secret") and data.values.trainingPortal.clients.robot.secret != None: - secret: #@ data.values.trainingPortal.clients.robot.secret -#@ if/end hasattr(data.values, "dockerDaemon") and data.values.dockerDaemon != None: -dockerDaemon: - #@ if/end hasattr(data.values.dockerDaemon, "networkMTU") and data.values.dockerDaemon.networkMTU != None: - networkMTU: #@ data.values.dockerDaemon.networkMTU - #@ if/end hasattr(data.values.dockerDaemon, "proxyCache") and data.values.dockerDaemon.proxyCache != None: - proxyCache: - #@ if/end hasattr(data.values.dockerDaemon.proxyCache, "remoteURL") and data.values.dockerDaemon.proxyCache.remoteURL != None: - remoteURL: #@ data.values.dockerDaemon.proxyCache.remoteURL - #@ if/end hasattr(data.values.dockerDaemon.proxyCache, "username") and data.values.dockerDaemon.proxyCache.username != None: - username: #@ data.values.dockerDaemon.proxyCache.username - #@ if/end hasattr(data.values.dockerDaemon.proxyCache, "password") and data.values.dockerDaemon.proxyCache.password != None: - password: #@ data.values.dockerDaemon.proxyCache.password -#@ if/end hasattr(data.values, "clusterNetwork") and data.values.clusterNetwork != None: -clusterNetwork: #@ data.values.clusterNetwork -#@ if/end hasattr(data.values, "workshopAnalytics") and data.values.workshopAnalytics != None: -workshopAnalytics: - #@ if/end hasattr(data.values.workshopAnalytics, "google") and data.values.workshopAnalytics.google != None: - google: - #@ if/end hasattr(data.values.workshopAnalytics.google, "trackingId") and data.values.workshopAnalytics.google.trackingId != None: - trackingId: #@ data.values.workshopAnalytics.google.trackingId - #@ if/end hasattr(data.values.workshopAnalytics, "clarity") and data.values.workshopAnalytics.clarity != None: - clarity: - #@ if/end hasattr(data.values.workshopAnalytics.clarity, "trackingId") and data.values.workshopAnalytics.clarity.trackingId != None: - trackingId: #@ data.values.workshopAnalytics.clarity.trackingId - #@ if/end hasattr(data.values.workshopAnalytics, "amplitude") and data.values.workshopAnalytics.amplitude != None: - amplitude: - #@ if/end hasattr(data.values.workshopAnalytics.amplitude, "trackingId") and data.values.workshopAnalytics.amplitude.trackingId != None: - trackingId: #@ data.values.workshopAnalytics.amplitude.trackingId - #@ if/end hasattr(data.values.workshopAnalytics, "webhook") and data.values.workshopAnalytics.webhook != None: - webhook: - #@ if/end hasattr(data.values.workshopAnalytics.webhook, "url") and data.values.workshopAnalytics.webhook.url != None: - url: #@ data.values.workshopAnalytics.webhook.url -#@ if/end hasattr(data.values, "websiteStyling") and data.values.websiteStyling != None: -websiteStyling: - #@ if/end hasattr(data.values.websiteStyling, "workshopDashboard") and data.values.websiteStyling.workshopDashboard != None: - workshopDashboard: - #@ if/end hasattr(data.values.websiteStyling.workshopDashboard, "html") and data.values.websiteStyling.workshopDashboard.html != None: - html: #@ data.values.websiteStyling.workshopDashboard.html - #@ if/end hasattr(data.values.websiteStyling.workshopDashboard, "script") and data.values.websiteStyling.workshopDashboard.script != None: - script: #@ data.values.websiteStyling.workshopDashboard.script - #@ if/end hasattr(data.values.websiteStyling.workshopDashboard, "style") and data.values.websiteStyling.workshopDashboard.style != None: - style: #@ data.values.websiteStyling.workshopDashboard.style - #@ if/end hasattr(data.values.websiteStyling, "workshopInstructions") and data.values.websiteStyling.workshopInstructions != None: - workshopInstructions: - #@ if/end hasattr(data.values.websiteStyling.workshopInstructions, "html") and data.values.websiteStyling.workshopInstructions.html != None: - html: #@ data.values.websiteStyling.workshopInstructions.html - #@ if/end hasattr(data.values.websiteStyling.workshopInstructions, "script") and data.values.websiteStyling.workshopInstructions.script != None: - script: #@ data.values.websiteStyling.workshopInstructions.script - #@ if/end hasattr(data.values.websiteStyling.workshopInstructions, "style") and data.values.websiteStyling.workshopInstructions.style != None: - style: #@ data.values.websiteStyling.workshopInstructions.style - #@ if/end hasattr(data.values.websiteStyling, "workshopStarted") and data.values.websiteStyling.workshopStarted != None: - workshopStarted: - #@ if/end hasattr(data.values.websiteStyling.workshopStarted, "html") and data.values.websiteStyling.workshopStarted.html != None: - html: #@ data.values.websiteStyling.workshopStarted.html - #@ if/end hasattr(data.values.websiteStyling, "workshopFinished") and data.values.websiteStyling.workshopFinished != None: - workshopFinished: - #@ if/end hasattr(data.values.websiteStyling.workshopFinished, "html") and data.values.websiteStyling.workshopFinished.html != None: - html: #@ data.values.websiteStyling.workshopFinished.html - #@ if/end hasattr(data.values.websiteStyling, "trainingPortal") and data.values.websiteStyling.trainingPortal != None: - trainingPortal: - #@ if/end hasattr(data.values.websiteStyling.trainingPortal, "html") and data.values.websiteStyling.trainingPortal.html != None: - html: #@ data.values.websiteStyling.trainingPortal.html - #@ if/end hasattr(data.values.websiteStyling.trainingPortal, "script") and data.values.websiteStyling.trainingPortal.script != None: - script: #@ data.values.websiteStyling.trainingPortal.script - #@ if/end hasattr(data.values.websiteStyling.trainingPortal, "style") and data.values.websiteStyling.trainingPortal.style != None: - style: #@ data.values.websiteStyling.trainingPortal.style - #@ if/end hasattr(data.values.websiteStyling, "defaultTheme") and data.values.websiteStyling.defaultTheme != None: - defaultTheme: #@ data.values.websiteStyling.defaultTheme - #@ if/end hasattr(data.values.websiteStyling, "themeDataRefs") and data.values.websiteStyling.themeDataRefs != None: - themeDataRefs: #@ data.values.websiteStyling.themeDataRefs - #@ if/end hasattr(data.values.websiteStyling, "frameAncestors") and data.values.websiteStyling.frameAncestors != None: - frameAncestors: #@ data.values.websiteStyling.frameAncestors -#@ if/end hasattr(data.values, "imagePuller") and data.values.imagePuller != None: -imagePuller: - enabled: #@ data.values.imagePuller.enabled - #@ if hasattr(data.values.imagePuller, "prePullImages") and data.values.imagePuller.prePullImages != None: - #@overlay/replace - prePullImages: #@ data.values.imagePuller.prePullImages - #@ end -#@ if/end hasattr(data.values, "lookupService") and data.values.lookupService != None: -lookupService: - #@ if/end hasattr(data.values.lookupService, "enabled") and data.values.lookupService.enabled != None: - enabled: #@ data.values.lookupService.enabled - #@ if/end hasattr(data.values.lookupService, "ingressPrefix") and data.values.lookupService.ingressPrefix != None: - ingressPrefix: #@ data.values.lookupService.ingressPrefix -#@ end diff --git a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/infrastructure/vcluster/functions.star b/carvel-packages/installer/bundle/config/ytt/_ytt_lib/infrastructure/vcluster/functions.star deleted file mode 100644 index 78ebaa3e7..000000000 --- a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/infrastructure/vcluster/functions.star +++ /dev/null @@ -1,35 +0,0 @@ -load("@ytt:data", "data") -load("defaults.star", "enabledByDefaultPackagesList") - -def isClusterPackageEnableByDefault(package): - return package in enabledByDefaultPackagesList -end - -def isClusterPackageEnabled(package): - if hasattr(data.values, "clusterPackages") and hasattr(data.values.clusterPackages, package) and hasattr(data.values.clusterPackages[package], "enabled"): - return data.values.clusterPackages[package].enabled - else: - return package in enabledByDefaultPackagesList - end -end - -def isClusterPackageExplicitDisabled(package): - return not isClusterPackageEnabled(package) -end - -def xgetattr(object, path, default=None): - def _lookup(object, key, default=None): - keys = key.split(".") - value = default - for key in keys: - value = getattr(object, key, None) - if value == None: - return default - end - object = value - end - return value - end - - return _lookup(object, path, default) -end \ No newline at end of file diff --git a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/cert-manager/overlays/.gitkeep b/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/cert-manager/overlays/.gitkeep deleted file mode 100644 index e69de29bb..000000000 diff --git a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/cert-manager/overlays/functions.star b/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/cert-manager/overlays/functions.star deleted file mode 100644 index 7a24277f5..000000000 --- a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/cert-manager/overlays/functions.star +++ /dev/null @@ -1,14 +0,0 @@ -load("@ytt:data", "data") -load("@ytt:struct", "struct") - -def get_serviceaccount_annotations(): - annotations = {} - - if data.values.serviceaccount.annotations: - annotations_kvs = struct.decode(data.values.serviceaccount.annotations) - annotations.update(annotations_kvs) - end - - return annotations -end - diff --git a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/cert-manager/overlays/overlay-annotations.yaml b/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/cert-manager/overlays/overlay-annotations.yaml deleted file mode 100644 index d6455c678..000000000 --- a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/cert-manager/overlays/overlay-annotations.yaml +++ /dev/null @@ -1,20 +0,0 @@ -#@ load("@ytt:data", "data") -#@ load("@ytt:overlay", "overlay") -#@ load("functions.star", "get_serviceaccount_annotations") - -#@ if hasattr(data.values, "serviceaccount") and hasattr(data.values.serviceaccount, "annotations") and data.values.serviceaccount.annotations!=None: -#@overlay/match by=overlay.subset({"kind":"ServiceAccount", "metadata": {"name": "cert-manager"}}) -#@overlay/match-child-defaults missing_ok=True ---- -metadata: - annotations: #@ get_serviceaccount_annotations() - -#@overlay/match by=overlay.subset({"kind":"Deployment", "metadata": {"name": "cert-manager"}}) -#@overlay/match-child-defaults missing_ok=True ---- -spec: - template: - spec: - securityContext: - fsGroup: 1001 -#@ end diff --git a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/cert-manager/overlays/overlay-cluster-resource-namespace.yaml b/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/cert-manager/overlays/overlay-cluster-resource-namespace.yaml deleted file mode 100644 index 0a1f1e665..000000000 --- a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/cert-manager/overlays/overlay-cluster-resource-namespace.yaml +++ /dev/null @@ -1,14 +0,0 @@ -#@ load("@ytt:data", "data") -#@ load("@ytt:overlay", "overlay") - -#@overlay/match by=overlay.subset({"kind":"Deployment", "metadata": {"name": "cert-manager"}}) ---- -spec: - template: - spec: - containers: - #@overlay/match by="name" - - name: cert-manager-controller - args: - #@overlay/match by=lambda i,l,r: l.startswith("--cluster-resource-namespace=") - - #@ "--cluster-resource-namespace={}".format(data.values.clusterResourceNamespace) diff --git a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/cert-manager/overlays/overlay-leader-election-namespace.yaml b/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/cert-manager/overlays/overlay-leader-election-namespace.yaml deleted file mode 100644 index bd4e603ba..000000000 --- a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/cert-manager/overlays/overlay-leader-election-namespace.yaml +++ /dev/null @@ -1,36 +0,0 @@ -#@ load("@ytt:data", "data") -#@ load("@ytt:overlay", "overlay") - -#@overlay/match by=overlay.subset({"kind":"Deployment", "metadata": {"name": "cert-manager-cainjector"}}) ---- -spec: - template: - spec: - containers: - #@overlay/match by="name" - - name: cert-manager-cainjector - args: - #@overlay/match by=lambda i,l,r: l.startswith("--leader-election-namespace=") - - #@ "--leader-election-namespace={}".format(data.values.leaderElectionNamespace) - -#@overlay/match by=overlay.subset({"kind":"Deployment", "metadata": {"name": "cert-manager"}}) ---- -spec: - template: - spec: - containers: - #@overlay/match by="name" - - name: cert-manager-controller - args: - #@overlay/match by=lambda i,l,r: l.startswith("--leader-election-namespace=") - - #@ "--leader-election-namespace={}".format(data.values.leaderElectionNamespace) - -#@overlay/match by=overlay.subset({"kind":"Role", "metadata": {"namespace": "kube-system"}}),expects=2 ---- -metadata: - namespace: #@ data.values.leaderElectionNamespace - -#@overlay/match by=overlay.subset({"kind":"RoleBinding", "metadata": {"namespace": "kube-system"}}),expects=2 ---- -metadata: - namespace: #@ data.values.leaderElectionNamespace diff --git a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/cert-manager/overlays/overlay-modify-acmeresolver-reference.yaml b/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/cert-manager/overlays/overlay-modify-acmeresolver-reference.yaml deleted file mode 100644 index 4bb7fcea2..000000000 --- a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/cert-manager/overlays/overlay-modify-acmeresolver-reference.yaml +++ /dev/null @@ -1,52 +0,0 @@ -#@ load("@ytt:data", "data") -#@ load("@ytt:overlay", "overlay") -#@ load("@ytt:yaml", "yaml") - -#@ def addImageAnnotation(l,image): -spec: - template: - metadata: - #@overlay/match missing_ok=True - annotations: - #@overlay/match missing_ok=True - acmesolver-image: #@ image -#@ end - -#@ def moveImageName(l,r): -#@ image = "notfound" -#@ if "spec" in l and "template" in l["spec"] and "spec" in l["spec"]["template"] and "containers" in l["spec"]["template"]["spec"]: -#@ for container in l["spec"]["template"]["spec"]["containers"]: -#@ if container["name"] == "cert-manager-controller": -#@ for arg in container["args"]: -#@ if arg.startswith("--acme-http01-solver-image="): -#@ image = arg.split("=")[1] -#@ break -#@ end -#@ end -#@ end -#@ end -#@ end -#@ return overlay.apply(l, addImageAnnotation(l,image)) -#@ end - -#@overlay/match by=overlay.subset({"kind":"Deployment", "metadata": {"name": "cert-manager"}}) -#@overlay/replace via=lambda l,r: moveImageName(l,r) ---- - -#! This third overlay will replace the arg in the container -#@overlay/match by=overlay.subset({"kind":"Deployment", "metadata": {"name": "cert-manager"}}) ---- -spec: - template: - spec: - containers: - #@overlay/match by="name" - - name: cert-manager-controller - args: - #@overlay/match by=lambda i,l,r: l.startswith("--acme-http01-solver-image=") - - #@ "--acme-http01-solver-image=$(ACMESOLVER_IMAGE)" - env: - - name: ACMESOLVER_IMAGE - valueFrom: - fieldRef: - fieldPath: metadata.annotations['acmesolver-image'] diff --git a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/cert-manager/overlays/overlay-namespace.yaml b/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/cert-manager/overlays/overlay-namespace.yaml deleted file mode 100644 index 8605bc05f..000000000 --- a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/cert-manager/overlays/overlay-namespace.yaml +++ /dev/null @@ -1,46 +0,0 @@ -#@ load("@ytt:data", "data") -#@ load("@ytt:overlay", "overlay") - -#@overlay/match by=overlay.subset({"kind":"Namespace", "metadata": {"name": "cert-manager"}}) ---- -apiVersion: v1 -kind: Namespace -metadata: - name: #@ data.values.namespace - -#@overlay/match by=overlay.subset({"metadata": {"namespace": "cert-manager"}}), expects=[10,14] ---- -metadata: - namespace: #@ data.values.namespace - -#@ crb=overlay.subset({"kind":"ClusterRoleBinding"}) -#@ rb=overlay.subset({"kind":"RoleBinding"}) -#@overlay/match by=overlay.or_op(crb, rb), expects=13 ---- -subjects: - #@overlay/match by=overlay.subset({"namespace": "cert-manager"}) - - kind: ServiceAccount - namespace: #@ data.values.namespace - -#@ vwc=overlay.subset({"kind":"ValidatingWebhookConfiguration"}) -#@ mwc=overlay.subset({"kind":"MutatingWebhookConfiguration"}) -#@overlay/match by=overlay.or_op(vwc, mwc), expects=2 ---- -webhooks: - #@overlay/match by="name" - - name: webhook.cert-manager.io - clientConfig: - service: - namespace: #@ data.values.namespace - -#@overlay/match by=overlay.subset({"kind":"MutatingWebhookConfiguration"}) ---- -metadata: - annotations: - cert-manager.io/inject-ca-from-secret: #@ "{}/cert-manager-webhook-ca".format(data.values.namespace) - -#@overlay/match by=overlay.subset({"kind":"ValidatingWebhookConfiguration"}) ---- -metadata: - annotations: - cert-manager.io/inject-ca-from-secret: #@ "{}/cert-manager-webhook-ca".format(data.values.namespace) diff --git a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/cert-manager/overlays/overlay-schema-fixes.yaml b/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/cert-manager/overlays/overlay-schema-fixes.yaml deleted file mode 100644 index 6a6c72600..000000000 --- a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/cert-manager/overlays/overlay-schema-fixes.yaml +++ /dev/null @@ -1,13 +0,0 @@ -#@ load("@ytt:overlay", "overlay") -#@ load("@ytt:data", "data") - -#@ b1 = overlay.subset({"kind":"ClusterRoleBinding", "metadata": {"name": "cert-manager-webhook:subjectaccessreviews"}}) -#@ b2 = overlay.subset({"kind":"RoleBinding", "metadata": {"name": "cert-manager:leaderelection"}}) -#@ b3 = overlay.subset({"kind":"RoleBinding", "metadata": {"name": "cert-manager-webhook:dynamic-serving"}}) -#@overlay/match by=overlay.or_op(b1, b2, b3), expects=3 ---- -subjects: - #@overlay/match by=overlay.subset({"apiGroup":""}) - - kind: ServiceAccount - #@overlay/remove - apiGroup: "" diff --git a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/cert-manager/upstream/cert-manager.yaml b/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/cert-manager/upstream/cert-manager.yaml deleted file mode 100644 index aa0cf726a..000000000 --- a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/cert-manager/upstream/cert-manager.yaml +++ /dev/null @@ -1,5837 +0,0 @@ -# Copyright 2022 The cert-manager Authors. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -apiVersion: v1 -kind: Namespace -metadata: - name: cert-manager ---- -# Source: cert-manager/templates/crds.yaml -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - name: certificaterequests.cert-manager.io - labels: - app: 'cert-manager' - app.kubernetes.io/name: 'cert-manager' - app.kubernetes.io/instance: 'cert-manager' - # Generated labels - app.kubernetes.io/version: "v1.14.7" -spec: - group: cert-manager.io - names: - kind: CertificateRequest - listKind: CertificateRequestList - plural: certificaterequests - shortNames: - - cr - - crs - singular: certificaterequest - categories: - - cert-manager - scope: Namespaced - versions: - - name: v1 - subresources: - status: {} - additionalPrinterColumns: - - jsonPath: .status.conditions[?(@.type=="Approved")].status - name: Approved - type: string - - jsonPath: .status.conditions[?(@.type=="Denied")].status - name: Denied - type: string - - jsonPath: .status.conditions[?(@.type=="Ready")].status - name: Ready - type: string - - jsonPath: .spec.issuerRef.name - name: Issuer - type: string - - jsonPath: .spec.username - name: Requestor - type: string - - jsonPath: .status.conditions[?(@.type=="Ready")].message - name: Status - priority: 1 - type: string - - jsonPath: .metadata.creationTimestamp - description: CreationTimestamp is a timestamp representing the server time when this object was created. It is not guaranteed to be set in happens-before order across separate operations. Clients may not set this value. It is represented in RFC3339 form and is in UTC. - name: Age - type: date - schema: - openAPIV3Schema: - description: "A CertificateRequest is used to request a signed certificate from one of the configured issuers. \n All fields within the CertificateRequest's `spec` are immutable after creation. A CertificateRequest will either succeed or fail, as denoted by its `Ready` status condition and its `status.failureTime` field. \n A CertificateRequest is a one-shot resource, meaning it represents a single point in time request for a certificate and cannot be re-used." - type: object - properties: - apiVersion: - description: 'APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' - type: string - kind: - description: 'Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' - type: string - metadata: - type: object - spec: - description: Specification of the desired state of the CertificateRequest resource. https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#spec-and-status - type: object - required: - - issuerRef - - request - properties: - duration: - description: Requested 'duration' (i.e. lifetime) of the Certificate. Note that the issuer may choose to ignore the requested duration, just like any other requested attribute. - type: string - extra: - description: Extra contains extra attributes of the user that created the CertificateRequest. Populated by the cert-manager webhook on creation and immutable. - type: object - additionalProperties: - type: array - items: - type: string - groups: - description: Groups contains group membership of the user that created the CertificateRequest. Populated by the cert-manager webhook on creation and immutable. - type: array - items: - type: string - x-kubernetes-list-type: atomic - isCA: - description: "Requested basic constraints isCA value. Note that the issuer may choose to ignore the requested isCA value, just like any other requested attribute. \n NOTE: If the CSR in the `Request` field has a BasicConstraints extension, it must have the same isCA value as specified here. \n If true, this will automatically add the `cert sign` usage to the list of requested `usages`." - type: boolean - issuerRef: - description: "Reference to the issuer responsible for issuing the certificate. If the issuer is namespace-scoped, it must be in the same namespace as the Certificate. If the issuer is cluster-scoped, it can be used from any namespace. \n The `name` field of the reference must always be specified." - type: object - required: - - name - properties: - group: - description: Group of the resource being referred to. - type: string - kind: - description: Kind of the resource being referred to. - type: string - name: - description: Name of the resource being referred to. - type: string - request: - description: "The PEM-encoded X.509 certificate signing request to be submitted to the issuer for signing. \n If the CSR has a BasicConstraints extension, its isCA attribute must match the `isCA` value of this CertificateRequest. If the CSR has a KeyUsage extension, its key usages must match the key usages in the `usages` field of this CertificateRequest. If the CSR has a ExtKeyUsage extension, its extended key usages must match the extended key usages in the `usages` field of this CertificateRequest." - type: string - format: byte - uid: - description: UID contains the uid of the user that created the CertificateRequest. Populated by the cert-manager webhook on creation and immutable. - type: string - usages: - description: "Requested key usages and extended key usages. \n NOTE: If the CSR in the `Request` field has uses the KeyUsage or ExtKeyUsage extension, these extensions must have the same values as specified here without any additional values. \n If unset, defaults to `digital signature` and `key encipherment`." - type: array - items: - description: "KeyUsage specifies valid usage contexts for keys. See: https://tools.ietf.org/html/rfc5280#section-4.2.1.3 https://tools.ietf.org/html/rfc5280#section-4.2.1.12 \n Valid KeyUsage values are as follows: \"signing\", \"digital signature\", \"content commitment\", \"key encipherment\", \"key agreement\", \"data encipherment\", \"cert sign\", \"crl sign\", \"encipher only\", \"decipher only\", \"any\", \"server auth\", \"client auth\", \"code signing\", \"email protection\", \"s/mime\", \"ipsec end system\", \"ipsec tunnel\", \"ipsec user\", \"timestamping\", \"ocsp signing\", \"microsoft sgc\", \"netscape sgc\"" - type: string - enum: - - signing - - digital signature - - content commitment - - key encipherment - - key agreement - - data encipherment - - cert sign - - crl sign - - encipher only - - decipher only - - any - - server auth - - client auth - - code signing - - email protection - - s/mime - - ipsec end system - - ipsec tunnel - - ipsec user - - timestamping - - ocsp signing - - microsoft sgc - - netscape sgc - username: - description: Username contains the name of the user that created the CertificateRequest. Populated by the cert-manager webhook on creation and immutable. - type: string - status: - description: 'Status of the CertificateRequest. This is set and managed automatically. Read-only. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#spec-and-status' - type: object - properties: - ca: - description: The PEM encoded X.509 certificate of the signer, also known as the CA (Certificate Authority). This is set on a best-effort basis by different issuers. If not set, the CA is assumed to be unknown/not available. - type: string - format: byte - certificate: - description: The PEM encoded X.509 certificate resulting from the certificate signing request. If not set, the CertificateRequest has either not been completed or has failed. More information on failure can be found by checking the `conditions` field. - type: string - format: byte - conditions: - description: List of status conditions to indicate the status of a CertificateRequest. Known condition types are `Ready`, `InvalidRequest`, `Approved` and `Denied`. - type: array - items: - description: CertificateRequestCondition contains condition information for a CertificateRequest. - type: object - required: - - status - - type - properties: - lastTransitionTime: - description: LastTransitionTime is the timestamp corresponding to the last status change of this condition. - type: string - format: date-time - message: - description: Message is a human readable description of the details of the last transition, complementing reason. - type: string - reason: - description: Reason is a brief machine readable explanation for the condition's last transition. - type: string - status: - description: Status of the condition, one of (`True`, `False`, `Unknown`). - type: string - enum: - - "True" - - "False" - - Unknown - type: - description: Type of the condition, known values are (`Ready`, `InvalidRequest`, `Approved`, `Denied`). - type: string - x-kubernetes-list-map-keys: - - type - x-kubernetes-list-type: map - failureTime: - description: FailureTime stores the time that this CertificateRequest failed. This is used to influence garbage collection and back-off. - type: string - format: date-time - served: true - storage: true ---- -# Source: cert-manager/templates/crds.yaml -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - name: certificates.cert-manager.io - labels: - app: 'cert-manager' - app.kubernetes.io/name: 'cert-manager' - app.kubernetes.io/instance: 'cert-manager' - # Generated labels - app.kubernetes.io/version: "v1.14.7" -spec: - group: cert-manager.io - names: - kind: Certificate - listKind: CertificateList - plural: certificates - shortNames: - - cert - - certs - singular: certificate - categories: - - cert-manager - scope: Namespaced - versions: - - name: v1 - subresources: - status: {} - additionalPrinterColumns: - - jsonPath: .status.conditions[?(@.type=="Ready")].status - name: Ready - type: string - - jsonPath: .spec.secretName - name: Secret - type: string - - jsonPath: .spec.issuerRef.name - name: Issuer - priority: 1 - type: string - - jsonPath: .status.conditions[?(@.type=="Ready")].message - name: Status - priority: 1 - type: string - - jsonPath: .metadata.creationTimestamp - description: CreationTimestamp is a timestamp representing the server time when this object was created. It is not guaranteed to be set in happens-before order across separate operations. Clients may not set this value. It is represented in RFC3339 form and is in UTC. - name: Age - type: date - schema: - openAPIV3Schema: - description: "A Certificate resource should be created to ensure an up to date and signed X.509 certificate is stored in the Kubernetes Secret resource named in `spec.secretName`. \n The stored certificate will be renewed before it expires (as configured by `spec.renewBefore`)." - type: object - properties: - apiVersion: - description: 'APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' - type: string - kind: - description: 'Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' - type: string - metadata: - type: object - spec: - description: Specification of the desired state of the Certificate resource. https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#spec-and-status - type: object - required: - - issuerRef - - secretName - properties: - additionalOutputFormats: - description: "Defines extra output formats of the private key and signed certificate chain to be written to this Certificate's target Secret. \n This is an Alpha Feature and is only enabled with the `--feature-gates=AdditionalCertificateOutputFormats=true` option set on both the controller and webhook components." - type: array - items: - description: CertificateAdditionalOutputFormat defines an additional output format of a Certificate resource. These contain supplementary data formats of the signed certificate chain and paired private key. - type: object - required: - - type - properties: - type: - description: Type is the name of the format type that should be written to the Certificate's target Secret. - type: string - enum: - - DER - - CombinedPEM - commonName: - description: "Requested common name X509 certificate subject attribute. More info: https://datatracker.ietf.org/doc/html/rfc5280#section-4.1.2.6 NOTE: TLS clients will ignore this value when any subject alternative name is set (see https://tools.ietf.org/html/rfc6125#section-6.4.4). \n Should have a length of 64 characters or fewer to avoid generating invalid CSRs. Cannot be set if the `literalSubject` field is set." - type: string - dnsNames: - description: Requested DNS subject alternative names. - type: array - items: - type: string - duration: - description: "Requested 'duration' (i.e. lifetime) of the Certificate. Note that the issuer may choose to ignore the requested duration, just like any other requested attribute. \n If unset, this defaults to 90 days. Minimum accepted duration is 1 hour. Value must be in units accepted by Go time.ParseDuration https://golang.org/pkg/time/#ParseDuration." - type: string - emailAddresses: - description: Requested email subject alternative names. - type: array - items: - type: string - encodeUsagesInRequest: - description: "Whether the KeyUsage and ExtKeyUsage extensions should be set in the encoded CSR. \n This option defaults to true, and should only be disabled if the target issuer does not support CSRs with these X509 KeyUsage/ ExtKeyUsage extensions." - type: boolean - ipAddresses: - description: Requested IP address subject alternative names. - type: array - items: - type: string - isCA: - description: "Requested basic constraints isCA value. The isCA value is used to set the `isCA` field on the created CertificateRequest resources. Note that the issuer may choose to ignore the requested isCA value, just like any other requested attribute. \n If true, this will automatically add the `cert sign` usage to the list of requested `usages`." - type: boolean - issuerRef: - description: "Reference to the issuer responsible for issuing the certificate. If the issuer is namespace-scoped, it must be in the same namespace as the Certificate. If the issuer is cluster-scoped, it can be used from any namespace. \n The `name` field of the reference must always be specified." - type: object - required: - - name - properties: - group: - description: Group of the resource being referred to. - type: string - kind: - description: Kind of the resource being referred to. - type: string - name: - description: Name of the resource being referred to. - type: string - keystores: - description: Additional keystore output formats to be stored in the Certificate's Secret. - type: object - properties: - jks: - description: JKS configures options for storing a JKS keystore in the `spec.secretName` Secret resource. - type: object - required: - - create - - passwordSecretRef - properties: - create: - description: Create enables JKS keystore creation for the Certificate. If true, a file named `keystore.jks` will be created in the target Secret resource, encrypted using the password stored in `passwordSecretRef`. The keystore file will be updated immediately. If the issuer provided a CA certificate, a file named `truststore.jks` will also be created in the target Secret resource, encrypted using the password stored in `passwordSecretRef` containing the issuing Certificate Authority - type: boolean - passwordSecretRef: - description: PasswordSecretRef is a reference to a key in a Secret resource containing the password used to encrypt the JKS keystore. - type: object - required: - - name - properties: - key: - description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. - type: string - name: - description: 'Name of the resource being referred to. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' - type: string - pkcs12: - description: PKCS12 configures options for storing a PKCS12 keystore in the `spec.secretName` Secret resource. - type: object - required: - - create - - passwordSecretRef - properties: - create: - description: Create enables PKCS12 keystore creation for the Certificate. If true, a file named `keystore.p12` will be created in the target Secret resource, encrypted using the password stored in `passwordSecretRef`. The keystore file will be updated immediately. If the issuer provided a CA certificate, a file named `truststore.p12` will also be created in the target Secret resource, encrypted using the password stored in `passwordSecretRef` containing the issuing Certificate Authority - type: boolean - passwordSecretRef: - description: PasswordSecretRef is a reference to a key in a Secret resource containing the password used to encrypt the PKCS12 keystore. - type: object - required: - - name - properties: - key: - description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. - type: string - name: - description: 'Name of the resource being referred to. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' - type: string - profile: - description: "Profile specifies the key and certificate encryption algorithms and the HMAC algorithm used to create the PKCS12 keystore. Default value is `LegacyRC2` for backward compatibility. \n If provided, allowed values are: `LegacyRC2`: Deprecated. Not supported by default in OpenSSL 3 or Java 20. `LegacyDES`: Less secure algorithm. Use this option for maximal compatibility. `Modern2023`: Secure algorithm. Use this option in case you have to always use secure algorithms (eg. because of company policy). Please note that the security of the algorithm is not that important in reality, because the unencrypted certificate and private key are also stored in the Secret." - type: string - enum: - - LegacyRC2 - - LegacyDES - - Modern2023 - literalSubject: - description: "Requested X.509 certificate subject, represented using the LDAP \"String Representation of a Distinguished Name\" [1]. Important: the LDAP string format also specifies the order of the attributes in the subject, this is important when issuing certs for LDAP authentication. Example: `CN=foo,DC=corp,DC=example,DC=com` More info [1]: https://datatracker.ietf.org/doc/html/rfc4514 More info: https://github.com/cert-manager/cert-manager/issues/3203 More info: https://github.com/cert-manager/cert-manager/issues/4424 \n Cannot be set if the `subject` or `commonName` field is set. This is an Alpha Feature and is only enabled with the `--feature-gates=LiteralCertificateSubject=true` option set on both the controller and webhook components." - type: string - nameConstraints: - description: "x.509 certificate NameConstraint extension which MUST NOT be used in a non-CA certificate. More Info: https://datatracker.ietf.org/doc/html/rfc5280#section-4.2.1.10 \n This is an Alpha Feature and is only enabled with the `--feature-gates=NameConstraints=true` option set on both the controller and webhook components." - type: object - properties: - critical: - description: if true then the name constraints are marked critical. - type: boolean - excluded: - description: Excluded contains the constraints which must be disallowed. Any name matching a restriction in the excluded field is invalid regardless of information appearing in the permitted - type: object - properties: - dnsDomains: - description: DNSDomains is a list of DNS domains that are permitted or excluded. - type: array - items: - type: string - emailAddresses: - description: EmailAddresses is a list of Email Addresses that are permitted or excluded. - type: array - items: - type: string - ipRanges: - description: IPRanges is a list of IP Ranges that are permitted or excluded. This should be a valid CIDR notation. - type: array - items: - type: string - uriDomains: - description: URIDomains is a list of URI domains that are permitted or excluded. - type: array - items: - type: string - permitted: - description: Permitted contains the constraints in which the names must be located. - type: object - properties: - dnsDomains: - description: DNSDomains is a list of DNS domains that are permitted or excluded. - type: array - items: - type: string - emailAddresses: - description: EmailAddresses is a list of Email Addresses that are permitted or excluded. - type: array - items: - type: string - ipRanges: - description: IPRanges is a list of IP Ranges that are permitted or excluded. This should be a valid CIDR notation. - type: array - items: - type: string - uriDomains: - description: URIDomains is a list of URI domains that are permitted or excluded. - type: array - items: - type: string - otherNames: - description: '`otherNames` is an escape hatch for SAN that allows any type. We currently restrict the support to string like otherNames, cf RFC 5280 p 37 Any UTF8 String valued otherName can be passed with by setting the keys oid: x.x.x.x and UTF8Value: somevalue for `otherName`. Most commonly this would be UPN set with oid: 1.3.6.1.4.1.311.20.2.3 You should ensure that any OID passed is valid for the UTF8String type as we do not explicitly validate this.' - type: array - items: - type: object - properties: - oid: - description: OID is the object identifier for the otherName SAN. The object identifier must be expressed as a dotted string, for example, "1.2.840.113556.1.4.221". - type: string - utf8Value: - description: utf8Value is the string value of the otherName SAN. The utf8Value accepts any valid UTF8 string to set as value for the otherName SAN. - type: string - privateKey: - description: Private key options. These include the key algorithm and size, the used encoding and the rotation policy. - type: object - properties: - algorithm: - description: "Algorithm is the private key algorithm of the corresponding private key for this certificate. \n If provided, allowed values are either `RSA`, `ECDSA` or `Ed25519`. If `algorithm` is specified and `size` is not provided, key size of 2048 will be used for `RSA` key algorithm and key size of 256 will be used for `ECDSA` key algorithm. key size is ignored when using the `Ed25519` key algorithm." - type: string - enum: - - RSA - - ECDSA - - Ed25519 - encoding: - description: "The private key cryptography standards (PKCS) encoding for this certificate's private key to be encoded in. \n If provided, allowed values are `PKCS1` and `PKCS8` standing for PKCS#1 and PKCS#8, respectively. Defaults to `PKCS1` if not specified." - type: string - enum: - - PKCS1 - - PKCS8 - rotationPolicy: - description: "RotationPolicy controls how private keys should be regenerated when a re-issuance is being processed. \n If set to `Never`, a private key will only be generated if one does not already exist in the target `spec.secretName`. If one does exists but it does not have the correct algorithm or size, a warning will be raised to await user intervention. If set to `Always`, a private key matching the specified requirements will be generated whenever a re-issuance occurs. Default is `Never` for backward compatibility." - type: string - enum: - - Never - - Always - size: - description: "Size is the key bit size of the corresponding private key for this certificate. \n If `algorithm` is set to `RSA`, valid values are `2048`, `4096` or `8192`, and will default to `2048` if not specified. If `algorithm` is set to `ECDSA`, valid values are `256`, `384` or `521`, and will default to `256` if not specified. If `algorithm` is set to `Ed25519`, Size is ignored. No other values are allowed." - type: integer - renewBefore: - description: "How long before the currently issued certificate's expiry cert-manager should renew the certificate. For example, if a certificate is valid for 60 minutes, and `renewBefore=10m`, cert-manager will begin to attempt to renew the certificate 50 minutes after it was issued (i.e. when there are 10 minutes remaining until the certificate is no longer valid). \n NOTE: The actual lifetime of the issued certificate is used to determine the renewal time. If an issuer returns a certificate with a different lifetime than the one requested, cert-manager will use the lifetime of the issued certificate. \n If unset, this defaults to 1/3 of the issued certificate's lifetime. Minimum accepted value is 5 minutes. Value must be in units accepted by Go time.ParseDuration https://golang.org/pkg/time/#ParseDuration." - type: string - revisionHistoryLimit: - description: "The maximum number of CertificateRequest revisions that are maintained in the Certificate's history. Each revision represents a single `CertificateRequest` created by this Certificate, either when it was created, renewed, or Spec was changed. Revisions will be removed by oldest first if the number of revisions exceeds this number. \n If set, revisionHistoryLimit must be a value of `1` or greater. If unset (`nil`), revisions will not be garbage collected. Default value is `nil`." - type: integer - format: int32 - secretName: - description: Name of the Secret resource that will be automatically created and managed by this Certificate resource. It will be populated with a private key and certificate, signed by the denoted issuer. The Secret resource lives in the same namespace as the Certificate resource. - type: string - secretTemplate: - description: Defines annotations and labels to be copied to the Certificate's Secret. Labels and annotations on the Secret will be changed as they appear on the SecretTemplate when added or removed. SecretTemplate annotations are added in conjunction with, and cannot overwrite, the base set of annotations cert-manager sets on the Certificate's Secret. - type: object - properties: - annotations: - description: Annotations is a key value map to be copied to the target Kubernetes Secret. - type: object - additionalProperties: - type: string - labels: - description: Labels is a key value map to be copied to the target Kubernetes Secret. - type: object - additionalProperties: - type: string - subject: - description: "Requested set of X509 certificate subject attributes. More info: https://datatracker.ietf.org/doc/html/rfc5280#section-4.1.2.6 \n The common name attribute is specified separately in the `commonName` field. Cannot be set if the `literalSubject` field is set." - type: object - properties: - countries: - description: Countries to be used on the Certificate. - type: array - items: - type: string - localities: - description: Cities to be used on the Certificate. - type: array - items: - type: string - organizationalUnits: - description: Organizational Units to be used on the Certificate. - type: array - items: - type: string - organizations: - description: Organizations to be used on the Certificate. - type: array - items: - type: string - postalCodes: - description: Postal codes to be used on the Certificate. - type: array - items: - type: string - provinces: - description: State/Provinces to be used on the Certificate. - type: array - items: - type: string - serialNumber: - description: Serial number to be used on the Certificate. - type: string - streetAddresses: - description: Street addresses to be used on the Certificate. - type: array - items: - type: string - uris: - description: Requested URI subject alternative names. - type: array - items: - type: string - usages: - description: "Requested key usages and extended key usages. These usages are used to set the `usages` field on the created CertificateRequest resources. If `encodeUsagesInRequest` is unset or set to `true`, the usages will additionally be encoded in the `request` field which contains the CSR blob. \n If unset, defaults to `digital signature` and `key encipherment`." - type: array - items: - description: "KeyUsage specifies valid usage contexts for keys. See: https://tools.ietf.org/html/rfc5280#section-4.2.1.3 https://tools.ietf.org/html/rfc5280#section-4.2.1.12 \n Valid KeyUsage values are as follows: \"signing\", \"digital signature\", \"content commitment\", \"key encipherment\", \"key agreement\", \"data encipherment\", \"cert sign\", \"crl sign\", \"encipher only\", \"decipher only\", \"any\", \"server auth\", \"client auth\", \"code signing\", \"email protection\", \"s/mime\", \"ipsec end system\", \"ipsec tunnel\", \"ipsec user\", \"timestamping\", \"ocsp signing\", \"microsoft sgc\", \"netscape sgc\"" - type: string - enum: - - signing - - digital signature - - content commitment - - key encipherment - - key agreement - - data encipherment - - cert sign - - crl sign - - encipher only - - decipher only - - any - - server auth - - client auth - - code signing - - email protection - - s/mime - - ipsec end system - - ipsec tunnel - - ipsec user - - timestamping - - ocsp signing - - microsoft sgc - - netscape sgc - status: - description: 'Status of the Certificate. This is set and managed automatically. Read-only. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#spec-and-status' - type: object - properties: - conditions: - description: List of status conditions to indicate the status of certificates. Known condition types are `Ready` and `Issuing`. - type: array - items: - description: CertificateCondition contains condition information for an Certificate. - type: object - required: - - status - - type - properties: - lastTransitionTime: - description: LastTransitionTime is the timestamp corresponding to the last status change of this condition. - type: string - format: date-time - message: - description: Message is a human readable description of the details of the last transition, complementing reason. - type: string - observedGeneration: - description: If set, this represents the .metadata.generation that the condition was set based upon. For instance, if .metadata.generation is currently 12, but the .status.condition[x].observedGeneration is 9, the condition is out of date with respect to the current state of the Certificate. - type: integer - format: int64 - reason: - description: Reason is a brief machine readable explanation for the condition's last transition. - type: string - status: - description: Status of the condition, one of (`True`, `False`, `Unknown`). - type: string - enum: - - "True" - - "False" - - Unknown - type: - description: Type of the condition, known values are (`Ready`, `Issuing`). - type: string - x-kubernetes-list-map-keys: - - type - x-kubernetes-list-type: map - failedIssuanceAttempts: - description: The number of continuous failed issuance attempts up till now. This field gets removed (if set) on a successful issuance and gets set to 1 if unset and an issuance has failed. If an issuance has failed, the delay till the next issuance will be calculated using formula time.Hour * 2 ^ (failedIssuanceAttempts - 1). - type: integer - lastFailureTime: - description: LastFailureTime is set only if the lastest issuance for this Certificate failed and contains the time of the failure. If an issuance has failed, the delay till the next issuance will be calculated using formula time.Hour * 2 ^ (failedIssuanceAttempts - 1). If the latest issuance has succeeded this field will be unset. - type: string - format: date-time - nextPrivateKeySecretName: - description: The name of the Secret resource containing the private key to be used for the next certificate iteration. The keymanager controller will automatically set this field if the `Issuing` condition is set to `True`. It will automatically unset this field when the Issuing condition is not set or False. - type: string - notAfter: - description: The expiration time of the certificate stored in the secret named by this resource in `spec.secretName`. - type: string - format: date-time - notBefore: - description: The time after which the certificate stored in the secret named by this resource in `spec.secretName` is valid. - type: string - format: date-time - renewalTime: - description: RenewalTime is the time at which the certificate will be next renewed. If not set, no upcoming renewal is scheduled. - type: string - format: date-time - revision: - description: "The current 'revision' of the certificate as issued. \n When a CertificateRequest resource is created, it will have the `cert-manager.io/certificate-revision` set to one greater than the current value of this field. \n Upon issuance, this field will be set to the value of the annotation on the CertificateRequest resource used to issue the certificate. \n Persisting the value on the CertificateRequest resource allows the certificates controller to know whether a request is part of an old issuance or if it is part of the ongoing revision's issuance by checking if the revision value in the annotation is greater than this field." - type: integer - served: true - storage: true ---- -# Source: cert-manager/templates/crds.yaml -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - name: challenges.acme.cert-manager.io - labels: - app: 'cert-manager' - app.kubernetes.io/name: 'cert-manager' - app.kubernetes.io/instance: 'cert-manager' - # Generated labels - app.kubernetes.io/version: "v1.14.7" -spec: - group: acme.cert-manager.io - names: - kind: Challenge - listKind: ChallengeList - plural: challenges - singular: challenge - categories: - - cert-manager - - cert-manager-acme - scope: Namespaced - versions: - - additionalPrinterColumns: - - jsonPath: .status.state - name: State - type: string - - jsonPath: .spec.dnsName - name: Domain - type: string - - jsonPath: .status.reason - name: Reason - priority: 1 - type: string - - description: CreationTimestamp is a timestamp representing the server time when this object was created. It is not guaranteed to be set in happens-before order across separate operations. Clients may not set this value. It is represented in RFC3339 form and is in UTC. - jsonPath: .metadata.creationTimestamp - name: Age - type: date - name: v1 - schema: - openAPIV3Schema: - description: Challenge is a type to represent a Challenge request with an ACME server - type: object - required: - - metadata - - spec - properties: - apiVersion: - description: 'APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' - type: string - kind: - description: 'Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' - type: string - metadata: - type: object - spec: - type: object - required: - - authorizationURL - - dnsName - - issuerRef - - key - - solver - - token - - type - - url - properties: - authorizationURL: - description: The URL to the ACME Authorization resource that this challenge is a part of. - type: string - dnsName: - description: dnsName is the identifier that this challenge is for, e.g. example.com. If the requested DNSName is a 'wildcard', this field MUST be set to the non-wildcard domain, e.g. for `*.example.com`, it must be `example.com`. - type: string - issuerRef: - description: References a properly configured ACME-type Issuer which should be used to create this Challenge. If the Issuer does not exist, processing will be retried. If the Issuer is not an 'ACME' Issuer, an error will be returned and the Challenge will be marked as failed. - type: object - required: - - name - properties: - group: - description: Group of the resource being referred to. - type: string - kind: - description: Kind of the resource being referred to. - type: string - name: - description: Name of the resource being referred to. - type: string - key: - description: 'The ACME challenge key for this challenge For HTTP01 challenges, this is the value that must be responded with to complete the HTTP01 challenge in the format: `.`. For DNS01 challenges, this is the base64 encoded SHA256 sum of the `.` text that must be set as the TXT record content.' - type: string - solver: - description: Contains the domain solving configuration that should be used to solve this challenge resource. - type: object - properties: - dns01: - description: Configures cert-manager to attempt to complete authorizations by performing the DNS01 challenge flow. - type: object - properties: - acmeDNS: - description: Use the 'ACME DNS' (https://github.com/joohoi/acme-dns) API to manage DNS01 challenge records. - type: object - required: - - accountSecretRef - - host - properties: - accountSecretRef: - description: A reference to a specific 'key' within a Secret resource. In some instances, `key` is a required field. - type: object - required: - - name - properties: - key: - description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. - type: string - name: - description: 'Name of the resource being referred to. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' - type: string - host: - type: string - akamai: - description: Use the Akamai DNS zone management API to manage DNS01 challenge records. - type: object - required: - - accessTokenSecretRef - - clientSecretSecretRef - - clientTokenSecretRef - - serviceConsumerDomain - properties: - accessTokenSecretRef: - description: A reference to a specific 'key' within a Secret resource. In some instances, `key` is a required field. - type: object - required: - - name - properties: - key: - description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. - type: string - name: - description: 'Name of the resource being referred to. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' - type: string - clientSecretSecretRef: - description: A reference to a specific 'key' within a Secret resource. In some instances, `key` is a required field. - type: object - required: - - name - properties: - key: - description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. - type: string - name: - description: 'Name of the resource being referred to. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' - type: string - clientTokenSecretRef: - description: A reference to a specific 'key' within a Secret resource. In some instances, `key` is a required field. - type: object - required: - - name - properties: - key: - description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. - type: string - name: - description: 'Name of the resource being referred to. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' - type: string - serviceConsumerDomain: - type: string - azureDNS: - description: Use the Microsoft Azure DNS API to manage DNS01 challenge records. - type: object - required: - - resourceGroupName - - subscriptionID - properties: - clientID: - description: 'Auth: Azure Service Principal: The ClientID of the Azure Service Principal used to authenticate with Azure DNS. If set, ClientSecret and TenantID must also be set.' - type: string - clientSecretSecretRef: - description: 'Auth: Azure Service Principal: A reference to a Secret containing the password associated with the Service Principal. If set, ClientID and TenantID must also be set.' - type: object - required: - - name - properties: - key: - description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. - type: string - name: - description: 'Name of the resource being referred to. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' - type: string - environment: - description: name of the Azure environment (default AzurePublicCloud) - type: string - enum: - - AzurePublicCloud - - AzureChinaCloud - - AzureGermanCloud - - AzureUSGovernmentCloud - hostedZoneName: - description: name of the DNS zone that should be used - type: string - managedIdentity: - description: 'Auth: Azure Workload Identity or Azure Managed Service Identity: Settings to enable Azure Workload Identity or Azure Managed Service Identity If set, ClientID, ClientSecret and TenantID must not be set.' - type: object - properties: - clientID: - description: client ID of the managed identity, can not be used at the same time as resourceID - type: string - resourceID: - description: resource ID of the managed identity, can not be used at the same time as clientID Cannot be used for Azure Managed Service Identity - type: string - resourceGroupName: - description: resource group the DNS zone is located in - type: string - subscriptionID: - description: ID of the Azure subscription - type: string - tenantID: - description: 'Auth: Azure Service Principal: The TenantID of the Azure Service Principal used to authenticate with Azure DNS. If set, ClientID and ClientSecret must also be set.' - type: string - cloudDNS: - description: Use the Google Cloud DNS API to manage DNS01 challenge records. - type: object - required: - - project - properties: - hostedZoneName: - description: HostedZoneName is an optional field that tells cert-manager in which Cloud DNS zone the challenge record has to be created. If left empty cert-manager will automatically choose a zone. - type: string - project: - type: string - serviceAccountSecretRef: - description: A reference to a specific 'key' within a Secret resource. In some instances, `key` is a required field. - type: object - required: - - name - properties: - key: - description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. - type: string - name: - description: 'Name of the resource being referred to. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' - type: string - cloudflare: - description: Use the Cloudflare API to manage DNS01 challenge records. - type: object - properties: - apiKeySecretRef: - description: 'API key to use to authenticate with Cloudflare. Note: using an API token to authenticate is now the recommended method as it allows greater control of permissions.' - type: object - required: - - name - properties: - key: - description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. - type: string - name: - description: 'Name of the resource being referred to. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' - type: string - apiTokenSecretRef: - description: API token used to authenticate with Cloudflare. - type: object - required: - - name - properties: - key: - description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. - type: string - name: - description: 'Name of the resource being referred to. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' - type: string - email: - description: Email of the account, only required when using API key based authentication. - type: string - cnameStrategy: - description: CNAMEStrategy configures how the DNS01 provider should handle CNAME records when found in DNS zones. - type: string - enum: - - None - - Follow - digitalocean: - description: Use the DigitalOcean DNS API to manage DNS01 challenge records. - type: object - required: - - tokenSecretRef - properties: - tokenSecretRef: - description: A reference to a specific 'key' within a Secret resource. In some instances, `key` is a required field. - type: object - required: - - name - properties: - key: - description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. - type: string - name: - description: 'Name of the resource being referred to. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' - type: string - rfc2136: - description: Use RFC2136 ("Dynamic Updates in the Domain Name System") (https://datatracker.ietf.org/doc/rfc2136/) to manage DNS01 challenge records. - type: object - required: - - nameserver - properties: - nameserver: - description: The IP address or hostname of an authoritative DNS server supporting RFC2136 in the form host:port. If the host is an IPv6 address it must be enclosed in square brackets (e.g [2001:db8::1]) ; port is optional. This field is required. - type: string - tsigAlgorithm: - description: 'The TSIG Algorithm configured in the DNS supporting RFC2136. Used only when ``tsigSecretSecretRef`` and ``tsigKeyName`` are defined. Supported values are (case-insensitive): ``HMACMD5`` (default), ``HMACSHA1``, ``HMACSHA256`` or ``HMACSHA512``.' - type: string - tsigKeyName: - description: The TSIG Key name configured in the DNS. If ``tsigSecretSecretRef`` is defined, this field is required. - type: string - tsigSecretSecretRef: - description: The name of the secret containing the TSIG value. If ``tsigKeyName`` is defined, this field is required. - type: object - required: - - name - properties: - key: - description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. - type: string - name: - description: 'Name of the resource being referred to. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' - type: string - route53: - description: Use the AWS Route53 API to manage DNS01 challenge records. - type: object - required: - - region - properties: - accessKeyID: - description: 'The AccessKeyID is used for authentication. Cannot be set when SecretAccessKeyID is set. If neither the Access Key nor Key ID are set, we fall-back to using env vars, shared credentials file or AWS Instance metadata, see: https://docs.aws.amazon.com/sdk-for-go/v1/developer-guide/configuring-sdk.html#specifying-credentials' - type: string - accessKeyIDSecretRef: - description: 'The SecretAccessKey is used for authentication. If set, pull the AWS access key ID from a key within a Kubernetes Secret. Cannot be set when AccessKeyID is set. If neither the Access Key nor Key ID are set, we fall-back to using env vars, shared credentials file or AWS Instance metadata, see: https://docs.aws.amazon.com/sdk-for-go/v1/developer-guide/configuring-sdk.html#specifying-credentials' - type: object - required: - - name - properties: - key: - description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. - type: string - name: - description: 'Name of the resource being referred to. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' - type: string - hostedZoneID: - description: If set, the provider will manage only this zone in Route53 and will not do an lookup using the route53:ListHostedZonesByName api call. - type: string - region: - description: Always set the region when using AccessKeyID and SecretAccessKey - type: string - role: - description: Role is a Role ARN which the Route53 provider will assume using either the explicit credentials AccessKeyID/SecretAccessKey or the inferred credentials from environment variables, shared credentials file or AWS Instance metadata - type: string - secretAccessKeySecretRef: - description: 'The SecretAccessKey is used for authentication. If neither the Access Key nor Key ID are set, we fall-back to using env vars, shared credentials file or AWS Instance metadata, see: https://docs.aws.amazon.com/sdk-for-go/v1/developer-guide/configuring-sdk.html#specifying-credentials' - type: object - required: - - name - properties: - key: - description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. - type: string - name: - description: 'Name of the resource being referred to. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' - type: string - webhook: - description: Configure an external webhook based DNS01 challenge solver to manage DNS01 challenge records. - type: object - required: - - groupName - - solverName - properties: - config: - description: Additional configuration that should be passed to the webhook apiserver when challenges are processed. This can contain arbitrary JSON data. Secret values should not be specified in this stanza. If secret values are needed (e.g. credentials for a DNS service), you should use a SecretKeySelector to reference a Secret resource. For details on the schema of this field, consult the webhook provider implementation's documentation. - x-kubernetes-preserve-unknown-fields: true - groupName: - description: The API group name that should be used when POSTing ChallengePayload resources to the webhook apiserver. This should be the same as the GroupName specified in the webhook provider implementation. - type: string - solverName: - description: The name of the solver to use, as defined in the webhook provider implementation. This will typically be the name of the provider, e.g. 'cloudflare'. - type: string - http01: - description: Configures cert-manager to attempt to complete authorizations by performing the HTTP01 challenge flow. It is not possible to obtain certificates for wildcard domain names (e.g. `*.example.com`) using the HTTP01 challenge mechanism. - type: object - properties: - gatewayHTTPRoute: - description: The Gateway API is a sig-network community API that models service networking in Kubernetes (https://gateway-api.sigs.k8s.io/). The Gateway solver will create HTTPRoutes with the specified labels in the same namespace as the challenge. This solver is experimental, and fields / behaviour may change in the future. - type: object - properties: - labels: - description: Custom labels that will be applied to HTTPRoutes created by cert-manager while solving HTTP-01 challenges. - type: object - additionalProperties: - type: string - parentRefs: - description: 'When solving an HTTP-01 challenge, cert-manager creates an HTTPRoute. cert-manager needs to know which parentRefs should be used when creating the HTTPRoute. Usually, the parentRef references a Gateway. See: https://gateway-api.sigs.k8s.io/api-types/httproute/#attaching-to-gateways' - type: array - items: - description: "ParentReference identifies an API object (usually a Gateway) that can be considered a parent of this resource (usually a route). There are two kinds of parent resources with \"Core\" support: \n * Gateway (Gateway conformance profile) * Service (Mesh conformance profile, experimental, ClusterIP Services only) \n This API may be extended in the future to support additional kinds of parent resources. \n The API object must be valid in the cluster; the Group and Kind must be registered in the cluster for this reference to be valid." - type: object - required: - - name - properties: - group: - description: "Group is the group of the referent. When unspecified, \"gateway.networking.k8s.io\" is inferred. To set the core API group (such as for a \"Service\" kind referent), Group must be explicitly set to \"\" (empty string). \n Support: Core" - type: string - default: gateway.networking.k8s.io - maxLength: 253 - pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ - kind: - description: "Kind is kind of the referent. \n There are two kinds of parent resources with \"Core\" support: \n * Gateway (Gateway conformance profile) * Service (Mesh conformance profile, experimental, ClusterIP Services only) \n Support for other resources is Implementation-Specific." - type: string - default: Gateway - maxLength: 63 - minLength: 1 - pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ - name: - description: "Name is the name of the referent. \n Support: Core" - type: string - maxLength: 253 - minLength: 1 - namespace: - description: "Namespace is the namespace of the referent. When unspecified, this refers to the local namespace of the Route. \n Note that there are specific rules for ParentRefs which cross namespace boundaries. Cross-namespace references are only valid if they are explicitly allowed by something in the namespace they are referring to. For example: Gateway has the AllowedRoutes field, and ReferenceGrant provides a generic way to enable any other kind of cross-namespace reference. \n ParentRefs from a Route to a Service in the same namespace are \"producer\" routes, which apply default routing rules to inbound connections from any namespace to the Service. \n ParentRefs from a Route to a Service in a different namespace are \"consumer\" routes, and these routing rules are only applied to outbound connections originating from the same namespace as the Route, for which the intended destination of the connections are a Service targeted as a ParentRef of the Route. \n Support: Core" - type: string - maxLength: 63 - minLength: 1 - pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ - port: - description: "Port is the network port this Route targets. It can be interpreted differently based on the type of parent resource. \n When the parent resource is a Gateway, this targets all listeners listening on the specified port that also support this kind of Route(and select this Route). It's not recommended to set `Port` unless the networking behaviors specified in a Route must apply to a specific port as opposed to a listener(s) whose port(s) may be changed. When both Port and SectionName are specified, the name and port of the selected listener must match both specified values. \n When the parent resource is a Service, this targets a specific port in the Service spec. When both Port (experimental) and SectionName are specified, the name and port of the selected port must match both specified values. \n Implementations MAY choose to support other parent resources. Implementations supporting other types of parent resources MUST clearly document how/if Port is interpreted. \n For the purpose of status, an attachment is considered successful as long as the parent resource accepts it partially. For example, Gateway listeners can restrict which Routes can attach to them by Route kind, namespace, or hostname. If 1 of 2 Gateway listeners accept attachment from the referencing Route, the Route MUST be considered successfully attached. If no Gateway listeners accept attachment from this Route, the Route MUST be considered detached from the Gateway. \n Support: Extended \n " - type: integer - format: int32 - maximum: 65535 - minimum: 1 - sectionName: - description: "SectionName is the name of a section within the target resource. In the following resources, SectionName is interpreted as the following: \n * Gateway: Listener Name. When both Port (experimental) and SectionName are specified, the name and port of the selected listener must match both specified values. * Service: Port Name. When both Port (experimental) and SectionName are specified, the name and port of the selected listener must match both specified values. Note that attaching Routes to Services as Parents is part of experimental Mesh support and is not supported for any other purpose. \n Implementations MAY choose to support attaching Routes to other resources. If that is the case, they MUST clearly document how SectionName is interpreted. \n When unspecified (empty string), this will reference the entire resource. For the purpose of status, an attachment is considered successful if at least one section in the parent resource accepts it. For example, Gateway listeners can restrict which Routes can attach to them by Route kind, namespace, or hostname. If 1 of 2 Gateway listeners accept attachment from the referencing Route, the Route MUST be considered successfully attached. If no Gateway listeners accept attachment from this Route, the Route MUST be considered detached from the Gateway. \n Support: Core" - type: string - maxLength: 253 - minLength: 1 - pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ - serviceType: - description: Optional service type for Kubernetes solver service. Supported values are NodePort or ClusterIP. If unset, defaults to NodePort. - type: string - ingress: - description: The ingress based HTTP01 challenge solver will solve challenges by creating or modifying Ingress resources in order to route requests for '/.well-known/acme-challenge/XYZ' to 'challenge solver' pods that are provisioned by cert-manager for each Challenge to be completed. - type: object - properties: - class: - description: This field configures the annotation `kubernetes.io/ingress.class` when creating Ingress resources to solve ACME challenges that use this challenge solver. Only one of `class`, `name` or `ingressClassName` may be specified. - type: string - ingressClassName: - description: This field configures the field `ingressClassName` on the created Ingress resources used to solve ACME challenges that use this challenge solver. This is the recommended way of configuring the ingress class. Only one of `class`, `name` or `ingressClassName` may be specified. - type: string - ingressTemplate: - description: Optional ingress template used to configure the ACME challenge solver ingress used for HTTP01 challenges. - type: object - properties: - metadata: - description: ObjectMeta overrides for the ingress used to solve HTTP01 challenges. Only the 'labels' and 'annotations' fields may be set. If labels or annotations overlap with in-built values, the values here will override the in-built values. - type: object - properties: - annotations: - description: Annotations that should be added to the created ACME HTTP01 solver ingress. - type: object - additionalProperties: - type: string - labels: - description: Labels that should be added to the created ACME HTTP01 solver ingress. - type: object - additionalProperties: - type: string - name: - description: The name of the ingress resource that should have ACME challenge solving routes inserted into it in order to solve HTTP01 challenges. This is typically used in conjunction with ingress controllers like ingress-gce, which maintains a 1:1 mapping between external IPs and ingress resources. Only one of `class`, `name` or `ingressClassName` may be specified. - type: string - podTemplate: - description: Optional pod template used to configure the ACME challenge solver pods used for HTTP01 challenges. - type: object - properties: - metadata: - description: ObjectMeta overrides for the pod used to solve HTTP01 challenges. Only the 'labels' and 'annotations' fields may be set. If labels or annotations overlap with in-built values, the values here will override the in-built values. - type: object - properties: - annotations: - description: Annotations that should be added to the create ACME HTTP01 solver pods. - type: object - additionalProperties: - type: string - labels: - description: Labels that should be added to the created ACME HTTP01 solver pods. - type: object - additionalProperties: - type: string - spec: - description: PodSpec defines overrides for the HTTP01 challenge solver pod. Check ACMEChallengeSolverHTTP01IngressPodSpec to find out currently supported fields. All other fields will be ignored. - type: object - properties: - affinity: - description: If specified, the pod's scheduling constraints - type: object - properties: - nodeAffinity: - description: Describes node affinity scheduling rules for the pod. - type: object - properties: - preferredDuringSchedulingIgnoredDuringExecution: - description: The scheduler will prefer to schedule pods to nodes that satisfy the affinity expressions specified by this field, but it may choose a node that violates one or more of the expressions. The node that is most preferred is the one with the greatest sum of weights, i.e. for each node that meets all of the scheduling requirements (resource request, requiredDuringScheduling affinity expressions, etc.), compute a sum by iterating through the elements of this field and adding "weight" to the sum if the node matches the corresponding matchExpressions; the node(s) with the highest sum are the most preferred. - type: array - items: - description: An empty preferred scheduling term matches all objects with implicit weight 0 (i.e. it's a no-op). A null preferred scheduling term matches no objects (i.e. is also a no-op). - type: object - required: - - preference - - weight - properties: - preference: - description: A node selector term, associated with the corresponding weight. - type: object - properties: - matchExpressions: - description: A list of node selector requirements by node's labels. - type: array - items: - description: A node selector requirement is a selector that contains values, a key, and an operator that relates the key and values. - type: object - required: - - key - - operator - properties: - key: - description: The label key that the selector applies to. - type: string - operator: - description: Represents a key's relationship to a set of values. Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. - type: string - values: - description: An array of string values. If the operator is In or NotIn, the values array must be non-empty. If the operator is Exists or DoesNotExist, the values array must be empty. If the operator is Gt or Lt, the values array must have a single element, which will be interpreted as an integer. This array is replaced during a strategic merge patch. - type: array - items: - type: string - matchFields: - description: A list of node selector requirements by node's fields. - type: array - items: - description: A node selector requirement is a selector that contains values, a key, and an operator that relates the key and values. - type: object - required: - - key - - operator - properties: - key: - description: The label key that the selector applies to. - type: string - operator: - description: Represents a key's relationship to a set of values. Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. - type: string - values: - description: An array of string values. If the operator is In or NotIn, the values array must be non-empty. If the operator is Exists or DoesNotExist, the values array must be empty. If the operator is Gt or Lt, the values array must have a single element, which will be interpreted as an integer. This array is replaced during a strategic merge patch. - type: array - items: - type: string - x-kubernetes-map-type: atomic - weight: - description: Weight associated with matching the corresponding nodeSelectorTerm, in the range 1-100. - type: integer - format: int32 - requiredDuringSchedulingIgnoredDuringExecution: - description: If the affinity requirements specified by this field are not met at scheduling time, the pod will not be scheduled onto the node. If the affinity requirements specified by this field cease to be met at some point during pod execution (e.g. due to an update), the system may or may not try to eventually evict the pod from its node. - type: object - required: - - nodeSelectorTerms - properties: - nodeSelectorTerms: - description: Required. A list of node selector terms. The terms are ORed. - type: array - items: - description: A null or empty node selector term matches no objects. The requirements of them are ANDed. The TopologySelectorTerm type implements a subset of the NodeSelectorTerm. - type: object - properties: - matchExpressions: - description: A list of node selector requirements by node's labels. - type: array - items: - description: A node selector requirement is a selector that contains values, a key, and an operator that relates the key and values. - type: object - required: - - key - - operator - properties: - key: - description: The label key that the selector applies to. - type: string - operator: - description: Represents a key's relationship to a set of values. Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. - type: string - values: - description: An array of string values. If the operator is In or NotIn, the values array must be non-empty. If the operator is Exists or DoesNotExist, the values array must be empty. If the operator is Gt or Lt, the values array must have a single element, which will be interpreted as an integer. This array is replaced during a strategic merge patch. - type: array - items: - type: string - matchFields: - description: A list of node selector requirements by node's fields. - type: array - items: - description: A node selector requirement is a selector that contains values, a key, and an operator that relates the key and values. - type: object - required: - - key - - operator - properties: - key: - description: The label key that the selector applies to. - type: string - operator: - description: Represents a key's relationship to a set of values. Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. - type: string - values: - description: An array of string values. If the operator is In or NotIn, the values array must be non-empty. If the operator is Exists or DoesNotExist, the values array must be empty. If the operator is Gt or Lt, the values array must have a single element, which will be interpreted as an integer. This array is replaced during a strategic merge patch. - type: array - items: - type: string - x-kubernetes-map-type: atomic - x-kubernetes-map-type: atomic - podAffinity: - description: Describes pod affinity scheduling rules (e.g. co-locate this pod in the same node, zone, etc. as some other pod(s)). - type: object - properties: - preferredDuringSchedulingIgnoredDuringExecution: - description: The scheduler will prefer to schedule pods to nodes that satisfy the affinity expressions specified by this field, but it may choose a node that violates one or more of the expressions. The node that is most preferred is the one with the greatest sum of weights, i.e. for each node that meets all of the scheduling requirements (resource request, requiredDuringScheduling affinity expressions, etc.), compute a sum by iterating through the elements of this field and adding "weight" to the sum if the node has pods which matches the corresponding podAffinityTerm; the node(s) with the highest sum are the most preferred. - type: array - items: - description: The weights of all of the matched WeightedPodAffinityTerm fields are added per-node to find the most preferred node(s) - type: object - required: - - podAffinityTerm - - weight - properties: - podAffinityTerm: - description: Required. A pod affinity term, associated with the corresponding weight. - type: object - required: - - topologyKey - properties: - labelSelector: - description: A label query over a set of resources, in this case pods. If it's null, this PodAffinityTerm matches with no Pods. - type: object - properties: - matchExpressions: - description: matchExpressions is a list of label selector requirements. The requirements are ANDed. - type: array - items: - description: A label selector requirement is a selector that contains values, a key, and an operator that relates the key and values. - type: object - required: - - key - - operator - properties: - key: - description: key is the label key that the selector applies to. - type: string - operator: - description: operator represents a key's relationship to a set of values. Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: values is an array of string values. If the operator is In or NotIn, the values array must be non-empty. If the operator is Exists or DoesNotExist, the values array must be empty. This array is replaced during a strategic merge patch. - type: array - items: - type: string - matchLabels: - description: matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels map is equivalent to an element of matchExpressions, whose key field is "key", the operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - additionalProperties: - type: string - x-kubernetes-map-type: atomic - matchLabelKeys: - description: MatchLabelKeys is a set of pod label keys to select which pods will be taken into consideration. The keys are used to lookup values from the incoming pod labels, those key-value labels are merged with `LabelSelector` as `key in (value)` to select the group of existing pods which pods will be taken into consideration for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both MatchLabelKeys and LabelSelector. Also, MatchLabelKeys cannot be set when LabelSelector isn't set. This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. - type: array - items: - type: string - x-kubernetes-list-type: atomic - mismatchLabelKeys: - description: MismatchLabelKeys is a set of pod label keys to select which pods will be taken into consideration. The keys are used to lookup values from the incoming pod labels, those key-value labels are merged with `LabelSelector` as `key notin (value)` to select the group of existing pods which pods will be taken into consideration for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both MismatchLabelKeys and LabelSelector. Also, MismatchLabelKeys cannot be set when LabelSelector isn't set. This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. - type: array - items: - type: string - x-kubernetes-list-type: atomic - namespaceSelector: - description: A label query over the set of namespaces that the term applies to. The term is applied to the union of the namespaces selected by this field and the ones listed in the namespaces field. null selector and null or empty namespaces list means "this pod's namespace". An empty selector ({}) matches all namespaces. - type: object - properties: - matchExpressions: - description: matchExpressions is a list of label selector requirements. The requirements are ANDed. - type: array - items: - description: A label selector requirement is a selector that contains values, a key, and an operator that relates the key and values. - type: object - required: - - key - - operator - properties: - key: - description: key is the label key that the selector applies to. - type: string - operator: - description: operator represents a key's relationship to a set of values. Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: values is an array of string values. If the operator is In or NotIn, the values array must be non-empty. If the operator is Exists or DoesNotExist, the values array must be empty. This array is replaced during a strategic merge patch. - type: array - items: - type: string - matchLabels: - description: matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels map is equivalent to an element of matchExpressions, whose key field is "key", the operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - additionalProperties: - type: string - x-kubernetes-map-type: atomic - namespaces: - description: namespaces specifies a static list of namespace names that the term applies to. The term is applied to the union of the namespaces listed in this field and the ones selected by namespaceSelector. null or empty namespaces list and null namespaceSelector means "this pod's namespace". - type: array - items: - type: string - topologyKey: - description: This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching the labelSelector in the specified namespaces, where co-located is defined as running on a node whose value of the label with key topologyKey matches that of any node on which any of the selected pods is running. Empty topologyKey is not allowed. - type: string - weight: - description: weight associated with matching the corresponding podAffinityTerm, in the range 1-100. - type: integer - format: int32 - requiredDuringSchedulingIgnoredDuringExecution: - description: If the affinity requirements specified by this field are not met at scheduling time, the pod will not be scheduled onto the node. If the affinity requirements specified by this field cease to be met at some point during pod execution (e.g. due to a pod label update), the system may or may not try to eventually evict the pod from its node. When there are multiple elements, the lists of nodes corresponding to each podAffinityTerm are intersected, i.e. all terms must be satisfied. - type: array - items: - description: Defines a set of pods (namely those matching the labelSelector relative to the given namespace(s)) that this pod should be co-located (affinity) or not co-located (anti-affinity) with, where co-located is defined as running on a node whose value of the label with key matches that of any node on which a pod of the set of pods is running - type: object - required: - - topologyKey - properties: - labelSelector: - description: A label query over a set of resources, in this case pods. If it's null, this PodAffinityTerm matches with no Pods. - type: object - properties: - matchExpressions: - description: matchExpressions is a list of label selector requirements. The requirements are ANDed. - type: array - items: - description: A label selector requirement is a selector that contains values, a key, and an operator that relates the key and values. - type: object - required: - - key - - operator - properties: - key: - description: key is the label key that the selector applies to. - type: string - operator: - description: operator represents a key's relationship to a set of values. Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: values is an array of string values. If the operator is In or NotIn, the values array must be non-empty. If the operator is Exists or DoesNotExist, the values array must be empty. This array is replaced during a strategic merge patch. - type: array - items: - type: string - matchLabels: - description: matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels map is equivalent to an element of matchExpressions, whose key field is "key", the operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - additionalProperties: - type: string - x-kubernetes-map-type: atomic - matchLabelKeys: - description: MatchLabelKeys is a set of pod label keys to select which pods will be taken into consideration. The keys are used to lookup values from the incoming pod labels, those key-value labels are merged with `LabelSelector` as `key in (value)` to select the group of existing pods which pods will be taken into consideration for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both MatchLabelKeys and LabelSelector. Also, MatchLabelKeys cannot be set when LabelSelector isn't set. This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. - type: array - items: - type: string - x-kubernetes-list-type: atomic - mismatchLabelKeys: - description: MismatchLabelKeys is a set of pod label keys to select which pods will be taken into consideration. The keys are used to lookup values from the incoming pod labels, those key-value labels are merged with `LabelSelector` as `key notin (value)` to select the group of existing pods which pods will be taken into consideration for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both MismatchLabelKeys and LabelSelector. Also, MismatchLabelKeys cannot be set when LabelSelector isn't set. This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. - type: array - items: - type: string - x-kubernetes-list-type: atomic - namespaceSelector: - description: A label query over the set of namespaces that the term applies to. The term is applied to the union of the namespaces selected by this field and the ones listed in the namespaces field. null selector and null or empty namespaces list means "this pod's namespace". An empty selector ({}) matches all namespaces. - type: object - properties: - matchExpressions: - description: matchExpressions is a list of label selector requirements. The requirements are ANDed. - type: array - items: - description: A label selector requirement is a selector that contains values, a key, and an operator that relates the key and values. - type: object - required: - - key - - operator - properties: - key: - description: key is the label key that the selector applies to. - type: string - operator: - description: operator represents a key's relationship to a set of values. Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: values is an array of string values. If the operator is In or NotIn, the values array must be non-empty. If the operator is Exists or DoesNotExist, the values array must be empty. This array is replaced during a strategic merge patch. - type: array - items: - type: string - matchLabels: - description: matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels map is equivalent to an element of matchExpressions, whose key field is "key", the operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - additionalProperties: - type: string - x-kubernetes-map-type: atomic - namespaces: - description: namespaces specifies a static list of namespace names that the term applies to. The term is applied to the union of the namespaces listed in this field and the ones selected by namespaceSelector. null or empty namespaces list and null namespaceSelector means "this pod's namespace". - type: array - items: - type: string - topologyKey: - description: This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching the labelSelector in the specified namespaces, where co-located is defined as running on a node whose value of the label with key topologyKey matches that of any node on which any of the selected pods is running. Empty topologyKey is not allowed. - type: string - podAntiAffinity: - description: Describes pod anti-affinity scheduling rules (e.g. avoid putting this pod in the same node, zone, etc. as some other pod(s)). - type: object - properties: - preferredDuringSchedulingIgnoredDuringExecution: - description: The scheduler will prefer to schedule pods to nodes that satisfy the anti-affinity expressions specified by this field, but it may choose a node that violates one or more of the expressions. The node that is most preferred is the one with the greatest sum of weights, i.e. for each node that meets all of the scheduling requirements (resource request, requiredDuringScheduling anti-affinity expressions, etc.), compute a sum by iterating through the elements of this field and adding "weight" to the sum if the node has pods which matches the corresponding podAffinityTerm; the node(s) with the highest sum are the most preferred. - type: array - items: - description: The weights of all of the matched WeightedPodAffinityTerm fields are added per-node to find the most preferred node(s) - type: object - required: - - podAffinityTerm - - weight - properties: - podAffinityTerm: - description: Required. A pod affinity term, associated with the corresponding weight. - type: object - required: - - topologyKey - properties: - labelSelector: - description: A label query over a set of resources, in this case pods. If it's null, this PodAffinityTerm matches with no Pods. - type: object - properties: - matchExpressions: - description: matchExpressions is a list of label selector requirements. The requirements are ANDed. - type: array - items: - description: A label selector requirement is a selector that contains values, a key, and an operator that relates the key and values. - type: object - required: - - key - - operator - properties: - key: - description: key is the label key that the selector applies to. - type: string - operator: - description: operator represents a key's relationship to a set of values. Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: values is an array of string values. If the operator is In or NotIn, the values array must be non-empty. If the operator is Exists or DoesNotExist, the values array must be empty. This array is replaced during a strategic merge patch. - type: array - items: - type: string - matchLabels: - description: matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels map is equivalent to an element of matchExpressions, whose key field is "key", the operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - additionalProperties: - type: string - x-kubernetes-map-type: atomic - matchLabelKeys: - description: MatchLabelKeys is a set of pod label keys to select which pods will be taken into consideration. The keys are used to lookup values from the incoming pod labels, those key-value labels are merged with `LabelSelector` as `key in (value)` to select the group of existing pods which pods will be taken into consideration for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both MatchLabelKeys and LabelSelector. Also, MatchLabelKeys cannot be set when LabelSelector isn't set. This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. - type: array - items: - type: string - x-kubernetes-list-type: atomic - mismatchLabelKeys: - description: MismatchLabelKeys is a set of pod label keys to select which pods will be taken into consideration. The keys are used to lookup values from the incoming pod labels, those key-value labels are merged with `LabelSelector` as `key notin (value)` to select the group of existing pods which pods will be taken into consideration for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both MismatchLabelKeys and LabelSelector. Also, MismatchLabelKeys cannot be set when LabelSelector isn't set. This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. - type: array - items: - type: string - x-kubernetes-list-type: atomic - namespaceSelector: - description: A label query over the set of namespaces that the term applies to. The term is applied to the union of the namespaces selected by this field and the ones listed in the namespaces field. null selector and null or empty namespaces list means "this pod's namespace". An empty selector ({}) matches all namespaces. - type: object - properties: - matchExpressions: - description: matchExpressions is a list of label selector requirements. The requirements are ANDed. - type: array - items: - description: A label selector requirement is a selector that contains values, a key, and an operator that relates the key and values. - type: object - required: - - key - - operator - properties: - key: - description: key is the label key that the selector applies to. - type: string - operator: - description: operator represents a key's relationship to a set of values. Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: values is an array of string values. If the operator is In or NotIn, the values array must be non-empty. If the operator is Exists or DoesNotExist, the values array must be empty. This array is replaced during a strategic merge patch. - type: array - items: - type: string - matchLabels: - description: matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels map is equivalent to an element of matchExpressions, whose key field is "key", the operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - additionalProperties: - type: string - x-kubernetes-map-type: atomic - namespaces: - description: namespaces specifies a static list of namespace names that the term applies to. The term is applied to the union of the namespaces listed in this field and the ones selected by namespaceSelector. null or empty namespaces list and null namespaceSelector means "this pod's namespace". - type: array - items: - type: string - topologyKey: - description: This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching the labelSelector in the specified namespaces, where co-located is defined as running on a node whose value of the label with key topologyKey matches that of any node on which any of the selected pods is running. Empty topologyKey is not allowed. - type: string - weight: - description: weight associated with matching the corresponding podAffinityTerm, in the range 1-100. - type: integer - format: int32 - requiredDuringSchedulingIgnoredDuringExecution: - description: If the anti-affinity requirements specified by this field are not met at scheduling time, the pod will not be scheduled onto the node. If the anti-affinity requirements specified by this field cease to be met at some point during pod execution (e.g. due to a pod label update), the system may or may not try to eventually evict the pod from its node. When there are multiple elements, the lists of nodes corresponding to each podAffinityTerm are intersected, i.e. all terms must be satisfied. - type: array - items: - description: Defines a set of pods (namely those matching the labelSelector relative to the given namespace(s)) that this pod should be co-located (affinity) or not co-located (anti-affinity) with, where co-located is defined as running on a node whose value of the label with key matches that of any node on which a pod of the set of pods is running - type: object - required: - - topologyKey - properties: - labelSelector: - description: A label query over a set of resources, in this case pods. If it's null, this PodAffinityTerm matches with no Pods. - type: object - properties: - matchExpressions: - description: matchExpressions is a list of label selector requirements. The requirements are ANDed. - type: array - items: - description: A label selector requirement is a selector that contains values, a key, and an operator that relates the key and values. - type: object - required: - - key - - operator - properties: - key: - description: key is the label key that the selector applies to. - type: string - operator: - description: operator represents a key's relationship to a set of values. Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: values is an array of string values. If the operator is In or NotIn, the values array must be non-empty. If the operator is Exists or DoesNotExist, the values array must be empty. This array is replaced during a strategic merge patch. - type: array - items: - type: string - matchLabels: - description: matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels map is equivalent to an element of matchExpressions, whose key field is "key", the operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - additionalProperties: - type: string - x-kubernetes-map-type: atomic - matchLabelKeys: - description: MatchLabelKeys is a set of pod label keys to select which pods will be taken into consideration. The keys are used to lookup values from the incoming pod labels, those key-value labels are merged with `LabelSelector` as `key in (value)` to select the group of existing pods which pods will be taken into consideration for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both MatchLabelKeys and LabelSelector. Also, MatchLabelKeys cannot be set when LabelSelector isn't set. This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. - type: array - items: - type: string - x-kubernetes-list-type: atomic - mismatchLabelKeys: - description: MismatchLabelKeys is a set of pod label keys to select which pods will be taken into consideration. The keys are used to lookup values from the incoming pod labels, those key-value labels are merged with `LabelSelector` as `key notin (value)` to select the group of existing pods which pods will be taken into consideration for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both MismatchLabelKeys and LabelSelector. Also, MismatchLabelKeys cannot be set when LabelSelector isn't set. This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. - type: array - items: - type: string - x-kubernetes-list-type: atomic - namespaceSelector: - description: A label query over the set of namespaces that the term applies to. The term is applied to the union of the namespaces selected by this field and the ones listed in the namespaces field. null selector and null or empty namespaces list means "this pod's namespace". An empty selector ({}) matches all namespaces. - type: object - properties: - matchExpressions: - description: matchExpressions is a list of label selector requirements. The requirements are ANDed. - type: array - items: - description: A label selector requirement is a selector that contains values, a key, and an operator that relates the key and values. - type: object - required: - - key - - operator - properties: - key: - description: key is the label key that the selector applies to. - type: string - operator: - description: operator represents a key's relationship to a set of values. Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: values is an array of string values. If the operator is In or NotIn, the values array must be non-empty. If the operator is Exists or DoesNotExist, the values array must be empty. This array is replaced during a strategic merge patch. - type: array - items: - type: string - matchLabels: - description: matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels map is equivalent to an element of matchExpressions, whose key field is "key", the operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - additionalProperties: - type: string - x-kubernetes-map-type: atomic - namespaces: - description: namespaces specifies a static list of namespace names that the term applies to. The term is applied to the union of the namespaces listed in this field and the ones selected by namespaceSelector. null or empty namespaces list and null namespaceSelector means "this pod's namespace". - type: array - items: - type: string - topologyKey: - description: This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching the labelSelector in the specified namespaces, where co-located is defined as running on a node whose value of the label with key topologyKey matches that of any node on which any of the selected pods is running. Empty topologyKey is not allowed. - type: string - imagePullSecrets: - description: If specified, the pod's imagePullSecrets - type: array - items: - description: LocalObjectReference contains enough information to let you locate the referenced object inside the same namespace. - type: object - properties: - name: - description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names TODO: Add other useful fields. apiVersion, kind, uid?' - type: string - x-kubernetes-map-type: atomic - nodeSelector: - description: 'NodeSelector is a selector which must be true for the pod to fit on a node. Selector which must match a node''s labels for the pod to be scheduled on that node. More info: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/' - type: object - additionalProperties: - type: string - priorityClassName: - description: If specified, the pod's priorityClassName. - type: string - serviceAccountName: - description: If specified, the pod's service account - type: string - tolerations: - description: If specified, the pod's tolerations. - type: array - items: - description: The pod this Toleration is attached to tolerates any taint that matches the triple using the matching operator . - type: object - properties: - effect: - description: Effect indicates the taint effect to match. Empty means match all taint effects. When specified, allowed values are NoSchedule, PreferNoSchedule and NoExecute. - type: string - key: - description: Key is the taint key that the toleration applies to. Empty means match all taint keys. If the key is empty, operator must be Exists; this combination means to match all values and all keys. - type: string - operator: - description: Operator represents a key's relationship to the value. Valid operators are Exists and Equal. Defaults to Equal. Exists is equivalent to wildcard for value, so that a pod can tolerate all taints of a particular category. - type: string - tolerationSeconds: - description: TolerationSeconds represents the period of time the toleration (which must be of effect NoExecute, otherwise this field is ignored) tolerates the taint. By default, it is not set, which means tolerate the taint forever (do not evict). Zero and negative values will be treated as 0 (evict immediately) by the system. - type: integer - format: int64 - value: - description: Value is the taint value the toleration matches to. If the operator is Exists, the value should be empty, otherwise just a regular string. - type: string - serviceType: - description: Optional service type for Kubernetes solver service. Supported values are NodePort or ClusterIP. If unset, defaults to NodePort. - type: string - selector: - description: Selector selects a set of DNSNames on the Certificate resource that should be solved using this challenge solver. If not specified, the solver will be treated as the 'default' solver with the lowest priority, i.e. if any other solver has a more specific match, it will be used instead. - type: object - properties: - dnsNames: - description: List of DNSNames that this solver will be used to solve. If specified and a match is found, a dnsNames selector will take precedence over a dnsZones selector. If multiple solvers match with the same dnsNames value, the solver with the most matching labels in matchLabels will be selected. If neither has more matches, the solver defined earlier in the list will be selected. - type: array - items: - type: string - dnsZones: - description: List of DNSZones that this solver will be used to solve. The most specific DNS zone match specified here will take precedence over other DNS zone matches, so a solver specifying sys.example.com will be selected over one specifying example.com for the domain www.sys.example.com. If multiple solvers match with the same dnsZones value, the solver with the most matching labels in matchLabels will be selected. If neither has more matches, the solver defined earlier in the list will be selected. - type: array - items: - type: string - matchLabels: - description: A label selector that is used to refine the set of certificate's that this challenge solver will apply to. - type: object - additionalProperties: - type: string - token: - description: The ACME challenge token for this challenge. This is the raw value returned from the ACME server. - type: string - type: - description: The type of ACME challenge this resource represents. One of "HTTP-01" or "DNS-01". - type: string - enum: - - HTTP-01 - - DNS-01 - url: - description: The URL of the ACME Challenge resource for this challenge. This can be used to lookup details about the status of this challenge. - type: string - wildcard: - description: wildcard will be true if this challenge is for a wildcard identifier, for example '*.example.com'. - type: boolean - status: - type: object - properties: - presented: - description: presented will be set to true if the challenge values for this challenge are currently 'presented'. This *does not* imply the self check is passing. Only that the values have been 'submitted' for the appropriate challenge mechanism (i.e. the DNS01 TXT record has been presented, or the HTTP01 configuration has been configured). - type: boolean - processing: - description: Used to denote whether this challenge should be processed or not. This field will only be set to true by the 'scheduling' component. It will only be set to false by the 'challenges' controller, after the challenge has reached a final state or timed out. If this field is set to false, the challenge controller will not take any more action. - type: boolean - reason: - description: Contains human readable information on why the Challenge is in the current state. - type: string - state: - description: Contains the current 'state' of the challenge. If not set, the state of the challenge is unknown. - type: string - enum: - - valid - - ready - - pending - - processing - - invalid - - expired - - errored - served: true - storage: true - subresources: - status: {} ---- -# Source: cert-manager/templates/crds.yaml -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - name: clusterissuers.cert-manager.io - labels: - app: 'cert-manager' - app.kubernetes.io/name: 'cert-manager' - app.kubernetes.io/instance: "cert-manager" - # Generated labels - app.kubernetes.io/version: "v1.14.7" -spec: - group: cert-manager.io - names: - kind: ClusterIssuer - listKind: ClusterIssuerList - plural: clusterissuers - singular: clusterissuer - categories: - - cert-manager - scope: Cluster - versions: - - name: v1 - subresources: - status: {} - additionalPrinterColumns: - - jsonPath: .status.conditions[?(@.type=="Ready")].status - name: Ready - type: string - - jsonPath: .status.conditions[?(@.type=="Ready")].message - name: Status - priority: 1 - type: string - - jsonPath: .metadata.creationTimestamp - description: CreationTimestamp is a timestamp representing the server time when this object was created. It is not guaranteed to be set in happens-before order across separate operations. Clients may not set this value. It is represented in RFC3339 form and is in UTC. - name: Age - type: date - schema: - openAPIV3Schema: - description: A ClusterIssuer represents a certificate issuing authority which can be referenced as part of `issuerRef` fields. It is similar to an Issuer, however it is cluster-scoped and therefore can be referenced by resources that exist in *any* namespace, not just the same namespace as the referent. - type: object - required: - - spec - properties: - apiVersion: - description: 'APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' - type: string - kind: - description: 'Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' - type: string - metadata: - type: object - spec: - description: Desired state of the ClusterIssuer resource. - type: object - properties: - acme: - description: ACME configures this issuer to communicate with a RFC8555 (ACME) server to obtain signed x509 certificates. - type: object - required: - - privateKeySecretRef - - server - properties: - caBundle: - description: Base64-encoded bundle of PEM CAs which can be used to validate the certificate chain presented by the ACME server. Mutually exclusive with SkipTLSVerify; prefer using CABundle to prevent various kinds of security vulnerabilities. If CABundle and SkipTLSVerify are unset, the system certificate bundle inside the container is used to validate the TLS connection. - type: string - format: byte - disableAccountKeyGeneration: - description: Enables or disables generating a new ACME account key. If true, the Issuer resource will *not* request a new account but will expect the account key to be supplied via an existing secret. If false, the cert-manager system will generate a new ACME account key for the Issuer. Defaults to false. - type: boolean - email: - description: Email is the email address to be associated with the ACME account. This field is optional, but it is strongly recommended to be set. It will be used to contact you in case of issues with your account or certificates, including expiry notification emails. This field may be updated after the account is initially registered. - type: string - enableDurationFeature: - description: Enables requesting a Not After date on certificates that matches the duration of the certificate. This is not supported by all ACME servers like Let's Encrypt. If set to true when the ACME server does not support it it will create an error on the Order. Defaults to false. - type: boolean - externalAccountBinding: - description: ExternalAccountBinding is a reference to a CA external account of the ACME server. If set, upon registration cert-manager will attempt to associate the given external account credentials with the registered ACME account. - type: object - required: - - keyID - - keySecretRef - properties: - keyAlgorithm: - description: 'Deprecated: keyAlgorithm field exists for historical compatibility reasons and should not be used. The algorithm is now hardcoded to HS256 in golang/x/crypto/acme.' - type: string - enum: - - HS256 - - HS384 - - HS512 - keyID: - description: keyID is the ID of the CA key that the External Account is bound to. - type: string - keySecretRef: - description: keySecretRef is a Secret Key Selector referencing a data item in a Kubernetes Secret which holds the symmetric MAC key of the External Account Binding. The `key` is the index string that is paired with the key data in the Secret and should not be confused with the key data itself, or indeed with the External Account Binding keyID above. The secret key stored in the Secret **must** be un-padded, base64 URL encoded data. - type: object - required: - - name - properties: - key: - description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. - type: string - name: - description: 'Name of the resource being referred to. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' - type: string - preferredChain: - description: 'PreferredChain is the chain to use if the ACME server outputs multiple. PreferredChain is no guarantee that this one gets delivered by the ACME endpoint. For example, for Let''s Encrypt''s DST crosssign you would use: "DST Root CA X3" or "ISRG Root X1" for the newer Let''s Encrypt root CA. This value picks the first certificate bundle in the ACME alternative chains that has a certificate with this value as its issuer''s CN' - type: string - maxLength: 64 - privateKeySecretRef: - description: PrivateKey is the name of a Kubernetes Secret resource that will be used to store the automatically generated ACME account private key. Optionally, a `key` may be specified to select a specific entry within the named Secret resource. If `key` is not specified, a default of `tls.key` will be used. - type: object - required: - - name - properties: - key: - description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. - type: string - name: - description: 'Name of the resource being referred to. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' - type: string - server: - description: 'Server is the URL used to access the ACME server''s ''directory'' endpoint. For example, for Let''s Encrypt''s staging endpoint, you would use: "https://acme-staging-v02.api.letsencrypt.org/directory". Only ACME v2 endpoints (i.e. RFC 8555) are supported.' - type: string - skipTLSVerify: - description: 'INSECURE: Enables or disables validation of the ACME server TLS certificate. If true, requests to the ACME server will not have the TLS certificate chain validated. Mutually exclusive with CABundle; prefer using CABundle to prevent various kinds of security vulnerabilities. Only enable this option in development environments. If CABundle and SkipTLSVerify are unset, the system certificate bundle inside the container is used to validate the TLS connection. Defaults to false.' - type: boolean - solvers: - description: 'Solvers is a list of challenge solvers that will be used to solve ACME challenges for the matching domains. Solver configurations must be provided in order to obtain certificates from an ACME server. For more information, see: https://cert-manager.io/docs/configuration/acme/' - type: array - items: - description: An ACMEChallengeSolver describes how to solve ACME challenges for the issuer it is part of. A selector may be provided to use different solving strategies for different DNS names. Only one of HTTP01 or DNS01 must be provided. - type: object - properties: - dns01: - description: Configures cert-manager to attempt to complete authorizations by performing the DNS01 challenge flow. - type: object - properties: - acmeDNS: - description: Use the 'ACME DNS' (https://github.com/joohoi/acme-dns) API to manage DNS01 challenge records. - type: object - required: - - accountSecretRef - - host - properties: - accountSecretRef: - description: A reference to a specific 'key' within a Secret resource. In some instances, `key` is a required field. - type: object - required: - - name - properties: - key: - description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. - type: string - name: - description: 'Name of the resource being referred to. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' - type: string - host: - type: string - akamai: - description: Use the Akamai DNS zone management API to manage DNS01 challenge records. - type: object - required: - - accessTokenSecretRef - - clientSecretSecretRef - - clientTokenSecretRef - - serviceConsumerDomain - properties: - accessTokenSecretRef: - description: A reference to a specific 'key' within a Secret resource. In some instances, `key` is a required field. - type: object - required: - - name - properties: - key: - description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. - type: string - name: - description: 'Name of the resource being referred to. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' - type: string - clientSecretSecretRef: - description: A reference to a specific 'key' within a Secret resource. In some instances, `key` is a required field. - type: object - required: - - name - properties: - key: - description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. - type: string - name: - description: 'Name of the resource being referred to. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' - type: string - clientTokenSecretRef: - description: A reference to a specific 'key' within a Secret resource. In some instances, `key` is a required field. - type: object - required: - - name - properties: - key: - description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. - type: string - name: - description: 'Name of the resource being referred to. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' - type: string - serviceConsumerDomain: - type: string - azureDNS: - description: Use the Microsoft Azure DNS API to manage DNS01 challenge records. - type: object - required: - - resourceGroupName - - subscriptionID - properties: - clientID: - description: 'Auth: Azure Service Principal: The ClientID of the Azure Service Principal used to authenticate with Azure DNS. If set, ClientSecret and TenantID must also be set.' - type: string - clientSecretSecretRef: - description: 'Auth: Azure Service Principal: A reference to a Secret containing the password associated with the Service Principal. If set, ClientID and TenantID must also be set.' - type: object - required: - - name - properties: - key: - description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. - type: string - name: - description: 'Name of the resource being referred to. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' - type: string - environment: - description: name of the Azure environment (default AzurePublicCloud) - type: string - enum: - - AzurePublicCloud - - AzureChinaCloud - - AzureGermanCloud - - AzureUSGovernmentCloud - hostedZoneName: - description: name of the DNS zone that should be used - type: string - managedIdentity: - description: 'Auth: Azure Workload Identity or Azure Managed Service Identity: Settings to enable Azure Workload Identity or Azure Managed Service Identity If set, ClientID, ClientSecret and TenantID must not be set.' - type: object - properties: - clientID: - description: client ID of the managed identity, can not be used at the same time as resourceID - type: string - resourceID: - description: resource ID of the managed identity, can not be used at the same time as clientID Cannot be used for Azure Managed Service Identity - type: string - resourceGroupName: - description: resource group the DNS zone is located in - type: string - subscriptionID: - description: ID of the Azure subscription - type: string - tenantID: - description: 'Auth: Azure Service Principal: The TenantID of the Azure Service Principal used to authenticate with Azure DNS. If set, ClientID and ClientSecret must also be set.' - type: string - cloudDNS: - description: Use the Google Cloud DNS API to manage DNS01 challenge records. - type: object - required: - - project - properties: - hostedZoneName: - description: HostedZoneName is an optional field that tells cert-manager in which Cloud DNS zone the challenge record has to be created. If left empty cert-manager will automatically choose a zone. - type: string - project: - type: string - serviceAccountSecretRef: - description: A reference to a specific 'key' within a Secret resource. In some instances, `key` is a required field. - type: object - required: - - name - properties: - key: - description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. - type: string - name: - description: 'Name of the resource being referred to. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' - type: string - cloudflare: - description: Use the Cloudflare API to manage DNS01 challenge records. - type: object - properties: - apiKeySecretRef: - description: 'API key to use to authenticate with Cloudflare. Note: using an API token to authenticate is now the recommended method as it allows greater control of permissions.' - type: object - required: - - name - properties: - key: - description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. - type: string - name: - description: 'Name of the resource being referred to. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' - type: string - apiTokenSecretRef: - description: API token used to authenticate with Cloudflare. - type: object - required: - - name - properties: - key: - description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. - type: string - name: - description: 'Name of the resource being referred to. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' - type: string - email: - description: Email of the account, only required when using API key based authentication. - type: string - cnameStrategy: - description: CNAMEStrategy configures how the DNS01 provider should handle CNAME records when found in DNS zones. - type: string - enum: - - None - - Follow - digitalocean: - description: Use the DigitalOcean DNS API to manage DNS01 challenge records. - type: object - required: - - tokenSecretRef - properties: - tokenSecretRef: - description: A reference to a specific 'key' within a Secret resource. In some instances, `key` is a required field. - type: object - required: - - name - properties: - key: - description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. - type: string - name: - description: 'Name of the resource being referred to. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' - type: string - rfc2136: - description: Use RFC2136 ("Dynamic Updates in the Domain Name System") (https://datatracker.ietf.org/doc/rfc2136/) to manage DNS01 challenge records. - type: object - required: - - nameserver - properties: - nameserver: - description: The IP address or hostname of an authoritative DNS server supporting RFC2136 in the form host:port. If the host is an IPv6 address it must be enclosed in square brackets (e.g [2001:db8::1]) ; port is optional. This field is required. - type: string - tsigAlgorithm: - description: 'The TSIG Algorithm configured in the DNS supporting RFC2136. Used only when ``tsigSecretSecretRef`` and ``tsigKeyName`` are defined. Supported values are (case-insensitive): ``HMACMD5`` (default), ``HMACSHA1``, ``HMACSHA256`` or ``HMACSHA512``.' - type: string - tsigKeyName: - description: The TSIG Key name configured in the DNS. If ``tsigSecretSecretRef`` is defined, this field is required. - type: string - tsigSecretSecretRef: - description: The name of the secret containing the TSIG value. If ``tsigKeyName`` is defined, this field is required. - type: object - required: - - name - properties: - key: - description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. - type: string - name: - description: 'Name of the resource being referred to. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' - type: string - route53: - description: Use the AWS Route53 API to manage DNS01 challenge records. - type: object - required: - - region - properties: - accessKeyID: - description: 'The AccessKeyID is used for authentication. Cannot be set when SecretAccessKeyID is set. If neither the Access Key nor Key ID are set, we fall-back to using env vars, shared credentials file or AWS Instance metadata, see: https://docs.aws.amazon.com/sdk-for-go/v1/developer-guide/configuring-sdk.html#specifying-credentials' - type: string - accessKeyIDSecretRef: - description: 'The SecretAccessKey is used for authentication. If set, pull the AWS access key ID from a key within a Kubernetes Secret. Cannot be set when AccessKeyID is set. If neither the Access Key nor Key ID are set, we fall-back to using env vars, shared credentials file or AWS Instance metadata, see: https://docs.aws.amazon.com/sdk-for-go/v1/developer-guide/configuring-sdk.html#specifying-credentials' - type: object - required: - - name - properties: - key: - description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. - type: string - name: - description: 'Name of the resource being referred to. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' - type: string - hostedZoneID: - description: If set, the provider will manage only this zone in Route53 and will not do an lookup using the route53:ListHostedZonesByName api call. - type: string - region: - description: Always set the region when using AccessKeyID and SecretAccessKey - type: string - role: - description: Role is a Role ARN which the Route53 provider will assume using either the explicit credentials AccessKeyID/SecretAccessKey or the inferred credentials from environment variables, shared credentials file or AWS Instance metadata - type: string - secretAccessKeySecretRef: - description: 'The SecretAccessKey is used for authentication. If neither the Access Key nor Key ID are set, we fall-back to using env vars, shared credentials file or AWS Instance metadata, see: https://docs.aws.amazon.com/sdk-for-go/v1/developer-guide/configuring-sdk.html#specifying-credentials' - type: object - required: - - name - properties: - key: - description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. - type: string - name: - description: 'Name of the resource being referred to. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' - type: string - webhook: - description: Configure an external webhook based DNS01 challenge solver to manage DNS01 challenge records. - type: object - required: - - groupName - - solverName - properties: - config: - description: Additional configuration that should be passed to the webhook apiserver when challenges are processed. This can contain arbitrary JSON data. Secret values should not be specified in this stanza. If secret values are needed (e.g. credentials for a DNS service), you should use a SecretKeySelector to reference a Secret resource. For details on the schema of this field, consult the webhook provider implementation's documentation. - x-kubernetes-preserve-unknown-fields: true - groupName: - description: The API group name that should be used when POSTing ChallengePayload resources to the webhook apiserver. This should be the same as the GroupName specified in the webhook provider implementation. - type: string - solverName: - description: The name of the solver to use, as defined in the webhook provider implementation. This will typically be the name of the provider, e.g. 'cloudflare'. - type: string - http01: - description: Configures cert-manager to attempt to complete authorizations by performing the HTTP01 challenge flow. It is not possible to obtain certificates for wildcard domain names (e.g. `*.example.com`) using the HTTP01 challenge mechanism. - type: object - properties: - gatewayHTTPRoute: - description: The Gateway API is a sig-network community API that models service networking in Kubernetes (https://gateway-api.sigs.k8s.io/). The Gateway solver will create HTTPRoutes with the specified labels in the same namespace as the challenge. This solver is experimental, and fields / behaviour may change in the future. - type: object - properties: - labels: - description: Custom labels that will be applied to HTTPRoutes created by cert-manager while solving HTTP-01 challenges. - type: object - additionalProperties: - type: string - parentRefs: - description: 'When solving an HTTP-01 challenge, cert-manager creates an HTTPRoute. cert-manager needs to know which parentRefs should be used when creating the HTTPRoute. Usually, the parentRef references a Gateway. See: https://gateway-api.sigs.k8s.io/api-types/httproute/#attaching-to-gateways' - type: array - items: - description: "ParentReference identifies an API object (usually a Gateway) that can be considered a parent of this resource (usually a route). There are two kinds of parent resources with \"Core\" support: \n * Gateway (Gateway conformance profile) * Service (Mesh conformance profile, experimental, ClusterIP Services only) \n This API may be extended in the future to support additional kinds of parent resources. \n The API object must be valid in the cluster; the Group and Kind must be registered in the cluster for this reference to be valid." - type: object - required: - - name - properties: - group: - description: "Group is the group of the referent. When unspecified, \"gateway.networking.k8s.io\" is inferred. To set the core API group (such as for a \"Service\" kind referent), Group must be explicitly set to \"\" (empty string). \n Support: Core" - type: string - default: gateway.networking.k8s.io - maxLength: 253 - pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ - kind: - description: "Kind is kind of the referent. \n There are two kinds of parent resources with \"Core\" support: \n * Gateway (Gateway conformance profile) * Service (Mesh conformance profile, experimental, ClusterIP Services only) \n Support for other resources is Implementation-Specific." - type: string - default: Gateway - maxLength: 63 - minLength: 1 - pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ - name: - description: "Name is the name of the referent. \n Support: Core" - type: string - maxLength: 253 - minLength: 1 - namespace: - description: "Namespace is the namespace of the referent. When unspecified, this refers to the local namespace of the Route. \n Note that there are specific rules for ParentRefs which cross namespace boundaries. Cross-namespace references are only valid if they are explicitly allowed by something in the namespace they are referring to. For example: Gateway has the AllowedRoutes field, and ReferenceGrant provides a generic way to enable any other kind of cross-namespace reference. \n ParentRefs from a Route to a Service in the same namespace are \"producer\" routes, which apply default routing rules to inbound connections from any namespace to the Service. \n ParentRefs from a Route to a Service in a different namespace are \"consumer\" routes, and these routing rules are only applied to outbound connections originating from the same namespace as the Route, for which the intended destination of the connections are a Service targeted as a ParentRef of the Route. \n Support: Core" - type: string - maxLength: 63 - minLength: 1 - pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ - port: - description: "Port is the network port this Route targets. It can be interpreted differently based on the type of parent resource. \n When the parent resource is a Gateway, this targets all listeners listening on the specified port that also support this kind of Route(and select this Route). It's not recommended to set `Port` unless the networking behaviors specified in a Route must apply to a specific port as opposed to a listener(s) whose port(s) may be changed. When both Port and SectionName are specified, the name and port of the selected listener must match both specified values. \n When the parent resource is a Service, this targets a specific port in the Service spec. When both Port (experimental) and SectionName are specified, the name and port of the selected port must match both specified values. \n Implementations MAY choose to support other parent resources. Implementations supporting other types of parent resources MUST clearly document how/if Port is interpreted. \n For the purpose of status, an attachment is considered successful as long as the parent resource accepts it partially. For example, Gateway listeners can restrict which Routes can attach to them by Route kind, namespace, or hostname. If 1 of 2 Gateway listeners accept attachment from the referencing Route, the Route MUST be considered successfully attached. If no Gateway listeners accept attachment from this Route, the Route MUST be considered detached from the Gateway. \n Support: Extended \n " - type: integer - format: int32 - maximum: 65535 - minimum: 1 - sectionName: - description: "SectionName is the name of a section within the target resource. In the following resources, SectionName is interpreted as the following: \n * Gateway: Listener Name. When both Port (experimental) and SectionName are specified, the name and port of the selected listener must match both specified values. * Service: Port Name. When both Port (experimental) and SectionName are specified, the name and port of the selected listener must match both specified values. Note that attaching Routes to Services as Parents is part of experimental Mesh support and is not supported for any other purpose. \n Implementations MAY choose to support attaching Routes to other resources. If that is the case, they MUST clearly document how SectionName is interpreted. \n When unspecified (empty string), this will reference the entire resource. For the purpose of status, an attachment is considered successful if at least one section in the parent resource accepts it. For example, Gateway listeners can restrict which Routes can attach to them by Route kind, namespace, or hostname. If 1 of 2 Gateway listeners accept attachment from the referencing Route, the Route MUST be considered successfully attached. If no Gateway listeners accept attachment from this Route, the Route MUST be considered detached from the Gateway. \n Support: Core" - type: string - maxLength: 253 - minLength: 1 - pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ - serviceType: - description: Optional service type for Kubernetes solver service. Supported values are NodePort or ClusterIP. If unset, defaults to NodePort. - type: string - ingress: - description: The ingress based HTTP01 challenge solver will solve challenges by creating or modifying Ingress resources in order to route requests for '/.well-known/acme-challenge/XYZ' to 'challenge solver' pods that are provisioned by cert-manager for each Challenge to be completed. - type: object - properties: - class: - description: This field configures the annotation `kubernetes.io/ingress.class` when creating Ingress resources to solve ACME challenges that use this challenge solver. Only one of `class`, `name` or `ingressClassName` may be specified. - type: string - ingressClassName: - description: This field configures the field `ingressClassName` on the created Ingress resources used to solve ACME challenges that use this challenge solver. This is the recommended way of configuring the ingress class. Only one of `class`, `name` or `ingressClassName` may be specified. - type: string - ingressTemplate: - description: Optional ingress template used to configure the ACME challenge solver ingress used for HTTP01 challenges. - type: object - properties: - metadata: - description: ObjectMeta overrides for the ingress used to solve HTTP01 challenges. Only the 'labels' and 'annotations' fields may be set. If labels or annotations overlap with in-built values, the values here will override the in-built values. - type: object - properties: - annotations: - description: Annotations that should be added to the created ACME HTTP01 solver ingress. - type: object - additionalProperties: - type: string - labels: - description: Labels that should be added to the created ACME HTTP01 solver ingress. - type: object - additionalProperties: - type: string - name: - description: The name of the ingress resource that should have ACME challenge solving routes inserted into it in order to solve HTTP01 challenges. This is typically used in conjunction with ingress controllers like ingress-gce, which maintains a 1:1 mapping between external IPs and ingress resources. Only one of `class`, `name` or `ingressClassName` may be specified. - type: string - podTemplate: - description: Optional pod template used to configure the ACME challenge solver pods used for HTTP01 challenges. - type: object - properties: - metadata: - description: ObjectMeta overrides for the pod used to solve HTTP01 challenges. Only the 'labels' and 'annotations' fields may be set. If labels or annotations overlap with in-built values, the values here will override the in-built values. - type: object - properties: - annotations: - description: Annotations that should be added to the create ACME HTTP01 solver pods. - type: object - additionalProperties: - type: string - labels: - description: Labels that should be added to the created ACME HTTP01 solver pods. - type: object - additionalProperties: - type: string - spec: - description: PodSpec defines overrides for the HTTP01 challenge solver pod. Check ACMEChallengeSolverHTTP01IngressPodSpec to find out currently supported fields. All other fields will be ignored. - type: object - properties: - affinity: - description: If specified, the pod's scheduling constraints - type: object - properties: - nodeAffinity: - description: Describes node affinity scheduling rules for the pod. - type: object - properties: - preferredDuringSchedulingIgnoredDuringExecution: - description: The scheduler will prefer to schedule pods to nodes that satisfy the affinity expressions specified by this field, but it may choose a node that violates one or more of the expressions. The node that is most preferred is the one with the greatest sum of weights, i.e. for each node that meets all of the scheduling requirements (resource request, requiredDuringScheduling affinity expressions, etc.), compute a sum by iterating through the elements of this field and adding "weight" to the sum if the node matches the corresponding matchExpressions; the node(s) with the highest sum are the most preferred. - type: array - items: - description: An empty preferred scheduling term matches all objects with implicit weight 0 (i.e. it's a no-op). A null preferred scheduling term matches no objects (i.e. is also a no-op). - type: object - required: - - preference - - weight - properties: - preference: - description: A node selector term, associated with the corresponding weight. - type: object - properties: - matchExpressions: - description: A list of node selector requirements by node's labels. - type: array - items: - description: A node selector requirement is a selector that contains values, a key, and an operator that relates the key and values. - type: object - required: - - key - - operator - properties: - key: - description: The label key that the selector applies to. - type: string - operator: - description: Represents a key's relationship to a set of values. Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. - type: string - values: - description: An array of string values. If the operator is In or NotIn, the values array must be non-empty. If the operator is Exists or DoesNotExist, the values array must be empty. If the operator is Gt or Lt, the values array must have a single element, which will be interpreted as an integer. This array is replaced during a strategic merge patch. - type: array - items: - type: string - matchFields: - description: A list of node selector requirements by node's fields. - type: array - items: - description: A node selector requirement is a selector that contains values, a key, and an operator that relates the key and values. - type: object - required: - - key - - operator - properties: - key: - description: The label key that the selector applies to. - type: string - operator: - description: Represents a key's relationship to a set of values. Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. - type: string - values: - description: An array of string values. If the operator is In or NotIn, the values array must be non-empty. If the operator is Exists or DoesNotExist, the values array must be empty. If the operator is Gt or Lt, the values array must have a single element, which will be interpreted as an integer. This array is replaced during a strategic merge patch. - type: array - items: - type: string - x-kubernetes-map-type: atomic - weight: - description: Weight associated with matching the corresponding nodeSelectorTerm, in the range 1-100. - type: integer - format: int32 - requiredDuringSchedulingIgnoredDuringExecution: - description: If the affinity requirements specified by this field are not met at scheduling time, the pod will not be scheduled onto the node. If the affinity requirements specified by this field cease to be met at some point during pod execution (e.g. due to an update), the system may or may not try to eventually evict the pod from its node. - type: object - required: - - nodeSelectorTerms - properties: - nodeSelectorTerms: - description: Required. A list of node selector terms. The terms are ORed. - type: array - items: - description: A null or empty node selector term matches no objects. The requirements of them are ANDed. The TopologySelectorTerm type implements a subset of the NodeSelectorTerm. - type: object - properties: - matchExpressions: - description: A list of node selector requirements by node's labels. - type: array - items: - description: A node selector requirement is a selector that contains values, a key, and an operator that relates the key and values. - type: object - required: - - key - - operator - properties: - key: - description: The label key that the selector applies to. - type: string - operator: - description: Represents a key's relationship to a set of values. Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. - type: string - values: - description: An array of string values. If the operator is In or NotIn, the values array must be non-empty. If the operator is Exists or DoesNotExist, the values array must be empty. If the operator is Gt or Lt, the values array must have a single element, which will be interpreted as an integer. This array is replaced during a strategic merge patch. - type: array - items: - type: string - matchFields: - description: A list of node selector requirements by node's fields. - type: array - items: - description: A node selector requirement is a selector that contains values, a key, and an operator that relates the key and values. - type: object - required: - - key - - operator - properties: - key: - description: The label key that the selector applies to. - type: string - operator: - description: Represents a key's relationship to a set of values. Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. - type: string - values: - description: An array of string values. If the operator is In or NotIn, the values array must be non-empty. If the operator is Exists or DoesNotExist, the values array must be empty. If the operator is Gt or Lt, the values array must have a single element, which will be interpreted as an integer. This array is replaced during a strategic merge patch. - type: array - items: - type: string - x-kubernetes-map-type: atomic - x-kubernetes-map-type: atomic - podAffinity: - description: Describes pod affinity scheduling rules (e.g. co-locate this pod in the same node, zone, etc. as some other pod(s)). - type: object - properties: - preferredDuringSchedulingIgnoredDuringExecution: - description: The scheduler will prefer to schedule pods to nodes that satisfy the affinity expressions specified by this field, but it may choose a node that violates one or more of the expressions. The node that is most preferred is the one with the greatest sum of weights, i.e. for each node that meets all of the scheduling requirements (resource request, requiredDuringScheduling affinity expressions, etc.), compute a sum by iterating through the elements of this field and adding "weight" to the sum if the node has pods which matches the corresponding podAffinityTerm; the node(s) with the highest sum are the most preferred. - type: array - items: - description: The weights of all of the matched WeightedPodAffinityTerm fields are added per-node to find the most preferred node(s) - type: object - required: - - podAffinityTerm - - weight - properties: - podAffinityTerm: - description: Required. A pod affinity term, associated with the corresponding weight. - type: object - required: - - topologyKey - properties: - labelSelector: - description: A label query over a set of resources, in this case pods. If it's null, this PodAffinityTerm matches with no Pods. - type: object - properties: - matchExpressions: - description: matchExpressions is a list of label selector requirements. The requirements are ANDed. - type: array - items: - description: A label selector requirement is a selector that contains values, a key, and an operator that relates the key and values. - type: object - required: - - key - - operator - properties: - key: - description: key is the label key that the selector applies to. - type: string - operator: - description: operator represents a key's relationship to a set of values. Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: values is an array of string values. If the operator is In or NotIn, the values array must be non-empty. If the operator is Exists or DoesNotExist, the values array must be empty. This array is replaced during a strategic merge patch. - type: array - items: - type: string - matchLabels: - description: matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels map is equivalent to an element of matchExpressions, whose key field is "key", the operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - additionalProperties: - type: string - x-kubernetes-map-type: atomic - matchLabelKeys: - description: MatchLabelKeys is a set of pod label keys to select which pods will be taken into consideration. The keys are used to lookup values from the incoming pod labels, those key-value labels are merged with `LabelSelector` as `key in (value)` to select the group of existing pods which pods will be taken into consideration for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both MatchLabelKeys and LabelSelector. Also, MatchLabelKeys cannot be set when LabelSelector isn't set. This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. - type: array - items: - type: string - x-kubernetes-list-type: atomic - mismatchLabelKeys: - description: MismatchLabelKeys is a set of pod label keys to select which pods will be taken into consideration. The keys are used to lookup values from the incoming pod labels, those key-value labels are merged with `LabelSelector` as `key notin (value)` to select the group of existing pods which pods will be taken into consideration for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both MismatchLabelKeys and LabelSelector. Also, MismatchLabelKeys cannot be set when LabelSelector isn't set. This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. - type: array - items: - type: string - x-kubernetes-list-type: atomic - namespaceSelector: - description: A label query over the set of namespaces that the term applies to. The term is applied to the union of the namespaces selected by this field and the ones listed in the namespaces field. null selector and null or empty namespaces list means "this pod's namespace". An empty selector ({}) matches all namespaces. - type: object - properties: - matchExpressions: - description: matchExpressions is a list of label selector requirements. The requirements are ANDed. - type: array - items: - description: A label selector requirement is a selector that contains values, a key, and an operator that relates the key and values. - type: object - required: - - key - - operator - properties: - key: - description: key is the label key that the selector applies to. - type: string - operator: - description: operator represents a key's relationship to a set of values. Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: values is an array of string values. If the operator is In or NotIn, the values array must be non-empty. If the operator is Exists or DoesNotExist, the values array must be empty. This array is replaced during a strategic merge patch. - type: array - items: - type: string - matchLabels: - description: matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels map is equivalent to an element of matchExpressions, whose key field is "key", the operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - additionalProperties: - type: string - x-kubernetes-map-type: atomic - namespaces: - description: namespaces specifies a static list of namespace names that the term applies to. The term is applied to the union of the namespaces listed in this field and the ones selected by namespaceSelector. null or empty namespaces list and null namespaceSelector means "this pod's namespace". - type: array - items: - type: string - topologyKey: - description: This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching the labelSelector in the specified namespaces, where co-located is defined as running on a node whose value of the label with key topologyKey matches that of any node on which any of the selected pods is running. Empty topologyKey is not allowed. - type: string - weight: - description: weight associated with matching the corresponding podAffinityTerm, in the range 1-100. - type: integer - format: int32 - requiredDuringSchedulingIgnoredDuringExecution: - description: If the affinity requirements specified by this field are not met at scheduling time, the pod will not be scheduled onto the node. If the affinity requirements specified by this field cease to be met at some point during pod execution (e.g. due to a pod label update), the system may or may not try to eventually evict the pod from its node. When there are multiple elements, the lists of nodes corresponding to each podAffinityTerm are intersected, i.e. all terms must be satisfied. - type: array - items: - description: Defines a set of pods (namely those matching the labelSelector relative to the given namespace(s)) that this pod should be co-located (affinity) or not co-located (anti-affinity) with, where co-located is defined as running on a node whose value of the label with key matches that of any node on which a pod of the set of pods is running - type: object - required: - - topologyKey - properties: - labelSelector: - description: A label query over a set of resources, in this case pods. If it's null, this PodAffinityTerm matches with no Pods. - type: object - properties: - matchExpressions: - description: matchExpressions is a list of label selector requirements. The requirements are ANDed. - type: array - items: - description: A label selector requirement is a selector that contains values, a key, and an operator that relates the key and values. - type: object - required: - - key - - operator - properties: - key: - description: key is the label key that the selector applies to. - type: string - operator: - description: operator represents a key's relationship to a set of values. Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: values is an array of string values. If the operator is In or NotIn, the values array must be non-empty. If the operator is Exists or DoesNotExist, the values array must be empty. This array is replaced during a strategic merge patch. - type: array - items: - type: string - matchLabels: - description: matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels map is equivalent to an element of matchExpressions, whose key field is "key", the operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - additionalProperties: - type: string - x-kubernetes-map-type: atomic - matchLabelKeys: - description: MatchLabelKeys is a set of pod label keys to select which pods will be taken into consideration. The keys are used to lookup values from the incoming pod labels, those key-value labels are merged with `LabelSelector` as `key in (value)` to select the group of existing pods which pods will be taken into consideration for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both MatchLabelKeys and LabelSelector. Also, MatchLabelKeys cannot be set when LabelSelector isn't set. This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. - type: array - items: - type: string - x-kubernetes-list-type: atomic - mismatchLabelKeys: - description: MismatchLabelKeys is a set of pod label keys to select which pods will be taken into consideration. The keys are used to lookup values from the incoming pod labels, those key-value labels are merged with `LabelSelector` as `key notin (value)` to select the group of existing pods which pods will be taken into consideration for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both MismatchLabelKeys and LabelSelector. Also, MismatchLabelKeys cannot be set when LabelSelector isn't set. This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. - type: array - items: - type: string - x-kubernetes-list-type: atomic - namespaceSelector: - description: A label query over the set of namespaces that the term applies to. The term is applied to the union of the namespaces selected by this field and the ones listed in the namespaces field. null selector and null or empty namespaces list means "this pod's namespace". An empty selector ({}) matches all namespaces. - type: object - properties: - matchExpressions: - description: matchExpressions is a list of label selector requirements. The requirements are ANDed. - type: array - items: - description: A label selector requirement is a selector that contains values, a key, and an operator that relates the key and values. - type: object - required: - - key - - operator - properties: - key: - description: key is the label key that the selector applies to. - type: string - operator: - description: operator represents a key's relationship to a set of values. Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: values is an array of string values. If the operator is In or NotIn, the values array must be non-empty. If the operator is Exists or DoesNotExist, the values array must be empty. This array is replaced during a strategic merge patch. - type: array - items: - type: string - matchLabels: - description: matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels map is equivalent to an element of matchExpressions, whose key field is "key", the operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - additionalProperties: - type: string - x-kubernetes-map-type: atomic - namespaces: - description: namespaces specifies a static list of namespace names that the term applies to. The term is applied to the union of the namespaces listed in this field and the ones selected by namespaceSelector. null or empty namespaces list and null namespaceSelector means "this pod's namespace". - type: array - items: - type: string - topologyKey: - description: This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching the labelSelector in the specified namespaces, where co-located is defined as running on a node whose value of the label with key topologyKey matches that of any node on which any of the selected pods is running. Empty topologyKey is not allowed. - type: string - podAntiAffinity: - description: Describes pod anti-affinity scheduling rules (e.g. avoid putting this pod in the same node, zone, etc. as some other pod(s)). - type: object - properties: - preferredDuringSchedulingIgnoredDuringExecution: - description: The scheduler will prefer to schedule pods to nodes that satisfy the anti-affinity expressions specified by this field, but it may choose a node that violates one or more of the expressions. The node that is most preferred is the one with the greatest sum of weights, i.e. for each node that meets all of the scheduling requirements (resource request, requiredDuringScheduling anti-affinity expressions, etc.), compute a sum by iterating through the elements of this field and adding "weight" to the sum if the node has pods which matches the corresponding podAffinityTerm; the node(s) with the highest sum are the most preferred. - type: array - items: - description: The weights of all of the matched WeightedPodAffinityTerm fields are added per-node to find the most preferred node(s) - type: object - required: - - podAffinityTerm - - weight - properties: - podAffinityTerm: - description: Required. A pod affinity term, associated with the corresponding weight. - type: object - required: - - topologyKey - properties: - labelSelector: - description: A label query over a set of resources, in this case pods. If it's null, this PodAffinityTerm matches with no Pods. - type: object - properties: - matchExpressions: - description: matchExpressions is a list of label selector requirements. The requirements are ANDed. - type: array - items: - description: A label selector requirement is a selector that contains values, a key, and an operator that relates the key and values. - type: object - required: - - key - - operator - properties: - key: - description: key is the label key that the selector applies to. - type: string - operator: - description: operator represents a key's relationship to a set of values. Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: values is an array of string values. If the operator is In or NotIn, the values array must be non-empty. If the operator is Exists or DoesNotExist, the values array must be empty. This array is replaced during a strategic merge patch. - type: array - items: - type: string - matchLabels: - description: matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels map is equivalent to an element of matchExpressions, whose key field is "key", the operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - additionalProperties: - type: string - x-kubernetes-map-type: atomic - matchLabelKeys: - description: MatchLabelKeys is a set of pod label keys to select which pods will be taken into consideration. The keys are used to lookup values from the incoming pod labels, those key-value labels are merged with `LabelSelector` as `key in (value)` to select the group of existing pods which pods will be taken into consideration for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both MatchLabelKeys and LabelSelector. Also, MatchLabelKeys cannot be set when LabelSelector isn't set. This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. - type: array - items: - type: string - x-kubernetes-list-type: atomic - mismatchLabelKeys: - description: MismatchLabelKeys is a set of pod label keys to select which pods will be taken into consideration. The keys are used to lookup values from the incoming pod labels, those key-value labels are merged with `LabelSelector` as `key notin (value)` to select the group of existing pods which pods will be taken into consideration for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both MismatchLabelKeys and LabelSelector. Also, MismatchLabelKeys cannot be set when LabelSelector isn't set. This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. - type: array - items: - type: string - x-kubernetes-list-type: atomic - namespaceSelector: - description: A label query over the set of namespaces that the term applies to. The term is applied to the union of the namespaces selected by this field and the ones listed in the namespaces field. null selector and null or empty namespaces list means "this pod's namespace". An empty selector ({}) matches all namespaces. - type: object - properties: - matchExpressions: - description: matchExpressions is a list of label selector requirements. The requirements are ANDed. - type: array - items: - description: A label selector requirement is a selector that contains values, a key, and an operator that relates the key and values. - type: object - required: - - key - - operator - properties: - key: - description: key is the label key that the selector applies to. - type: string - operator: - description: operator represents a key's relationship to a set of values. Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: values is an array of string values. If the operator is In or NotIn, the values array must be non-empty. If the operator is Exists or DoesNotExist, the values array must be empty. This array is replaced during a strategic merge patch. - type: array - items: - type: string - matchLabels: - description: matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels map is equivalent to an element of matchExpressions, whose key field is "key", the operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - additionalProperties: - type: string - x-kubernetes-map-type: atomic - namespaces: - description: namespaces specifies a static list of namespace names that the term applies to. The term is applied to the union of the namespaces listed in this field and the ones selected by namespaceSelector. null or empty namespaces list and null namespaceSelector means "this pod's namespace". - type: array - items: - type: string - topologyKey: - description: This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching the labelSelector in the specified namespaces, where co-located is defined as running on a node whose value of the label with key topologyKey matches that of any node on which any of the selected pods is running. Empty topologyKey is not allowed. - type: string - weight: - description: weight associated with matching the corresponding podAffinityTerm, in the range 1-100. - type: integer - format: int32 - requiredDuringSchedulingIgnoredDuringExecution: - description: If the anti-affinity requirements specified by this field are not met at scheduling time, the pod will not be scheduled onto the node. If the anti-affinity requirements specified by this field cease to be met at some point during pod execution (e.g. due to a pod label update), the system may or may not try to eventually evict the pod from its node. When there are multiple elements, the lists of nodes corresponding to each podAffinityTerm are intersected, i.e. all terms must be satisfied. - type: array - items: - description: Defines a set of pods (namely those matching the labelSelector relative to the given namespace(s)) that this pod should be co-located (affinity) or not co-located (anti-affinity) with, where co-located is defined as running on a node whose value of the label with key matches that of any node on which a pod of the set of pods is running - type: object - required: - - topologyKey - properties: - labelSelector: - description: A label query over a set of resources, in this case pods. If it's null, this PodAffinityTerm matches with no Pods. - type: object - properties: - matchExpressions: - description: matchExpressions is a list of label selector requirements. The requirements are ANDed. - type: array - items: - description: A label selector requirement is a selector that contains values, a key, and an operator that relates the key and values. - type: object - required: - - key - - operator - properties: - key: - description: key is the label key that the selector applies to. - type: string - operator: - description: operator represents a key's relationship to a set of values. Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: values is an array of string values. If the operator is In or NotIn, the values array must be non-empty. If the operator is Exists or DoesNotExist, the values array must be empty. This array is replaced during a strategic merge patch. - type: array - items: - type: string - matchLabels: - description: matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels map is equivalent to an element of matchExpressions, whose key field is "key", the operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - additionalProperties: - type: string - x-kubernetes-map-type: atomic - matchLabelKeys: - description: MatchLabelKeys is a set of pod label keys to select which pods will be taken into consideration. The keys are used to lookup values from the incoming pod labels, those key-value labels are merged with `LabelSelector` as `key in (value)` to select the group of existing pods which pods will be taken into consideration for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both MatchLabelKeys and LabelSelector. Also, MatchLabelKeys cannot be set when LabelSelector isn't set. This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. - type: array - items: - type: string - x-kubernetes-list-type: atomic - mismatchLabelKeys: - description: MismatchLabelKeys is a set of pod label keys to select which pods will be taken into consideration. The keys are used to lookup values from the incoming pod labels, those key-value labels are merged with `LabelSelector` as `key notin (value)` to select the group of existing pods which pods will be taken into consideration for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both MismatchLabelKeys and LabelSelector. Also, MismatchLabelKeys cannot be set when LabelSelector isn't set. This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. - type: array - items: - type: string - x-kubernetes-list-type: atomic - namespaceSelector: - description: A label query over the set of namespaces that the term applies to. The term is applied to the union of the namespaces selected by this field and the ones listed in the namespaces field. null selector and null or empty namespaces list means "this pod's namespace". An empty selector ({}) matches all namespaces. - type: object - properties: - matchExpressions: - description: matchExpressions is a list of label selector requirements. The requirements are ANDed. - type: array - items: - description: A label selector requirement is a selector that contains values, a key, and an operator that relates the key and values. - type: object - required: - - key - - operator - properties: - key: - description: key is the label key that the selector applies to. - type: string - operator: - description: operator represents a key's relationship to a set of values. Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: values is an array of string values. If the operator is In or NotIn, the values array must be non-empty. If the operator is Exists or DoesNotExist, the values array must be empty. This array is replaced during a strategic merge patch. - type: array - items: - type: string - matchLabels: - description: matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels map is equivalent to an element of matchExpressions, whose key field is "key", the operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - additionalProperties: - type: string - x-kubernetes-map-type: atomic - namespaces: - description: namespaces specifies a static list of namespace names that the term applies to. The term is applied to the union of the namespaces listed in this field and the ones selected by namespaceSelector. null or empty namespaces list and null namespaceSelector means "this pod's namespace". - type: array - items: - type: string - topologyKey: - description: This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching the labelSelector in the specified namespaces, where co-located is defined as running on a node whose value of the label with key topologyKey matches that of any node on which any of the selected pods is running. Empty topologyKey is not allowed. - type: string - imagePullSecrets: - description: If specified, the pod's imagePullSecrets - type: array - items: - description: LocalObjectReference contains enough information to let you locate the referenced object inside the same namespace. - type: object - properties: - name: - description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names TODO: Add other useful fields. apiVersion, kind, uid?' - type: string - x-kubernetes-map-type: atomic - nodeSelector: - description: 'NodeSelector is a selector which must be true for the pod to fit on a node. Selector which must match a node''s labels for the pod to be scheduled on that node. More info: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/' - type: object - additionalProperties: - type: string - priorityClassName: - description: If specified, the pod's priorityClassName. - type: string - serviceAccountName: - description: If specified, the pod's service account - type: string - tolerations: - description: If specified, the pod's tolerations. - type: array - items: - description: The pod this Toleration is attached to tolerates any taint that matches the triple using the matching operator . - type: object - properties: - effect: - description: Effect indicates the taint effect to match. Empty means match all taint effects. When specified, allowed values are NoSchedule, PreferNoSchedule and NoExecute. - type: string - key: - description: Key is the taint key that the toleration applies to. Empty means match all taint keys. If the key is empty, operator must be Exists; this combination means to match all values and all keys. - type: string - operator: - description: Operator represents a key's relationship to the value. Valid operators are Exists and Equal. Defaults to Equal. Exists is equivalent to wildcard for value, so that a pod can tolerate all taints of a particular category. - type: string - tolerationSeconds: - description: TolerationSeconds represents the period of time the toleration (which must be of effect NoExecute, otherwise this field is ignored) tolerates the taint. By default, it is not set, which means tolerate the taint forever (do not evict). Zero and negative values will be treated as 0 (evict immediately) by the system. - type: integer - format: int64 - value: - description: Value is the taint value the toleration matches to. If the operator is Exists, the value should be empty, otherwise just a regular string. - type: string - serviceType: - description: Optional service type for Kubernetes solver service. Supported values are NodePort or ClusterIP. If unset, defaults to NodePort. - type: string - selector: - description: Selector selects a set of DNSNames on the Certificate resource that should be solved using this challenge solver. If not specified, the solver will be treated as the 'default' solver with the lowest priority, i.e. if any other solver has a more specific match, it will be used instead. - type: object - properties: - dnsNames: - description: List of DNSNames that this solver will be used to solve. If specified and a match is found, a dnsNames selector will take precedence over a dnsZones selector. If multiple solvers match with the same dnsNames value, the solver with the most matching labels in matchLabels will be selected. If neither has more matches, the solver defined earlier in the list will be selected. - type: array - items: - type: string - dnsZones: - description: List of DNSZones that this solver will be used to solve. The most specific DNS zone match specified here will take precedence over other DNS zone matches, so a solver specifying sys.example.com will be selected over one specifying example.com for the domain www.sys.example.com. If multiple solvers match with the same dnsZones value, the solver with the most matching labels in matchLabels will be selected. If neither has more matches, the solver defined earlier in the list will be selected. - type: array - items: - type: string - matchLabels: - description: A label selector that is used to refine the set of certificate's that this challenge solver will apply to. - type: object - additionalProperties: - type: string - ca: - description: CA configures this issuer to sign certificates using a signing CA keypair stored in a Secret resource. This is used to build internal PKIs that are managed by cert-manager. - type: object - required: - - secretName - properties: - crlDistributionPoints: - description: The CRL distribution points is an X.509 v3 certificate extension which identifies the location of the CRL from which the revocation of this certificate can be checked. If not set, certificates will be issued without distribution points set. - type: array - items: - type: string - issuingCertificateURLs: - description: IssuingCertificateURLs is a list of URLs which this issuer should embed into certificates it creates. See https://www.rfc-editor.org/rfc/rfc5280#section-4.2.2.1 for more details. As an example, such a URL might be "http://ca.domain.com/ca.crt". - type: array - items: - type: string - ocspServers: - description: The OCSP server list is an X.509 v3 extension that defines a list of URLs of OCSP responders. The OCSP responders can be queried for the revocation status of an issued certificate. If not set, the certificate will be issued with no OCSP servers set. For example, an OCSP server URL could be "http://ocsp.int-x3.letsencrypt.org". - type: array - items: - type: string - secretName: - description: SecretName is the name of the secret used to sign Certificates issued by this Issuer. - type: string - selfSigned: - description: SelfSigned configures this issuer to 'self sign' certificates using the private key used to create the CertificateRequest object. - type: object - properties: - crlDistributionPoints: - description: The CRL distribution points is an X.509 v3 certificate extension which identifies the location of the CRL from which the revocation of this certificate can be checked. If not set certificate will be issued without CDP. Values are strings. - type: array - items: - type: string - vault: - description: Vault configures this issuer to sign certificates using a HashiCorp Vault PKI backend. - type: object - required: - - auth - - path - - server - properties: - auth: - description: Auth configures how cert-manager authenticates with the Vault server. - type: object - properties: - appRole: - description: AppRole authenticates with Vault using the App Role auth mechanism, with the role and secret stored in a Kubernetes Secret resource. - type: object - required: - - path - - roleId - - secretRef - properties: - path: - description: 'Path where the App Role authentication backend is mounted in Vault, e.g: "approle"' - type: string - roleId: - description: RoleID configured in the App Role authentication backend when setting up the authentication backend in Vault. - type: string - secretRef: - description: Reference to a key in a Secret that contains the App Role secret used to authenticate with Vault. The `key` field must be specified and denotes which entry within the Secret resource is used as the app role secret. - type: object - required: - - name - properties: - key: - description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. - type: string - name: - description: 'Name of the resource being referred to. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' - type: string - kubernetes: - description: Kubernetes authenticates with Vault by passing the ServiceAccount token stored in the named Secret resource to the Vault server. - type: object - required: - - role - properties: - mountPath: - description: The Vault mountPath here is the mount path to use when authenticating with Vault. For example, setting a value to `/v1/auth/foo`, will use the path `/v1/auth/foo/login` to authenticate with Vault. If unspecified, the default value "/v1/auth/kubernetes" will be used. - type: string - role: - description: A required field containing the Vault Role to assume. A Role binds a Kubernetes ServiceAccount with a set of Vault policies. - type: string - secretRef: - description: The required Secret field containing a Kubernetes ServiceAccount JWT used for authenticating with Vault. Use of 'ambient credentials' is not supported. - type: object - required: - - name - properties: - key: - description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. - type: string - name: - description: 'Name of the resource being referred to. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' - type: string - serviceAccountRef: - description: A reference to a service account that will be used to request a bound token (also known as "projected token"). Compared to using "secretRef", using this field means that you don't rely on statically bound tokens. To use this field, you must configure an RBAC rule to let cert-manager request a token. - type: object - required: - - name - properties: - name: - description: Name of the ServiceAccount used to request a token. - type: string - tokenSecretRef: - description: TokenSecretRef authenticates with Vault by presenting a token. - type: object - required: - - name - properties: - key: - description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. - type: string - name: - description: 'Name of the resource being referred to. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' - type: string - caBundle: - description: Base64-encoded bundle of PEM CAs which will be used to validate the certificate chain presented by Vault. Only used if using HTTPS to connect to Vault and ignored for HTTP connections. Mutually exclusive with CABundleSecretRef. If neither CABundle nor CABundleSecretRef are defined, the certificate bundle in the cert-manager controller container is used to validate the TLS connection. - type: string - format: byte - caBundleSecretRef: - description: Reference to a Secret containing a bundle of PEM-encoded CAs to use when verifying the certificate chain presented by Vault when using HTTPS. Mutually exclusive with CABundle. If neither CABundle nor CABundleSecretRef are defined, the certificate bundle in the cert-manager controller container is used to validate the TLS connection. If no key for the Secret is specified, cert-manager will default to 'ca.crt'. - type: object - required: - - name - properties: - key: - description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. - type: string - name: - description: 'Name of the resource being referred to. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' - type: string - namespace: - description: 'Name of the vault namespace. Namespaces is a set of features within Vault Enterprise that allows Vault environments to support Secure Multi-tenancy. e.g: "ns1" More about namespaces can be found here https://www.vaultproject.io/docs/enterprise/namespaces' - type: string - path: - description: 'Path is the mount path of the Vault PKI backend''s `sign` endpoint, e.g: "my_pki_mount/sign/my-role-name".' - type: string - server: - description: 'Server is the connection address for the Vault server, e.g: "https://vault.example.com:8200".' - type: string - venafi: - description: Venafi configures this issuer to sign certificates using a Venafi TPP or Venafi Cloud policy zone. - type: object - required: - - zone - properties: - cloud: - description: Cloud specifies the Venafi cloud configuration settings. Only one of TPP or Cloud may be specified. - type: object - required: - - apiTokenSecretRef - properties: - apiTokenSecretRef: - description: APITokenSecretRef is a secret key selector for the Venafi Cloud API token. - type: object - required: - - name - properties: - key: - description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. - type: string - name: - description: 'Name of the resource being referred to. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' - type: string - url: - description: URL is the base URL for Venafi Cloud. Defaults to "https://api.venafi.cloud/v1". - type: string - tpp: - description: TPP specifies Trust Protection Platform configuration settings. Only one of TPP or Cloud may be specified. - type: object - required: - - credentialsRef - - url - properties: - caBundle: - description: Base64-encoded bundle of PEM CAs which will be used to validate the certificate chain presented by the TPP server. Only used if using HTTPS; ignored for HTTP. If undefined, the certificate bundle in the cert-manager controller container is used to validate the chain. - type: string - format: byte - credentialsRef: - description: CredentialsRef is a reference to a Secret containing the username and password for the TPP server. The secret must contain two keys, 'username' and 'password'. - type: object - required: - - name - properties: - name: - description: 'Name of the resource being referred to. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' - type: string - url: - description: 'URL is the base URL for the vedsdk endpoint of the Venafi TPP instance, for example: "https://tpp.example.com/vedsdk".' - type: string - zone: - description: Zone is the Venafi Policy Zone to use for this issuer. All requests made to the Venafi platform will be restricted by the named zone policy. This field is required. - type: string - status: - description: Status of the ClusterIssuer. This is set and managed automatically. - type: object - properties: - acme: - description: ACME specific status options. This field should only be set if the Issuer is configured to use an ACME server to issue certificates. - type: object - properties: - lastPrivateKeyHash: - description: LastPrivateKeyHash is a hash of the private key associated with the latest registered ACME account, in order to track changes made to registered account associated with the Issuer - type: string - lastRegisteredEmail: - description: LastRegisteredEmail is the email associated with the latest registered ACME account, in order to track changes made to registered account associated with the Issuer - type: string - uri: - description: URI is the unique account identifier, which can also be used to retrieve account details from the CA - type: string - conditions: - description: List of status conditions to indicate the status of a CertificateRequest. Known condition types are `Ready`. - type: array - items: - description: IssuerCondition contains condition information for an Issuer. - type: object - required: - - status - - type - properties: - lastTransitionTime: - description: LastTransitionTime is the timestamp corresponding to the last status change of this condition. - type: string - format: date-time - message: - description: Message is a human readable description of the details of the last transition, complementing reason. - type: string - observedGeneration: - description: If set, this represents the .metadata.generation that the condition was set based upon. For instance, if .metadata.generation is currently 12, but the .status.condition[x].observedGeneration is 9, the condition is out of date with respect to the current state of the Issuer. - type: integer - format: int64 - reason: - description: Reason is a brief machine readable explanation for the condition's last transition. - type: string - status: - description: Status of the condition, one of (`True`, `False`, `Unknown`). - type: string - enum: - - "True" - - "False" - - Unknown - type: - description: Type of the condition, known values are (`Ready`). - type: string - x-kubernetes-list-map-keys: - - type - x-kubernetes-list-type: map - served: true - storage: true ---- -# Source: cert-manager/templates/crds.yaml -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - name: issuers.cert-manager.io - labels: - app: 'cert-manager' - app.kubernetes.io/name: 'cert-manager' - app.kubernetes.io/instance: "cert-manager" - # Generated labels - app.kubernetes.io/version: "v1.14.7" -spec: - group: cert-manager.io - names: - kind: Issuer - listKind: IssuerList - plural: issuers - singular: issuer - categories: - - cert-manager - scope: Namespaced - versions: - - name: v1 - subresources: - status: {} - additionalPrinterColumns: - - jsonPath: .status.conditions[?(@.type=="Ready")].status - name: Ready - type: string - - jsonPath: .status.conditions[?(@.type=="Ready")].message - name: Status - priority: 1 - type: string - - jsonPath: .metadata.creationTimestamp - description: CreationTimestamp is a timestamp representing the server time when this object was created. It is not guaranteed to be set in happens-before order across separate operations. Clients may not set this value. It is represented in RFC3339 form and is in UTC. - name: Age - type: date - schema: - openAPIV3Schema: - description: An Issuer represents a certificate issuing authority which can be referenced as part of `issuerRef` fields. It is scoped to a single namespace and can therefore only be referenced by resources within the same namespace. - type: object - required: - - spec - properties: - apiVersion: - description: 'APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' - type: string - kind: - description: 'Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' - type: string - metadata: - type: object - spec: - description: Desired state of the Issuer resource. - type: object - properties: - acme: - description: ACME configures this issuer to communicate with a RFC8555 (ACME) server to obtain signed x509 certificates. - type: object - required: - - privateKeySecretRef - - server - properties: - caBundle: - description: Base64-encoded bundle of PEM CAs which can be used to validate the certificate chain presented by the ACME server. Mutually exclusive with SkipTLSVerify; prefer using CABundle to prevent various kinds of security vulnerabilities. If CABundle and SkipTLSVerify are unset, the system certificate bundle inside the container is used to validate the TLS connection. - type: string - format: byte - disableAccountKeyGeneration: - description: Enables or disables generating a new ACME account key. If true, the Issuer resource will *not* request a new account but will expect the account key to be supplied via an existing secret. If false, the cert-manager system will generate a new ACME account key for the Issuer. Defaults to false. - type: boolean - email: - description: Email is the email address to be associated with the ACME account. This field is optional, but it is strongly recommended to be set. It will be used to contact you in case of issues with your account or certificates, including expiry notification emails. This field may be updated after the account is initially registered. - type: string - enableDurationFeature: - description: Enables requesting a Not After date on certificates that matches the duration of the certificate. This is not supported by all ACME servers like Let's Encrypt. If set to true when the ACME server does not support it it will create an error on the Order. Defaults to false. - type: boolean - externalAccountBinding: - description: ExternalAccountBinding is a reference to a CA external account of the ACME server. If set, upon registration cert-manager will attempt to associate the given external account credentials with the registered ACME account. - type: object - required: - - keyID - - keySecretRef - properties: - keyAlgorithm: - description: 'Deprecated: keyAlgorithm field exists for historical compatibility reasons and should not be used. The algorithm is now hardcoded to HS256 in golang/x/crypto/acme.' - type: string - enum: - - HS256 - - HS384 - - HS512 - keyID: - description: keyID is the ID of the CA key that the External Account is bound to. - type: string - keySecretRef: - description: keySecretRef is a Secret Key Selector referencing a data item in a Kubernetes Secret which holds the symmetric MAC key of the External Account Binding. The `key` is the index string that is paired with the key data in the Secret and should not be confused with the key data itself, or indeed with the External Account Binding keyID above. The secret key stored in the Secret **must** be un-padded, base64 URL encoded data. - type: object - required: - - name - properties: - key: - description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. - type: string - name: - description: 'Name of the resource being referred to. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' - type: string - preferredChain: - description: 'PreferredChain is the chain to use if the ACME server outputs multiple. PreferredChain is no guarantee that this one gets delivered by the ACME endpoint. For example, for Let''s Encrypt''s DST crosssign you would use: "DST Root CA X3" or "ISRG Root X1" for the newer Let''s Encrypt root CA. This value picks the first certificate bundle in the ACME alternative chains that has a certificate with this value as its issuer''s CN' - type: string - maxLength: 64 - privateKeySecretRef: - description: PrivateKey is the name of a Kubernetes Secret resource that will be used to store the automatically generated ACME account private key. Optionally, a `key` may be specified to select a specific entry within the named Secret resource. If `key` is not specified, a default of `tls.key` will be used. - type: object - required: - - name - properties: - key: - description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. - type: string - name: - description: 'Name of the resource being referred to. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' - type: string - server: - description: 'Server is the URL used to access the ACME server''s ''directory'' endpoint. For example, for Let''s Encrypt''s staging endpoint, you would use: "https://acme-staging-v02.api.letsencrypt.org/directory". Only ACME v2 endpoints (i.e. RFC 8555) are supported.' - type: string - skipTLSVerify: - description: 'INSECURE: Enables or disables validation of the ACME server TLS certificate. If true, requests to the ACME server will not have the TLS certificate chain validated. Mutually exclusive with CABundle; prefer using CABundle to prevent various kinds of security vulnerabilities. Only enable this option in development environments. If CABundle and SkipTLSVerify are unset, the system certificate bundle inside the container is used to validate the TLS connection. Defaults to false.' - type: boolean - solvers: - description: 'Solvers is a list of challenge solvers that will be used to solve ACME challenges for the matching domains. Solver configurations must be provided in order to obtain certificates from an ACME server. For more information, see: https://cert-manager.io/docs/configuration/acme/' - type: array - items: - description: An ACMEChallengeSolver describes how to solve ACME challenges for the issuer it is part of. A selector may be provided to use different solving strategies for different DNS names. Only one of HTTP01 or DNS01 must be provided. - type: object - properties: - dns01: - description: Configures cert-manager to attempt to complete authorizations by performing the DNS01 challenge flow. - type: object - properties: - acmeDNS: - description: Use the 'ACME DNS' (https://github.com/joohoi/acme-dns) API to manage DNS01 challenge records. - type: object - required: - - accountSecretRef - - host - properties: - accountSecretRef: - description: A reference to a specific 'key' within a Secret resource. In some instances, `key` is a required field. - type: object - required: - - name - properties: - key: - description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. - type: string - name: - description: 'Name of the resource being referred to. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' - type: string - host: - type: string - akamai: - description: Use the Akamai DNS zone management API to manage DNS01 challenge records. - type: object - required: - - accessTokenSecretRef - - clientSecretSecretRef - - clientTokenSecretRef - - serviceConsumerDomain - properties: - accessTokenSecretRef: - description: A reference to a specific 'key' within a Secret resource. In some instances, `key` is a required field. - type: object - required: - - name - properties: - key: - description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. - type: string - name: - description: 'Name of the resource being referred to. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' - type: string - clientSecretSecretRef: - description: A reference to a specific 'key' within a Secret resource. In some instances, `key` is a required field. - type: object - required: - - name - properties: - key: - description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. - type: string - name: - description: 'Name of the resource being referred to. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' - type: string - clientTokenSecretRef: - description: A reference to a specific 'key' within a Secret resource. In some instances, `key` is a required field. - type: object - required: - - name - properties: - key: - description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. - type: string - name: - description: 'Name of the resource being referred to. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' - type: string - serviceConsumerDomain: - type: string - azureDNS: - description: Use the Microsoft Azure DNS API to manage DNS01 challenge records. - type: object - required: - - resourceGroupName - - subscriptionID - properties: - clientID: - description: 'Auth: Azure Service Principal: The ClientID of the Azure Service Principal used to authenticate with Azure DNS. If set, ClientSecret and TenantID must also be set.' - type: string - clientSecretSecretRef: - description: 'Auth: Azure Service Principal: A reference to a Secret containing the password associated with the Service Principal. If set, ClientID and TenantID must also be set.' - type: object - required: - - name - properties: - key: - description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. - type: string - name: - description: 'Name of the resource being referred to. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' - type: string - environment: - description: name of the Azure environment (default AzurePublicCloud) - type: string - enum: - - AzurePublicCloud - - AzureChinaCloud - - AzureGermanCloud - - AzureUSGovernmentCloud - hostedZoneName: - description: name of the DNS zone that should be used - type: string - managedIdentity: - description: 'Auth: Azure Workload Identity or Azure Managed Service Identity: Settings to enable Azure Workload Identity or Azure Managed Service Identity If set, ClientID, ClientSecret and TenantID must not be set.' - type: object - properties: - clientID: - description: client ID of the managed identity, can not be used at the same time as resourceID - type: string - resourceID: - description: resource ID of the managed identity, can not be used at the same time as clientID Cannot be used for Azure Managed Service Identity - type: string - resourceGroupName: - description: resource group the DNS zone is located in - type: string - subscriptionID: - description: ID of the Azure subscription - type: string - tenantID: - description: 'Auth: Azure Service Principal: The TenantID of the Azure Service Principal used to authenticate with Azure DNS. If set, ClientID and ClientSecret must also be set.' - type: string - cloudDNS: - description: Use the Google Cloud DNS API to manage DNS01 challenge records. - type: object - required: - - project - properties: - hostedZoneName: - description: HostedZoneName is an optional field that tells cert-manager in which Cloud DNS zone the challenge record has to be created. If left empty cert-manager will automatically choose a zone. - type: string - project: - type: string - serviceAccountSecretRef: - description: A reference to a specific 'key' within a Secret resource. In some instances, `key` is a required field. - type: object - required: - - name - properties: - key: - description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. - type: string - name: - description: 'Name of the resource being referred to. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' - type: string - cloudflare: - description: Use the Cloudflare API to manage DNS01 challenge records. - type: object - properties: - apiKeySecretRef: - description: 'API key to use to authenticate with Cloudflare. Note: using an API token to authenticate is now the recommended method as it allows greater control of permissions.' - type: object - required: - - name - properties: - key: - description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. - type: string - name: - description: 'Name of the resource being referred to. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' - type: string - apiTokenSecretRef: - description: API token used to authenticate with Cloudflare. - type: object - required: - - name - properties: - key: - description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. - type: string - name: - description: 'Name of the resource being referred to. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' - type: string - email: - description: Email of the account, only required when using API key based authentication. - type: string - cnameStrategy: - description: CNAMEStrategy configures how the DNS01 provider should handle CNAME records when found in DNS zones. - type: string - enum: - - None - - Follow - digitalocean: - description: Use the DigitalOcean DNS API to manage DNS01 challenge records. - type: object - required: - - tokenSecretRef - properties: - tokenSecretRef: - description: A reference to a specific 'key' within a Secret resource. In some instances, `key` is a required field. - type: object - required: - - name - properties: - key: - description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. - type: string - name: - description: 'Name of the resource being referred to. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' - type: string - rfc2136: - description: Use RFC2136 ("Dynamic Updates in the Domain Name System") (https://datatracker.ietf.org/doc/rfc2136/) to manage DNS01 challenge records. - type: object - required: - - nameserver - properties: - nameserver: - description: The IP address or hostname of an authoritative DNS server supporting RFC2136 in the form host:port. If the host is an IPv6 address it must be enclosed in square brackets (e.g [2001:db8::1]) ; port is optional. This field is required. - type: string - tsigAlgorithm: - description: 'The TSIG Algorithm configured in the DNS supporting RFC2136. Used only when ``tsigSecretSecretRef`` and ``tsigKeyName`` are defined. Supported values are (case-insensitive): ``HMACMD5`` (default), ``HMACSHA1``, ``HMACSHA256`` or ``HMACSHA512``.' - type: string - tsigKeyName: - description: The TSIG Key name configured in the DNS. If ``tsigSecretSecretRef`` is defined, this field is required. - type: string - tsigSecretSecretRef: - description: The name of the secret containing the TSIG value. If ``tsigKeyName`` is defined, this field is required. - type: object - required: - - name - properties: - key: - description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. - type: string - name: - description: 'Name of the resource being referred to. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' - type: string - route53: - description: Use the AWS Route53 API to manage DNS01 challenge records. - type: object - required: - - region - properties: - accessKeyID: - description: 'The AccessKeyID is used for authentication. Cannot be set when SecretAccessKeyID is set. If neither the Access Key nor Key ID are set, we fall-back to using env vars, shared credentials file or AWS Instance metadata, see: https://docs.aws.amazon.com/sdk-for-go/v1/developer-guide/configuring-sdk.html#specifying-credentials' - type: string - accessKeyIDSecretRef: - description: 'The SecretAccessKey is used for authentication. If set, pull the AWS access key ID from a key within a Kubernetes Secret. Cannot be set when AccessKeyID is set. If neither the Access Key nor Key ID are set, we fall-back to using env vars, shared credentials file or AWS Instance metadata, see: https://docs.aws.amazon.com/sdk-for-go/v1/developer-guide/configuring-sdk.html#specifying-credentials' - type: object - required: - - name - properties: - key: - description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. - type: string - name: - description: 'Name of the resource being referred to. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' - type: string - hostedZoneID: - description: If set, the provider will manage only this zone in Route53 and will not do an lookup using the route53:ListHostedZonesByName api call. - type: string - region: - description: Always set the region when using AccessKeyID and SecretAccessKey - type: string - role: - description: Role is a Role ARN which the Route53 provider will assume using either the explicit credentials AccessKeyID/SecretAccessKey or the inferred credentials from environment variables, shared credentials file or AWS Instance metadata - type: string - secretAccessKeySecretRef: - description: 'The SecretAccessKey is used for authentication. If neither the Access Key nor Key ID are set, we fall-back to using env vars, shared credentials file or AWS Instance metadata, see: https://docs.aws.amazon.com/sdk-for-go/v1/developer-guide/configuring-sdk.html#specifying-credentials' - type: object - required: - - name - properties: - key: - description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. - type: string - name: - description: 'Name of the resource being referred to. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' - type: string - webhook: - description: Configure an external webhook based DNS01 challenge solver to manage DNS01 challenge records. - type: object - required: - - groupName - - solverName - properties: - config: - description: Additional configuration that should be passed to the webhook apiserver when challenges are processed. This can contain arbitrary JSON data. Secret values should not be specified in this stanza. If secret values are needed (e.g. credentials for a DNS service), you should use a SecretKeySelector to reference a Secret resource. For details on the schema of this field, consult the webhook provider implementation's documentation. - x-kubernetes-preserve-unknown-fields: true - groupName: - description: The API group name that should be used when POSTing ChallengePayload resources to the webhook apiserver. This should be the same as the GroupName specified in the webhook provider implementation. - type: string - solverName: - description: The name of the solver to use, as defined in the webhook provider implementation. This will typically be the name of the provider, e.g. 'cloudflare'. - type: string - http01: - description: Configures cert-manager to attempt to complete authorizations by performing the HTTP01 challenge flow. It is not possible to obtain certificates for wildcard domain names (e.g. `*.example.com`) using the HTTP01 challenge mechanism. - type: object - properties: - gatewayHTTPRoute: - description: The Gateway API is a sig-network community API that models service networking in Kubernetes (https://gateway-api.sigs.k8s.io/). The Gateway solver will create HTTPRoutes with the specified labels in the same namespace as the challenge. This solver is experimental, and fields / behaviour may change in the future. - type: object - properties: - labels: - description: Custom labels that will be applied to HTTPRoutes created by cert-manager while solving HTTP-01 challenges. - type: object - additionalProperties: - type: string - parentRefs: - description: 'When solving an HTTP-01 challenge, cert-manager creates an HTTPRoute. cert-manager needs to know which parentRefs should be used when creating the HTTPRoute. Usually, the parentRef references a Gateway. See: https://gateway-api.sigs.k8s.io/api-types/httproute/#attaching-to-gateways' - type: array - items: - description: "ParentReference identifies an API object (usually a Gateway) that can be considered a parent of this resource (usually a route). There are two kinds of parent resources with \"Core\" support: \n * Gateway (Gateway conformance profile) * Service (Mesh conformance profile, experimental, ClusterIP Services only) \n This API may be extended in the future to support additional kinds of parent resources. \n The API object must be valid in the cluster; the Group and Kind must be registered in the cluster for this reference to be valid." - type: object - required: - - name - properties: - group: - description: "Group is the group of the referent. When unspecified, \"gateway.networking.k8s.io\" is inferred. To set the core API group (such as for a \"Service\" kind referent), Group must be explicitly set to \"\" (empty string). \n Support: Core" - type: string - default: gateway.networking.k8s.io - maxLength: 253 - pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ - kind: - description: "Kind is kind of the referent. \n There are two kinds of parent resources with \"Core\" support: \n * Gateway (Gateway conformance profile) * Service (Mesh conformance profile, experimental, ClusterIP Services only) \n Support for other resources is Implementation-Specific." - type: string - default: Gateway - maxLength: 63 - minLength: 1 - pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ - name: - description: "Name is the name of the referent. \n Support: Core" - type: string - maxLength: 253 - minLength: 1 - namespace: - description: "Namespace is the namespace of the referent. When unspecified, this refers to the local namespace of the Route. \n Note that there are specific rules for ParentRefs which cross namespace boundaries. Cross-namespace references are only valid if they are explicitly allowed by something in the namespace they are referring to. For example: Gateway has the AllowedRoutes field, and ReferenceGrant provides a generic way to enable any other kind of cross-namespace reference. \n ParentRefs from a Route to a Service in the same namespace are \"producer\" routes, which apply default routing rules to inbound connections from any namespace to the Service. \n ParentRefs from a Route to a Service in a different namespace are \"consumer\" routes, and these routing rules are only applied to outbound connections originating from the same namespace as the Route, for which the intended destination of the connections are a Service targeted as a ParentRef of the Route. \n Support: Core" - type: string - maxLength: 63 - minLength: 1 - pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ - port: - description: "Port is the network port this Route targets. It can be interpreted differently based on the type of parent resource. \n When the parent resource is a Gateway, this targets all listeners listening on the specified port that also support this kind of Route(and select this Route). It's not recommended to set `Port` unless the networking behaviors specified in a Route must apply to a specific port as opposed to a listener(s) whose port(s) may be changed. When both Port and SectionName are specified, the name and port of the selected listener must match both specified values. \n When the parent resource is a Service, this targets a specific port in the Service spec. When both Port (experimental) and SectionName are specified, the name and port of the selected port must match both specified values. \n Implementations MAY choose to support other parent resources. Implementations supporting other types of parent resources MUST clearly document how/if Port is interpreted. \n For the purpose of status, an attachment is considered successful as long as the parent resource accepts it partially. For example, Gateway listeners can restrict which Routes can attach to them by Route kind, namespace, or hostname. If 1 of 2 Gateway listeners accept attachment from the referencing Route, the Route MUST be considered successfully attached. If no Gateway listeners accept attachment from this Route, the Route MUST be considered detached from the Gateway. \n Support: Extended \n " - type: integer - format: int32 - maximum: 65535 - minimum: 1 - sectionName: - description: "SectionName is the name of a section within the target resource. In the following resources, SectionName is interpreted as the following: \n * Gateway: Listener Name. When both Port (experimental) and SectionName are specified, the name and port of the selected listener must match both specified values. * Service: Port Name. When both Port (experimental) and SectionName are specified, the name and port of the selected listener must match both specified values. Note that attaching Routes to Services as Parents is part of experimental Mesh support and is not supported for any other purpose. \n Implementations MAY choose to support attaching Routes to other resources. If that is the case, they MUST clearly document how SectionName is interpreted. \n When unspecified (empty string), this will reference the entire resource. For the purpose of status, an attachment is considered successful if at least one section in the parent resource accepts it. For example, Gateway listeners can restrict which Routes can attach to them by Route kind, namespace, or hostname. If 1 of 2 Gateway listeners accept attachment from the referencing Route, the Route MUST be considered successfully attached. If no Gateway listeners accept attachment from this Route, the Route MUST be considered detached from the Gateway. \n Support: Core" - type: string - maxLength: 253 - minLength: 1 - pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ - serviceType: - description: Optional service type for Kubernetes solver service. Supported values are NodePort or ClusterIP. If unset, defaults to NodePort. - type: string - ingress: - description: The ingress based HTTP01 challenge solver will solve challenges by creating or modifying Ingress resources in order to route requests for '/.well-known/acme-challenge/XYZ' to 'challenge solver' pods that are provisioned by cert-manager for each Challenge to be completed. - type: object - properties: - class: - description: This field configures the annotation `kubernetes.io/ingress.class` when creating Ingress resources to solve ACME challenges that use this challenge solver. Only one of `class`, `name` or `ingressClassName` may be specified. - type: string - ingressClassName: - description: This field configures the field `ingressClassName` on the created Ingress resources used to solve ACME challenges that use this challenge solver. This is the recommended way of configuring the ingress class. Only one of `class`, `name` or `ingressClassName` may be specified. - type: string - ingressTemplate: - description: Optional ingress template used to configure the ACME challenge solver ingress used for HTTP01 challenges. - type: object - properties: - metadata: - description: ObjectMeta overrides for the ingress used to solve HTTP01 challenges. Only the 'labels' and 'annotations' fields may be set. If labels or annotations overlap with in-built values, the values here will override the in-built values. - type: object - properties: - annotations: - description: Annotations that should be added to the created ACME HTTP01 solver ingress. - type: object - additionalProperties: - type: string - labels: - description: Labels that should be added to the created ACME HTTP01 solver ingress. - type: object - additionalProperties: - type: string - name: - description: The name of the ingress resource that should have ACME challenge solving routes inserted into it in order to solve HTTP01 challenges. This is typically used in conjunction with ingress controllers like ingress-gce, which maintains a 1:1 mapping between external IPs and ingress resources. Only one of `class`, `name` or `ingressClassName` may be specified. - type: string - podTemplate: - description: Optional pod template used to configure the ACME challenge solver pods used for HTTP01 challenges. - type: object - properties: - metadata: - description: ObjectMeta overrides for the pod used to solve HTTP01 challenges. Only the 'labels' and 'annotations' fields may be set. If labels or annotations overlap with in-built values, the values here will override the in-built values. - type: object - properties: - annotations: - description: Annotations that should be added to the create ACME HTTP01 solver pods. - type: object - additionalProperties: - type: string - labels: - description: Labels that should be added to the created ACME HTTP01 solver pods. - type: object - additionalProperties: - type: string - spec: - description: PodSpec defines overrides for the HTTP01 challenge solver pod. Check ACMEChallengeSolverHTTP01IngressPodSpec to find out currently supported fields. All other fields will be ignored. - type: object - properties: - affinity: - description: If specified, the pod's scheduling constraints - type: object - properties: - nodeAffinity: - description: Describes node affinity scheduling rules for the pod. - type: object - properties: - preferredDuringSchedulingIgnoredDuringExecution: - description: The scheduler will prefer to schedule pods to nodes that satisfy the affinity expressions specified by this field, but it may choose a node that violates one or more of the expressions. The node that is most preferred is the one with the greatest sum of weights, i.e. for each node that meets all of the scheduling requirements (resource request, requiredDuringScheduling affinity expressions, etc.), compute a sum by iterating through the elements of this field and adding "weight" to the sum if the node matches the corresponding matchExpressions; the node(s) with the highest sum are the most preferred. - type: array - items: - description: An empty preferred scheduling term matches all objects with implicit weight 0 (i.e. it's a no-op). A null preferred scheduling term matches no objects (i.e. is also a no-op). - type: object - required: - - preference - - weight - properties: - preference: - description: A node selector term, associated with the corresponding weight. - type: object - properties: - matchExpressions: - description: A list of node selector requirements by node's labels. - type: array - items: - description: A node selector requirement is a selector that contains values, a key, and an operator that relates the key and values. - type: object - required: - - key - - operator - properties: - key: - description: The label key that the selector applies to. - type: string - operator: - description: Represents a key's relationship to a set of values. Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. - type: string - values: - description: An array of string values. If the operator is In or NotIn, the values array must be non-empty. If the operator is Exists or DoesNotExist, the values array must be empty. If the operator is Gt or Lt, the values array must have a single element, which will be interpreted as an integer. This array is replaced during a strategic merge patch. - type: array - items: - type: string - matchFields: - description: A list of node selector requirements by node's fields. - type: array - items: - description: A node selector requirement is a selector that contains values, a key, and an operator that relates the key and values. - type: object - required: - - key - - operator - properties: - key: - description: The label key that the selector applies to. - type: string - operator: - description: Represents a key's relationship to a set of values. Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. - type: string - values: - description: An array of string values. If the operator is In or NotIn, the values array must be non-empty. If the operator is Exists or DoesNotExist, the values array must be empty. If the operator is Gt or Lt, the values array must have a single element, which will be interpreted as an integer. This array is replaced during a strategic merge patch. - type: array - items: - type: string - x-kubernetes-map-type: atomic - weight: - description: Weight associated with matching the corresponding nodeSelectorTerm, in the range 1-100. - type: integer - format: int32 - requiredDuringSchedulingIgnoredDuringExecution: - description: If the affinity requirements specified by this field are not met at scheduling time, the pod will not be scheduled onto the node. If the affinity requirements specified by this field cease to be met at some point during pod execution (e.g. due to an update), the system may or may not try to eventually evict the pod from its node. - type: object - required: - - nodeSelectorTerms - properties: - nodeSelectorTerms: - description: Required. A list of node selector terms. The terms are ORed. - type: array - items: - description: A null or empty node selector term matches no objects. The requirements of them are ANDed. The TopologySelectorTerm type implements a subset of the NodeSelectorTerm. - type: object - properties: - matchExpressions: - description: A list of node selector requirements by node's labels. - type: array - items: - description: A node selector requirement is a selector that contains values, a key, and an operator that relates the key and values. - type: object - required: - - key - - operator - properties: - key: - description: The label key that the selector applies to. - type: string - operator: - description: Represents a key's relationship to a set of values. Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. - type: string - values: - description: An array of string values. If the operator is In or NotIn, the values array must be non-empty. If the operator is Exists or DoesNotExist, the values array must be empty. If the operator is Gt or Lt, the values array must have a single element, which will be interpreted as an integer. This array is replaced during a strategic merge patch. - type: array - items: - type: string - matchFields: - description: A list of node selector requirements by node's fields. - type: array - items: - description: A node selector requirement is a selector that contains values, a key, and an operator that relates the key and values. - type: object - required: - - key - - operator - properties: - key: - description: The label key that the selector applies to. - type: string - operator: - description: Represents a key's relationship to a set of values. Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. - type: string - values: - description: An array of string values. If the operator is In or NotIn, the values array must be non-empty. If the operator is Exists or DoesNotExist, the values array must be empty. If the operator is Gt or Lt, the values array must have a single element, which will be interpreted as an integer. This array is replaced during a strategic merge patch. - type: array - items: - type: string - x-kubernetes-map-type: atomic - x-kubernetes-map-type: atomic - podAffinity: - description: Describes pod affinity scheduling rules (e.g. co-locate this pod in the same node, zone, etc. as some other pod(s)). - type: object - properties: - preferredDuringSchedulingIgnoredDuringExecution: - description: The scheduler will prefer to schedule pods to nodes that satisfy the affinity expressions specified by this field, but it may choose a node that violates one or more of the expressions. The node that is most preferred is the one with the greatest sum of weights, i.e. for each node that meets all of the scheduling requirements (resource request, requiredDuringScheduling affinity expressions, etc.), compute a sum by iterating through the elements of this field and adding "weight" to the sum if the node has pods which matches the corresponding podAffinityTerm; the node(s) with the highest sum are the most preferred. - type: array - items: - description: The weights of all of the matched WeightedPodAffinityTerm fields are added per-node to find the most preferred node(s) - type: object - required: - - podAffinityTerm - - weight - properties: - podAffinityTerm: - description: Required. A pod affinity term, associated with the corresponding weight. - type: object - required: - - topologyKey - properties: - labelSelector: - description: A label query over a set of resources, in this case pods. If it's null, this PodAffinityTerm matches with no Pods. - type: object - properties: - matchExpressions: - description: matchExpressions is a list of label selector requirements. The requirements are ANDed. - type: array - items: - description: A label selector requirement is a selector that contains values, a key, and an operator that relates the key and values. - type: object - required: - - key - - operator - properties: - key: - description: key is the label key that the selector applies to. - type: string - operator: - description: operator represents a key's relationship to a set of values. Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: values is an array of string values. If the operator is In or NotIn, the values array must be non-empty. If the operator is Exists or DoesNotExist, the values array must be empty. This array is replaced during a strategic merge patch. - type: array - items: - type: string - matchLabels: - description: matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels map is equivalent to an element of matchExpressions, whose key field is "key", the operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - additionalProperties: - type: string - x-kubernetes-map-type: atomic - matchLabelKeys: - description: MatchLabelKeys is a set of pod label keys to select which pods will be taken into consideration. The keys are used to lookup values from the incoming pod labels, those key-value labels are merged with `LabelSelector` as `key in (value)` to select the group of existing pods which pods will be taken into consideration for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both MatchLabelKeys and LabelSelector. Also, MatchLabelKeys cannot be set when LabelSelector isn't set. This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. - type: array - items: - type: string - x-kubernetes-list-type: atomic - mismatchLabelKeys: - description: MismatchLabelKeys is a set of pod label keys to select which pods will be taken into consideration. The keys are used to lookup values from the incoming pod labels, those key-value labels are merged with `LabelSelector` as `key notin (value)` to select the group of existing pods which pods will be taken into consideration for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both MismatchLabelKeys and LabelSelector. Also, MismatchLabelKeys cannot be set when LabelSelector isn't set. This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. - type: array - items: - type: string - x-kubernetes-list-type: atomic - namespaceSelector: - description: A label query over the set of namespaces that the term applies to. The term is applied to the union of the namespaces selected by this field and the ones listed in the namespaces field. null selector and null or empty namespaces list means "this pod's namespace". An empty selector ({}) matches all namespaces. - type: object - properties: - matchExpressions: - description: matchExpressions is a list of label selector requirements. The requirements are ANDed. - type: array - items: - description: A label selector requirement is a selector that contains values, a key, and an operator that relates the key and values. - type: object - required: - - key - - operator - properties: - key: - description: key is the label key that the selector applies to. - type: string - operator: - description: operator represents a key's relationship to a set of values. Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: values is an array of string values. If the operator is In or NotIn, the values array must be non-empty. If the operator is Exists or DoesNotExist, the values array must be empty. This array is replaced during a strategic merge patch. - type: array - items: - type: string - matchLabels: - description: matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels map is equivalent to an element of matchExpressions, whose key field is "key", the operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - additionalProperties: - type: string - x-kubernetes-map-type: atomic - namespaces: - description: namespaces specifies a static list of namespace names that the term applies to. The term is applied to the union of the namespaces listed in this field and the ones selected by namespaceSelector. null or empty namespaces list and null namespaceSelector means "this pod's namespace". - type: array - items: - type: string - topologyKey: - description: This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching the labelSelector in the specified namespaces, where co-located is defined as running on a node whose value of the label with key topologyKey matches that of any node on which any of the selected pods is running. Empty topologyKey is not allowed. - type: string - weight: - description: weight associated with matching the corresponding podAffinityTerm, in the range 1-100. - type: integer - format: int32 - requiredDuringSchedulingIgnoredDuringExecution: - description: If the affinity requirements specified by this field are not met at scheduling time, the pod will not be scheduled onto the node. If the affinity requirements specified by this field cease to be met at some point during pod execution (e.g. due to a pod label update), the system may or may not try to eventually evict the pod from its node. When there are multiple elements, the lists of nodes corresponding to each podAffinityTerm are intersected, i.e. all terms must be satisfied. - type: array - items: - description: Defines a set of pods (namely those matching the labelSelector relative to the given namespace(s)) that this pod should be co-located (affinity) or not co-located (anti-affinity) with, where co-located is defined as running on a node whose value of the label with key matches that of any node on which a pod of the set of pods is running - type: object - required: - - topologyKey - properties: - labelSelector: - description: A label query over a set of resources, in this case pods. If it's null, this PodAffinityTerm matches with no Pods. - type: object - properties: - matchExpressions: - description: matchExpressions is a list of label selector requirements. The requirements are ANDed. - type: array - items: - description: A label selector requirement is a selector that contains values, a key, and an operator that relates the key and values. - type: object - required: - - key - - operator - properties: - key: - description: key is the label key that the selector applies to. - type: string - operator: - description: operator represents a key's relationship to a set of values. Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: values is an array of string values. If the operator is In or NotIn, the values array must be non-empty. If the operator is Exists or DoesNotExist, the values array must be empty. This array is replaced during a strategic merge patch. - type: array - items: - type: string - matchLabels: - description: matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels map is equivalent to an element of matchExpressions, whose key field is "key", the operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - additionalProperties: - type: string - x-kubernetes-map-type: atomic - matchLabelKeys: - description: MatchLabelKeys is a set of pod label keys to select which pods will be taken into consideration. The keys are used to lookup values from the incoming pod labels, those key-value labels are merged with `LabelSelector` as `key in (value)` to select the group of existing pods which pods will be taken into consideration for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both MatchLabelKeys and LabelSelector. Also, MatchLabelKeys cannot be set when LabelSelector isn't set. This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. - type: array - items: - type: string - x-kubernetes-list-type: atomic - mismatchLabelKeys: - description: MismatchLabelKeys is a set of pod label keys to select which pods will be taken into consideration. The keys are used to lookup values from the incoming pod labels, those key-value labels are merged with `LabelSelector` as `key notin (value)` to select the group of existing pods which pods will be taken into consideration for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both MismatchLabelKeys and LabelSelector. Also, MismatchLabelKeys cannot be set when LabelSelector isn't set. This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. - type: array - items: - type: string - x-kubernetes-list-type: atomic - namespaceSelector: - description: A label query over the set of namespaces that the term applies to. The term is applied to the union of the namespaces selected by this field and the ones listed in the namespaces field. null selector and null or empty namespaces list means "this pod's namespace". An empty selector ({}) matches all namespaces. - type: object - properties: - matchExpressions: - description: matchExpressions is a list of label selector requirements. The requirements are ANDed. - type: array - items: - description: A label selector requirement is a selector that contains values, a key, and an operator that relates the key and values. - type: object - required: - - key - - operator - properties: - key: - description: key is the label key that the selector applies to. - type: string - operator: - description: operator represents a key's relationship to a set of values. Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: values is an array of string values. If the operator is In or NotIn, the values array must be non-empty. If the operator is Exists or DoesNotExist, the values array must be empty. This array is replaced during a strategic merge patch. - type: array - items: - type: string - matchLabels: - description: matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels map is equivalent to an element of matchExpressions, whose key field is "key", the operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - additionalProperties: - type: string - x-kubernetes-map-type: atomic - namespaces: - description: namespaces specifies a static list of namespace names that the term applies to. The term is applied to the union of the namespaces listed in this field and the ones selected by namespaceSelector. null or empty namespaces list and null namespaceSelector means "this pod's namespace". - type: array - items: - type: string - topologyKey: - description: This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching the labelSelector in the specified namespaces, where co-located is defined as running on a node whose value of the label with key topologyKey matches that of any node on which any of the selected pods is running. Empty topologyKey is not allowed. - type: string - podAntiAffinity: - description: Describes pod anti-affinity scheduling rules (e.g. avoid putting this pod in the same node, zone, etc. as some other pod(s)). - type: object - properties: - preferredDuringSchedulingIgnoredDuringExecution: - description: The scheduler will prefer to schedule pods to nodes that satisfy the anti-affinity expressions specified by this field, but it may choose a node that violates one or more of the expressions. The node that is most preferred is the one with the greatest sum of weights, i.e. for each node that meets all of the scheduling requirements (resource request, requiredDuringScheduling anti-affinity expressions, etc.), compute a sum by iterating through the elements of this field and adding "weight" to the sum if the node has pods which matches the corresponding podAffinityTerm; the node(s) with the highest sum are the most preferred. - type: array - items: - description: The weights of all of the matched WeightedPodAffinityTerm fields are added per-node to find the most preferred node(s) - type: object - required: - - podAffinityTerm - - weight - properties: - podAffinityTerm: - description: Required. A pod affinity term, associated with the corresponding weight. - type: object - required: - - topologyKey - properties: - labelSelector: - description: A label query over a set of resources, in this case pods. If it's null, this PodAffinityTerm matches with no Pods. - type: object - properties: - matchExpressions: - description: matchExpressions is a list of label selector requirements. The requirements are ANDed. - type: array - items: - description: A label selector requirement is a selector that contains values, a key, and an operator that relates the key and values. - type: object - required: - - key - - operator - properties: - key: - description: key is the label key that the selector applies to. - type: string - operator: - description: operator represents a key's relationship to a set of values. Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: values is an array of string values. If the operator is In or NotIn, the values array must be non-empty. If the operator is Exists or DoesNotExist, the values array must be empty. This array is replaced during a strategic merge patch. - type: array - items: - type: string - matchLabels: - description: matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels map is equivalent to an element of matchExpressions, whose key field is "key", the operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - additionalProperties: - type: string - x-kubernetes-map-type: atomic - matchLabelKeys: - description: MatchLabelKeys is a set of pod label keys to select which pods will be taken into consideration. The keys are used to lookup values from the incoming pod labels, those key-value labels are merged with `LabelSelector` as `key in (value)` to select the group of existing pods which pods will be taken into consideration for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both MatchLabelKeys and LabelSelector. Also, MatchLabelKeys cannot be set when LabelSelector isn't set. This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. - type: array - items: - type: string - x-kubernetes-list-type: atomic - mismatchLabelKeys: - description: MismatchLabelKeys is a set of pod label keys to select which pods will be taken into consideration. The keys are used to lookup values from the incoming pod labels, those key-value labels are merged with `LabelSelector` as `key notin (value)` to select the group of existing pods which pods will be taken into consideration for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both MismatchLabelKeys and LabelSelector. Also, MismatchLabelKeys cannot be set when LabelSelector isn't set. This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. - type: array - items: - type: string - x-kubernetes-list-type: atomic - namespaceSelector: - description: A label query over the set of namespaces that the term applies to. The term is applied to the union of the namespaces selected by this field and the ones listed in the namespaces field. null selector and null or empty namespaces list means "this pod's namespace". An empty selector ({}) matches all namespaces. - type: object - properties: - matchExpressions: - description: matchExpressions is a list of label selector requirements. The requirements are ANDed. - type: array - items: - description: A label selector requirement is a selector that contains values, a key, and an operator that relates the key and values. - type: object - required: - - key - - operator - properties: - key: - description: key is the label key that the selector applies to. - type: string - operator: - description: operator represents a key's relationship to a set of values. Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: values is an array of string values. If the operator is In or NotIn, the values array must be non-empty. If the operator is Exists or DoesNotExist, the values array must be empty. This array is replaced during a strategic merge patch. - type: array - items: - type: string - matchLabels: - description: matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels map is equivalent to an element of matchExpressions, whose key field is "key", the operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - additionalProperties: - type: string - x-kubernetes-map-type: atomic - namespaces: - description: namespaces specifies a static list of namespace names that the term applies to. The term is applied to the union of the namespaces listed in this field and the ones selected by namespaceSelector. null or empty namespaces list and null namespaceSelector means "this pod's namespace". - type: array - items: - type: string - topologyKey: - description: This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching the labelSelector in the specified namespaces, where co-located is defined as running on a node whose value of the label with key topologyKey matches that of any node on which any of the selected pods is running. Empty topologyKey is not allowed. - type: string - weight: - description: weight associated with matching the corresponding podAffinityTerm, in the range 1-100. - type: integer - format: int32 - requiredDuringSchedulingIgnoredDuringExecution: - description: If the anti-affinity requirements specified by this field are not met at scheduling time, the pod will not be scheduled onto the node. If the anti-affinity requirements specified by this field cease to be met at some point during pod execution (e.g. due to a pod label update), the system may or may not try to eventually evict the pod from its node. When there are multiple elements, the lists of nodes corresponding to each podAffinityTerm are intersected, i.e. all terms must be satisfied. - type: array - items: - description: Defines a set of pods (namely those matching the labelSelector relative to the given namespace(s)) that this pod should be co-located (affinity) or not co-located (anti-affinity) with, where co-located is defined as running on a node whose value of the label with key matches that of any node on which a pod of the set of pods is running - type: object - required: - - topologyKey - properties: - labelSelector: - description: A label query over a set of resources, in this case pods. If it's null, this PodAffinityTerm matches with no Pods. - type: object - properties: - matchExpressions: - description: matchExpressions is a list of label selector requirements. The requirements are ANDed. - type: array - items: - description: A label selector requirement is a selector that contains values, a key, and an operator that relates the key and values. - type: object - required: - - key - - operator - properties: - key: - description: key is the label key that the selector applies to. - type: string - operator: - description: operator represents a key's relationship to a set of values. Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: values is an array of string values. If the operator is In or NotIn, the values array must be non-empty. If the operator is Exists or DoesNotExist, the values array must be empty. This array is replaced during a strategic merge patch. - type: array - items: - type: string - matchLabels: - description: matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels map is equivalent to an element of matchExpressions, whose key field is "key", the operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - additionalProperties: - type: string - x-kubernetes-map-type: atomic - matchLabelKeys: - description: MatchLabelKeys is a set of pod label keys to select which pods will be taken into consideration. The keys are used to lookup values from the incoming pod labels, those key-value labels are merged with `LabelSelector` as `key in (value)` to select the group of existing pods which pods will be taken into consideration for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both MatchLabelKeys and LabelSelector. Also, MatchLabelKeys cannot be set when LabelSelector isn't set. This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. - type: array - items: - type: string - x-kubernetes-list-type: atomic - mismatchLabelKeys: - description: MismatchLabelKeys is a set of pod label keys to select which pods will be taken into consideration. The keys are used to lookup values from the incoming pod labels, those key-value labels are merged with `LabelSelector` as `key notin (value)` to select the group of existing pods which pods will be taken into consideration for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both MismatchLabelKeys and LabelSelector. Also, MismatchLabelKeys cannot be set when LabelSelector isn't set. This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. - type: array - items: - type: string - x-kubernetes-list-type: atomic - namespaceSelector: - description: A label query over the set of namespaces that the term applies to. The term is applied to the union of the namespaces selected by this field and the ones listed in the namespaces field. null selector and null or empty namespaces list means "this pod's namespace". An empty selector ({}) matches all namespaces. - type: object - properties: - matchExpressions: - description: matchExpressions is a list of label selector requirements. The requirements are ANDed. - type: array - items: - description: A label selector requirement is a selector that contains values, a key, and an operator that relates the key and values. - type: object - required: - - key - - operator - properties: - key: - description: key is the label key that the selector applies to. - type: string - operator: - description: operator represents a key's relationship to a set of values. Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: values is an array of string values. If the operator is In or NotIn, the values array must be non-empty. If the operator is Exists or DoesNotExist, the values array must be empty. This array is replaced during a strategic merge patch. - type: array - items: - type: string - matchLabels: - description: matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels map is equivalent to an element of matchExpressions, whose key field is "key", the operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - additionalProperties: - type: string - x-kubernetes-map-type: atomic - namespaces: - description: namespaces specifies a static list of namespace names that the term applies to. The term is applied to the union of the namespaces listed in this field and the ones selected by namespaceSelector. null or empty namespaces list and null namespaceSelector means "this pod's namespace". - type: array - items: - type: string - topologyKey: - description: This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching the labelSelector in the specified namespaces, where co-located is defined as running on a node whose value of the label with key topologyKey matches that of any node on which any of the selected pods is running. Empty topologyKey is not allowed. - type: string - imagePullSecrets: - description: If specified, the pod's imagePullSecrets - type: array - items: - description: LocalObjectReference contains enough information to let you locate the referenced object inside the same namespace. - type: object - properties: - name: - description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names TODO: Add other useful fields. apiVersion, kind, uid?' - type: string - x-kubernetes-map-type: atomic - nodeSelector: - description: 'NodeSelector is a selector which must be true for the pod to fit on a node. Selector which must match a node''s labels for the pod to be scheduled on that node. More info: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/' - type: object - additionalProperties: - type: string - priorityClassName: - description: If specified, the pod's priorityClassName. - type: string - serviceAccountName: - description: If specified, the pod's service account - type: string - tolerations: - description: If specified, the pod's tolerations. - type: array - items: - description: The pod this Toleration is attached to tolerates any taint that matches the triple using the matching operator . - type: object - properties: - effect: - description: Effect indicates the taint effect to match. Empty means match all taint effects. When specified, allowed values are NoSchedule, PreferNoSchedule and NoExecute. - type: string - key: - description: Key is the taint key that the toleration applies to. Empty means match all taint keys. If the key is empty, operator must be Exists; this combination means to match all values and all keys. - type: string - operator: - description: Operator represents a key's relationship to the value. Valid operators are Exists and Equal. Defaults to Equal. Exists is equivalent to wildcard for value, so that a pod can tolerate all taints of a particular category. - type: string - tolerationSeconds: - description: TolerationSeconds represents the period of time the toleration (which must be of effect NoExecute, otherwise this field is ignored) tolerates the taint. By default, it is not set, which means tolerate the taint forever (do not evict). Zero and negative values will be treated as 0 (evict immediately) by the system. - type: integer - format: int64 - value: - description: Value is the taint value the toleration matches to. If the operator is Exists, the value should be empty, otherwise just a regular string. - type: string - serviceType: - description: Optional service type for Kubernetes solver service. Supported values are NodePort or ClusterIP. If unset, defaults to NodePort. - type: string - selector: - description: Selector selects a set of DNSNames on the Certificate resource that should be solved using this challenge solver. If not specified, the solver will be treated as the 'default' solver with the lowest priority, i.e. if any other solver has a more specific match, it will be used instead. - type: object - properties: - dnsNames: - description: List of DNSNames that this solver will be used to solve. If specified and a match is found, a dnsNames selector will take precedence over a dnsZones selector. If multiple solvers match with the same dnsNames value, the solver with the most matching labels in matchLabels will be selected. If neither has more matches, the solver defined earlier in the list will be selected. - type: array - items: - type: string - dnsZones: - description: List of DNSZones that this solver will be used to solve. The most specific DNS zone match specified here will take precedence over other DNS zone matches, so a solver specifying sys.example.com will be selected over one specifying example.com for the domain www.sys.example.com. If multiple solvers match with the same dnsZones value, the solver with the most matching labels in matchLabels will be selected. If neither has more matches, the solver defined earlier in the list will be selected. - type: array - items: - type: string - matchLabels: - description: A label selector that is used to refine the set of certificate's that this challenge solver will apply to. - type: object - additionalProperties: - type: string - ca: - description: CA configures this issuer to sign certificates using a signing CA keypair stored in a Secret resource. This is used to build internal PKIs that are managed by cert-manager. - type: object - required: - - secretName - properties: - crlDistributionPoints: - description: The CRL distribution points is an X.509 v3 certificate extension which identifies the location of the CRL from which the revocation of this certificate can be checked. If not set, certificates will be issued without distribution points set. - type: array - items: - type: string - issuingCertificateURLs: - description: IssuingCertificateURLs is a list of URLs which this issuer should embed into certificates it creates. See https://www.rfc-editor.org/rfc/rfc5280#section-4.2.2.1 for more details. As an example, such a URL might be "http://ca.domain.com/ca.crt". - type: array - items: - type: string - ocspServers: - description: The OCSP server list is an X.509 v3 extension that defines a list of URLs of OCSP responders. The OCSP responders can be queried for the revocation status of an issued certificate. If not set, the certificate will be issued with no OCSP servers set. For example, an OCSP server URL could be "http://ocsp.int-x3.letsencrypt.org". - type: array - items: - type: string - secretName: - description: SecretName is the name of the secret used to sign Certificates issued by this Issuer. - type: string - selfSigned: - description: SelfSigned configures this issuer to 'self sign' certificates using the private key used to create the CertificateRequest object. - type: object - properties: - crlDistributionPoints: - description: The CRL distribution points is an X.509 v3 certificate extension which identifies the location of the CRL from which the revocation of this certificate can be checked. If not set certificate will be issued without CDP. Values are strings. - type: array - items: - type: string - vault: - description: Vault configures this issuer to sign certificates using a HashiCorp Vault PKI backend. - type: object - required: - - auth - - path - - server - properties: - auth: - description: Auth configures how cert-manager authenticates with the Vault server. - type: object - properties: - appRole: - description: AppRole authenticates with Vault using the App Role auth mechanism, with the role and secret stored in a Kubernetes Secret resource. - type: object - required: - - path - - roleId - - secretRef - properties: - path: - description: 'Path where the App Role authentication backend is mounted in Vault, e.g: "approle"' - type: string - roleId: - description: RoleID configured in the App Role authentication backend when setting up the authentication backend in Vault. - type: string - secretRef: - description: Reference to a key in a Secret that contains the App Role secret used to authenticate with Vault. The `key` field must be specified and denotes which entry within the Secret resource is used as the app role secret. - type: object - required: - - name - properties: - key: - description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. - type: string - name: - description: 'Name of the resource being referred to. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' - type: string - kubernetes: - description: Kubernetes authenticates with Vault by passing the ServiceAccount token stored in the named Secret resource to the Vault server. - type: object - required: - - role - properties: - mountPath: - description: The Vault mountPath here is the mount path to use when authenticating with Vault. For example, setting a value to `/v1/auth/foo`, will use the path `/v1/auth/foo/login` to authenticate with Vault. If unspecified, the default value "/v1/auth/kubernetes" will be used. - type: string - role: - description: A required field containing the Vault Role to assume. A Role binds a Kubernetes ServiceAccount with a set of Vault policies. - type: string - secretRef: - description: The required Secret field containing a Kubernetes ServiceAccount JWT used for authenticating with Vault. Use of 'ambient credentials' is not supported. - type: object - required: - - name - properties: - key: - description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. - type: string - name: - description: 'Name of the resource being referred to. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' - type: string - serviceAccountRef: - description: A reference to a service account that will be used to request a bound token (also known as "projected token"). Compared to using "secretRef", using this field means that you don't rely on statically bound tokens. To use this field, you must configure an RBAC rule to let cert-manager request a token. - type: object - required: - - name - properties: - name: - description: Name of the ServiceAccount used to request a token. - type: string - tokenSecretRef: - description: TokenSecretRef authenticates with Vault by presenting a token. - type: object - required: - - name - properties: - key: - description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. - type: string - name: - description: 'Name of the resource being referred to. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' - type: string - caBundle: - description: Base64-encoded bundle of PEM CAs which will be used to validate the certificate chain presented by Vault. Only used if using HTTPS to connect to Vault and ignored for HTTP connections. Mutually exclusive with CABundleSecretRef. If neither CABundle nor CABundleSecretRef are defined, the certificate bundle in the cert-manager controller container is used to validate the TLS connection. - type: string - format: byte - caBundleSecretRef: - description: Reference to a Secret containing a bundle of PEM-encoded CAs to use when verifying the certificate chain presented by Vault when using HTTPS. Mutually exclusive with CABundle. If neither CABundle nor CABundleSecretRef are defined, the certificate bundle in the cert-manager controller container is used to validate the TLS connection. If no key for the Secret is specified, cert-manager will default to 'ca.crt'. - type: object - required: - - name - properties: - key: - description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. - type: string - name: - description: 'Name of the resource being referred to. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' - type: string - namespace: - description: 'Name of the vault namespace. Namespaces is a set of features within Vault Enterprise that allows Vault environments to support Secure Multi-tenancy. e.g: "ns1" More about namespaces can be found here https://www.vaultproject.io/docs/enterprise/namespaces' - type: string - path: - description: 'Path is the mount path of the Vault PKI backend''s `sign` endpoint, e.g: "my_pki_mount/sign/my-role-name".' - type: string - server: - description: 'Server is the connection address for the Vault server, e.g: "https://vault.example.com:8200".' - type: string - venafi: - description: Venafi configures this issuer to sign certificates using a Venafi TPP or Venafi Cloud policy zone. - type: object - required: - - zone - properties: - cloud: - description: Cloud specifies the Venafi cloud configuration settings. Only one of TPP or Cloud may be specified. - type: object - required: - - apiTokenSecretRef - properties: - apiTokenSecretRef: - description: APITokenSecretRef is a secret key selector for the Venafi Cloud API token. - type: object - required: - - name - properties: - key: - description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. - type: string - name: - description: 'Name of the resource being referred to. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' - type: string - url: - description: URL is the base URL for Venafi Cloud. Defaults to "https://api.venafi.cloud/v1". - type: string - tpp: - description: TPP specifies Trust Protection Platform configuration settings. Only one of TPP or Cloud may be specified. - type: object - required: - - credentialsRef - - url - properties: - caBundle: - description: Base64-encoded bundle of PEM CAs which will be used to validate the certificate chain presented by the TPP server. Only used if using HTTPS; ignored for HTTP. If undefined, the certificate bundle in the cert-manager controller container is used to validate the chain. - type: string - format: byte - credentialsRef: - description: CredentialsRef is a reference to a Secret containing the username and password for the TPP server. The secret must contain two keys, 'username' and 'password'. - type: object - required: - - name - properties: - name: - description: 'Name of the resource being referred to. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' - type: string - url: - description: 'URL is the base URL for the vedsdk endpoint of the Venafi TPP instance, for example: "https://tpp.example.com/vedsdk".' - type: string - zone: - description: Zone is the Venafi Policy Zone to use for this issuer. All requests made to the Venafi platform will be restricted by the named zone policy. This field is required. - type: string - status: - description: Status of the Issuer. This is set and managed automatically. - type: object - properties: - acme: - description: ACME specific status options. This field should only be set if the Issuer is configured to use an ACME server to issue certificates. - type: object - properties: - lastPrivateKeyHash: - description: LastPrivateKeyHash is a hash of the private key associated with the latest registered ACME account, in order to track changes made to registered account associated with the Issuer - type: string - lastRegisteredEmail: - description: LastRegisteredEmail is the email associated with the latest registered ACME account, in order to track changes made to registered account associated with the Issuer - type: string - uri: - description: URI is the unique account identifier, which can also be used to retrieve account details from the CA - type: string - conditions: - description: List of status conditions to indicate the status of a CertificateRequest. Known condition types are `Ready`. - type: array - items: - description: IssuerCondition contains condition information for an Issuer. - type: object - required: - - status - - type - properties: - lastTransitionTime: - description: LastTransitionTime is the timestamp corresponding to the last status change of this condition. - type: string - format: date-time - message: - description: Message is a human readable description of the details of the last transition, complementing reason. - type: string - observedGeneration: - description: If set, this represents the .metadata.generation that the condition was set based upon. For instance, if .metadata.generation is currently 12, but the .status.condition[x].observedGeneration is 9, the condition is out of date with respect to the current state of the Issuer. - type: integer - format: int64 - reason: - description: Reason is a brief machine readable explanation for the condition's last transition. - type: string - status: - description: Status of the condition, one of (`True`, `False`, `Unknown`). - type: string - enum: - - "True" - - "False" - - Unknown - type: - description: Type of the condition, known values are (`Ready`). - type: string - x-kubernetes-list-map-keys: - - type - x-kubernetes-list-type: map - served: true - storage: true ---- -# Source: cert-manager/templates/crds.yaml -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - name: orders.acme.cert-manager.io - labels: - app: 'cert-manager' - app.kubernetes.io/name: 'cert-manager' - app.kubernetes.io/instance: 'cert-manager' - # Generated labels - app.kubernetes.io/version: "v1.14.7" -spec: - group: acme.cert-manager.io - names: - kind: Order - listKind: OrderList - plural: orders - singular: order - categories: - - cert-manager - - cert-manager-acme - scope: Namespaced - versions: - - name: v1 - subresources: - status: {} - additionalPrinterColumns: - - jsonPath: .status.state - name: State - type: string - - jsonPath: .spec.issuerRef.name - name: Issuer - priority: 1 - type: string - - jsonPath: .status.reason - name: Reason - priority: 1 - type: string - - jsonPath: .metadata.creationTimestamp - description: CreationTimestamp is a timestamp representing the server time when this object was created. It is not guaranteed to be set in happens-before order across separate operations. Clients may not set this value. It is represented in RFC3339 form and is in UTC. - name: Age - type: date - schema: - openAPIV3Schema: - description: Order is a type to represent an Order with an ACME server - type: object - required: - - metadata - - spec - properties: - apiVersion: - description: 'APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' - type: string - kind: - description: 'Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' - type: string - metadata: - type: object - spec: - type: object - required: - - issuerRef - - request - properties: - commonName: - description: CommonName is the common name as specified on the DER encoded CSR. If specified, this value must also be present in `dnsNames` or `ipAddresses`. This field must match the corresponding field on the DER encoded CSR. - type: string - dnsNames: - description: DNSNames is a list of DNS names that should be included as part of the Order validation process. This field must match the corresponding field on the DER encoded CSR. - type: array - items: - type: string - duration: - description: Duration is the duration for the not after date for the requested certificate. this is set on order creation as pe the ACME spec. - type: string - ipAddresses: - description: IPAddresses is a list of IP addresses that should be included as part of the Order validation process. This field must match the corresponding field on the DER encoded CSR. - type: array - items: - type: string - issuerRef: - description: IssuerRef references a properly configured ACME-type Issuer which should be used to create this Order. If the Issuer does not exist, processing will be retried. If the Issuer is not an 'ACME' Issuer, an error will be returned and the Order will be marked as failed. - type: object - required: - - name - properties: - group: - description: Group of the resource being referred to. - type: string - kind: - description: Kind of the resource being referred to. - type: string - name: - description: Name of the resource being referred to. - type: string - request: - description: Certificate signing request bytes in DER encoding. This will be used when finalizing the order. This field must be set on the order. - type: string - format: byte - status: - type: object - properties: - authorizations: - description: Authorizations contains data returned from the ACME server on what authorizations must be completed in order to validate the DNS names specified on the Order. - type: array - items: - description: ACMEAuthorization contains data returned from the ACME server on an authorization that must be completed in order validate a DNS name on an ACME Order resource. - type: object - required: - - url - properties: - challenges: - description: Challenges specifies the challenge types offered by the ACME server. One of these challenge types will be selected when validating the DNS name and an appropriate Challenge resource will be created to perform the ACME challenge process. - type: array - items: - description: Challenge specifies a challenge offered by the ACME server for an Order. An appropriate Challenge resource can be created to perform the ACME challenge process. - type: object - required: - - token - - type - - url - properties: - token: - description: Token is the token that must be presented for this challenge. This is used to compute the 'key' that must also be presented. - type: string - type: - description: Type is the type of challenge being offered, e.g. 'http-01', 'dns-01', 'tls-sni-01', etc. This is the raw value retrieved from the ACME server. Only 'http-01' and 'dns-01' are supported by cert-manager, other values will be ignored. - type: string - url: - description: URL is the URL of this challenge. It can be used to retrieve additional metadata about the Challenge from the ACME server. - type: string - identifier: - description: Identifier is the DNS name to be validated as part of this authorization - type: string - initialState: - description: InitialState is the initial state of the ACME authorization when first fetched from the ACME server. If an Authorization is already 'valid', the Order controller will not create a Challenge resource for the authorization. This will occur when working with an ACME server that enables 'authz reuse' (such as Let's Encrypt's production endpoint). If not set and 'identifier' is set, the state is assumed to be pending and a Challenge will be created. - type: string - enum: - - valid - - ready - - pending - - processing - - invalid - - expired - - errored - url: - description: URL is the URL of the Authorization that must be completed - type: string - wildcard: - description: Wildcard will be true if this authorization is for a wildcard DNS name. If this is true, the identifier will be the *non-wildcard* version of the DNS name. For example, if '*.example.com' is the DNS name being validated, this field will be 'true' and the 'identifier' field will be 'example.com'. - type: boolean - certificate: - description: Certificate is a copy of the PEM encoded certificate for this Order. This field will be populated after the order has been successfully finalized with the ACME server, and the order has transitioned to the 'valid' state. - type: string - format: byte - failureTime: - description: FailureTime stores the time that this order failed. This is used to influence garbage collection and back-off. - type: string - format: date-time - finalizeURL: - description: FinalizeURL of the Order. This is used to obtain certificates for this order once it has been completed. - type: string - reason: - description: Reason optionally provides more information about a why the order is in the current state. - type: string - state: - description: State contains the current state of this Order resource. States 'success' and 'expired' are 'final' - type: string - enum: - - valid - - ready - - pending - - processing - - invalid - - expired - - errored - url: - description: URL of the Order. This will initially be empty when the resource is first created. The Order controller will populate this field when the Order is first processed. This field will be immutable after it is initially set. - type: string - served: true - storage: true ---- -# Source: cert-manager/templates/cainjector-serviceaccount.yaml -apiVersion: v1 -kind: ServiceAccount -automountServiceAccountToken: true -metadata: - name: cert-manager-cainjector - namespace: cert-manager - labels: - app: cainjector - app.kubernetes.io/name: cainjector - app.kubernetes.io/instance: cert-manager - app.kubernetes.io/component: "cainjector" - app.kubernetes.io/version: "v1.14.7" ---- -# Source: cert-manager/templates/serviceaccount.yaml -apiVersion: v1 -kind: ServiceAccount -automountServiceAccountToken: true -metadata: - name: cert-manager - namespace: cert-manager - labels: - app: cert-manager - app.kubernetes.io/name: cert-manager - app.kubernetes.io/instance: cert-manager - app.kubernetes.io/component: "controller" - app.kubernetes.io/version: "v1.14.7" ---- -# Source: cert-manager/templates/webhook-serviceaccount.yaml -apiVersion: v1 -kind: ServiceAccount -automountServiceAccountToken: true -metadata: - name: cert-manager-webhook - namespace: cert-manager - labels: - app: webhook - app.kubernetes.io/name: webhook - app.kubernetes.io/instance: cert-manager - app.kubernetes.io/component: "webhook" - app.kubernetes.io/version: "v1.14.7" ---- -# Source: cert-manager/templates/cainjector-rbac.yaml -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - name: cert-manager-cainjector - labels: - app: cainjector - app.kubernetes.io/name: cainjector - app.kubernetes.io/instance: cert-manager - app.kubernetes.io/component: "cainjector" - app.kubernetes.io/version: "v1.14.7" -rules: - - apiGroups: ["cert-manager.io"] - resources: ["certificates"] - verbs: ["get", "list", "watch"] - - apiGroups: [""] - resources: ["secrets"] - verbs: ["get", "list", "watch"] - - apiGroups: [""] - resources: ["events"] - verbs: ["get", "create", "update", "patch"] - - apiGroups: ["admissionregistration.k8s.io"] - resources: ["validatingwebhookconfigurations", "mutatingwebhookconfigurations"] - verbs: ["get", "list", "watch", "update", "patch"] - - apiGroups: ["apiregistration.k8s.io"] - resources: ["apiservices"] - verbs: ["get", "list", "watch", "update", "patch"] - - apiGroups: ["apiextensions.k8s.io"] - resources: ["customresourcedefinitions"] - verbs: ["get", "list", "watch", "update", "patch"] ---- -# Source: cert-manager/templates/rbac.yaml -# Issuer controller role -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - name: cert-manager-controller-issuers - labels: - app: cert-manager - app.kubernetes.io/name: cert-manager - app.kubernetes.io/instance: cert-manager - app.kubernetes.io/component: "controller" - app.kubernetes.io/version: "v1.14.7" -rules: - - apiGroups: ["cert-manager.io"] - resources: ["issuers", "issuers/status"] - verbs: ["update", "patch"] - - apiGroups: ["cert-manager.io"] - resources: ["issuers"] - verbs: ["get", "list", "watch"] - - apiGroups: [""] - resources: ["secrets"] - verbs: ["get", "list", "watch", "create", "update", "delete"] - - apiGroups: [""] - resources: ["events"] - verbs: ["create", "patch"] ---- -# Source: cert-manager/templates/rbac.yaml -# ClusterIssuer controller role -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - name: cert-manager-controller-clusterissuers - labels: - app: cert-manager - app.kubernetes.io/name: cert-manager - app.kubernetes.io/instance: cert-manager - app.kubernetes.io/component: "controller" - app.kubernetes.io/version: "v1.14.7" -rules: - - apiGroups: ["cert-manager.io"] - resources: ["clusterissuers", "clusterissuers/status"] - verbs: ["update", "patch"] - - apiGroups: ["cert-manager.io"] - resources: ["clusterissuers"] - verbs: ["get", "list", "watch"] - - apiGroups: [""] - resources: ["secrets"] - verbs: ["get", "list", "watch", "create", "update", "delete"] - - apiGroups: [""] - resources: ["events"] - verbs: ["create", "patch"] ---- -# Source: cert-manager/templates/rbac.yaml -# Certificates controller role -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - name: cert-manager-controller-certificates - labels: - app: cert-manager - app.kubernetes.io/name: cert-manager - app.kubernetes.io/instance: cert-manager - app.kubernetes.io/component: "controller" - app.kubernetes.io/version: "v1.14.7" -rules: - - apiGroups: ["cert-manager.io"] - resources: ["certificates", "certificates/status", "certificaterequests", "certificaterequests/status"] - verbs: ["update", "patch"] - - apiGroups: ["cert-manager.io"] - resources: ["certificates", "certificaterequests", "clusterissuers", "issuers"] - verbs: ["get", "list", "watch"] - # We require these rules to support users with the OwnerReferencesPermissionEnforcement - # admission controller enabled: - # https://kubernetes.io/docs/reference/access-authn-authz/admission-controllers/#ownerreferencespermissionenforcement - - apiGroups: ["cert-manager.io"] - resources: ["certificates/finalizers", "certificaterequests/finalizers"] - verbs: ["update"] - - apiGroups: ["acme.cert-manager.io"] - resources: ["orders"] - verbs: ["create", "delete", "get", "list", "watch"] - - apiGroups: [""] - resources: ["secrets"] - verbs: ["get", "list", "watch", "create", "update", "delete", "patch"] - - apiGroups: [""] - resources: ["events"] - verbs: ["create", "patch"] ---- -# Source: cert-manager/templates/rbac.yaml -# Orders controller role -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - name: cert-manager-controller-orders - labels: - app: cert-manager - app.kubernetes.io/name: cert-manager - app.kubernetes.io/instance: cert-manager - app.kubernetes.io/component: "controller" - app.kubernetes.io/version: "v1.14.7" -rules: - - apiGroups: ["acme.cert-manager.io"] - resources: ["orders", "orders/status"] - verbs: ["update", "patch"] - - apiGroups: ["acme.cert-manager.io"] - resources: ["orders", "challenges"] - verbs: ["get", "list", "watch"] - - apiGroups: ["cert-manager.io"] - resources: ["clusterissuers", "issuers"] - verbs: ["get", "list", "watch"] - - apiGroups: ["acme.cert-manager.io"] - resources: ["challenges"] - verbs: ["create", "delete"] - # We require these rules to support users with the OwnerReferencesPermissionEnforcement - # admission controller enabled: - # https://kubernetes.io/docs/reference/access-authn-authz/admission-controllers/#ownerreferencespermissionenforcement - - apiGroups: ["acme.cert-manager.io"] - resources: ["orders/finalizers"] - verbs: ["update"] - - apiGroups: [""] - resources: ["secrets"] - verbs: ["get", "list", "watch"] - - apiGroups: [""] - resources: ["events"] - verbs: ["create", "patch"] ---- -# Source: cert-manager/templates/rbac.yaml -# Challenges controller role -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - name: cert-manager-controller-challenges - labels: - app: cert-manager - app.kubernetes.io/name: cert-manager - app.kubernetes.io/instance: cert-manager - app.kubernetes.io/component: "controller" - app.kubernetes.io/version: "v1.14.7" -rules: - # Use to update challenge resource status - - apiGroups: ["acme.cert-manager.io"] - resources: ["challenges", "challenges/status"] - verbs: ["update", "patch"] - # Used to watch challenge resources - - apiGroups: ["acme.cert-manager.io"] - resources: ["challenges"] - verbs: ["get", "list", "watch"] - # Used to watch challenges, issuer and clusterissuer resources - - apiGroups: ["cert-manager.io"] - resources: ["issuers", "clusterissuers"] - verbs: ["get", "list", "watch"] - # Need to be able to retrieve ACME account private key to complete challenges - - apiGroups: [""] - resources: ["secrets"] - verbs: ["get", "list", "watch"] - # Used to create events - - apiGroups: [""] - resources: ["events"] - verbs: ["create", "patch"] - # HTTP01 rules - - apiGroups: [""] - resources: ["pods", "services"] - verbs: ["get", "list", "watch", "create", "delete"] - - apiGroups: ["networking.k8s.io"] - resources: ["ingresses"] - verbs: ["get", "list", "watch", "create", "delete", "update"] - - apiGroups: [ "gateway.networking.k8s.io" ] - resources: [ "httproutes" ] - verbs: ["get", "list", "watch", "create", "delete", "update"] - # We require the ability to specify a custom hostname when we are creating - # new ingress resources. - # See: https://github.com/openshift/origin/blob/21f191775636f9acadb44fa42beeb4f75b255532/pkg/route/apiserver/admission/ingress_admission.go#L84-L148 - - apiGroups: ["route.openshift.io"] - resources: ["routes/custom-host"] - verbs: ["create"] - # We require these rules to support users with the OwnerReferencesPermissionEnforcement - # admission controller enabled: - # https://kubernetes.io/docs/reference/access-authn-authz/admission-controllers/#ownerreferencespermissionenforcement - - apiGroups: ["acme.cert-manager.io"] - resources: ["challenges/finalizers"] - verbs: ["update"] - # DNS01 rules (duplicated above) - - apiGroups: [""] - resources: ["secrets"] - verbs: ["get", "list", "watch"] ---- -# Source: cert-manager/templates/rbac.yaml -# ingress-shim controller role -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - name: cert-manager-controller-ingress-shim - labels: - app: cert-manager - app.kubernetes.io/name: cert-manager - app.kubernetes.io/instance: cert-manager - app.kubernetes.io/component: "controller" - app.kubernetes.io/version: "v1.14.7" -rules: - - apiGroups: ["cert-manager.io"] - resources: ["certificates", "certificaterequests"] - verbs: ["create", "update", "delete"] - - apiGroups: ["cert-manager.io"] - resources: ["certificates", "certificaterequests", "issuers", "clusterissuers"] - verbs: ["get", "list", "watch"] - - apiGroups: ["networking.k8s.io"] - resources: ["ingresses"] - verbs: ["get", "list", "watch"] - # We require these rules to support users with the OwnerReferencesPermissionEnforcement - # admission controller enabled: - # https://kubernetes.io/docs/reference/access-authn-authz/admission-controllers/#ownerreferencespermissionenforcement - - apiGroups: ["networking.k8s.io"] - resources: ["ingresses/finalizers"] - verbs: ["update"] - - apiGroups: ["gateway.networking.k8s.io"] - resources: ["gateways", "httproutes"] - verbs: ["get", "list", "watch"] - - apiGroups: ["gateway.networking.k8s.io"] - resources: ["gateways/finalizers", "httproutes/finalizers"] - verbs: ["update"] - - apiGroups: [""] - resources: ["events"] - verbs: ["create", "patch"] ---- -# Source: cert-manager/templates/rbac.yaml -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - name: cert-manager-cluster-view - labels: - app: cert-manager - app.kubernetes.io/name: cert-manager - app.kubernetes.io/instance: cert-manager - app.kubernetes.io/component: "controller" - app.kubernetes.io/version: "v1.14.7" - rbac.authorization.k8s.io/aggregate-to-cluster-reader: "true" -rules: - - apiGroups: ["cert-manager.io"] - resources: ["clusterissuers"] - verbs: ["get", "list", "watch"] ---- -# Source: cert-manager/templates/rbac.yaml -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - name: cert-manager-view - labels: - app: cert-manager - app.kubernetes.io/name: cert-manager - app.kubernetes.io/instance: cert-manager - app.kubernetes.io/component: "controller" - app.kubernetes.io/version: "v1.14.7" - rbac.authorization.k8s.io/aggregate-to-view: "true" - rbac.authorization.k8s.io/aggregate-to-edit: "true" - rbac.authorization.k8s.io/aggregate-to-admin: "true" - rbac.authorization.k8s.io/aggregate-to-cluster-reader: "true" -rules: - - apiGroups: ["cert-manager.io"] - resources: ["certificates", "certificaterequests", "issuers"] - verbs: ["get", "list", "watch"] - - apiGroups: ["acme.cert-manager.io"] - resources: ["challenges", "orders"] - verbs: ["get", "list", "watch"] ---- -# Source: cert-manager/templates/rbac.yaml -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - name: cert-manager-edit - labels: - app: cert-manager - app.kubernetes.io/name: cert-manager - app.kubernetes.io/instance: cert-manager - app.kubernetes.io/component: "controller" - app.kubernetes.io/version: "v1.14.7" - rbac.authorization.k8s.io/aggregate-to-edit: "true" - rbac.authorization.k8s.io/aggregate-to-admin: "true" -rules: - - apiGroups: ["cert-manager.io"] - resources: ["certificates", "certificaterequests", "issuers"] - verbs: ["create", "delete", "deletecollection", "patch", "update"] - - apiGroups: ["cert-manager.io"] - resources: ["certificates/status"] - verbs: ["update"] - - apiGroups: ["acme.cert-manager.io"] - resources: ["challenges", "orders"] - verbs: ["create", "delete", "deletecollection", "patch", "update"] ---- -# Source: cert-manager/templates/rbac.yaml -# Permission to approve CertificateRequests referencing cert-manager.io Issuers and ClusterIssuers -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - name: cert-manager-controller-approve:cert-manager-io - labels: - app: cert-manager - app.kubernetes.io/name: cert-manager - app.kubernetes.io/instance: cert-manager - app.kubernetes.io/component: "cert-manager" - app.kubernetes.io/version: "v1.14.7" -rules: - - apiGroups: ["cert-manager.io"] - resources: ["signers"] - verbs: ["approve"] - resourceNames: ["issuers.cert-manager.io/*", "clusterissuers.cert-manager.io/*"] ---- -# Source: cert-manager/templates/rbac.yaml -# Permission to: -# - Update and sign CertificatSigningeRequests referencing cert-manager.io Issuers and ClusterIssuers -# - Perform SubjectAccessReviews to test whether users are able to reference Namespaced Issuers -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - name: cert-manager-controller-certificatesigningrequests - labels: - app: cert-manager - app.kubernetes.io/name: cert-manager - app.kubernetes.io/instance: cert-manager - app.kubernetes.io/component: "cert-manager" - app.kubernetes.io/version: "v1.14.7" -rules: - - apiGroups: ["certificates.k8s.io"] - resources: ["certificatesigningrequests"] - verbs: ["get", "list", "watch", "update"] - - apiGroups: ["certificates.k8s.io"] - resources: ["certificatesigningrequests/status"] - verbs: ["update", "patch"] - - apiGroups: ["certificates.k8s.io"] - resources: ["signers"] - resourceNames: ["issuers.cert-manager.io/*", "clusterissuers.cert-manager.io/*"] - verbs: ["sign"] - - apiGroups: ["authorization.k8s.io"] - resources: ["subjectaccessreviews"] - verbs: ["create"] ---- -# Source: cert-manager/templates/webhook-rbac.yaml -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - name: cert-manager-webhook:subjectaccessreviews - labels: - app: webhook - app.kubernetes.io/name: webhook - app.kubernetes.io/instance: cert-manager - app.kubernetes.io/component: "webhook" - app.kubernetes.io/version: "v1.14.7" -rules: -- apiGroups: ["authorization.k8s.io"] - resources: ["subjectaccessreviews"] - verbs: ["create"] ---- -# Source: cert-manager/templates/cainjector-rbac.yaml -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRoleBinding -metadata: - name: cert-manager-cainjector - labels: - app: cainjector - app.kubernetes.io/name: cainjector - app.kubernetes.io/instance: cert-manager - app.kubernetes.io/component: "cainjector" - app.kubernetes.io/version: "v1.14.7" -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: ClusterRole - name: cert-manager-cainjector -subjects: - - name: cert-manager-cainjector - namespace: cert-manager - kind: ServiceAccount ---- -# Source: cert-manager/templates/rbac.yaml -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRoleBinding -metadata: - name: cert-manager-controller-issuers - labels: - app: cert-manager - app.kubernetes.io/name: cert-manager - app.kubernetes.io/instance: cert-manager - app.kubernetes.io/component: "controller" - app.kubernetes.io/version: "v1.14.7" -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: ClusterRole - name: cert-manager-controller-issuers -subjects: - - name: cert-manager - namespace: cert-manager - kind: ServiceAccount ---- -# Source: cert-manager/templates/rbac.yaml -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRoleBinding -metadata: - name: cert-manager-controller-clusterissuers - labels: - app: cert-manager - app.kubernetes.io/name: cert-manager - app.kubernetes.io/instance: cert-manager - app.kubernetes.io/component: "controller" - app.kubernetes.io/version: "v1.14.7" -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: ClusterRole - name: cert-manager-controller-clusterissuers -subjects: - - name: cert-manager - namespace: cert-manager - kind: ServiceAccount ---- -# Source: cert-manager/templates/rbac.yaml -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRoleBinding -metadata: - name: cert-manager-controller-certificates - labels: - app: cert-manager - app.kubernetes.io/name: cert-manager - app.kubernetes.io/instance: cert-manager - app.kubernetes.io/component: "controller" - app.kubernetes.io/version: "v1.14.7" -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: ClusterRole - name: cert-manager-controller-certificates -subjects: - - name: cert-manager - namespace: cert-manager - kind: ServiceAccount ---- -# Source: cert-manager/templates/rbac.yaml -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRoleBinding -metadata: - name: cert-manager-controller-orders - labels: - app: cert-manager - app.kubernetes.io/name: cert-manager - app.kubernetes.io/instance: cert-manager - app.kubernetes.io/component: "controller" - app.kubernetes.io/version: "v1.14.7" -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: ClusterRole - name: cert-manager-controller-orders -subjects: - - name: cert-manager - namespace: cert-manager - kind: ServiceAccount ---- -# Source: cert-manager/templates/rbac.yaml -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRoleBinding -metadata: - name: cert-manager-controller-challenges - labels: - app: cert-manager - app.kubernetes.io/name: cert-manager - app.kubernetes.io/instance: cert-manager - app.kubernetes.io/component: "controller" - app.kubernetes.io/version: "v1.14.7" -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: ClusterRole - name: cert-manager-controller-challenges -subjects: - - name: cert-manager - namespace: cert-manager - kind: ServiceAccount ---- -# Source: cert-manager/templates/rbac.yaml -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRoleBinding -metadata: - name: cert-manager-controller-ingress-shim - labels: - app: cert-manager - app.kubernetes.io/name: cert-manager - app.kubernetes.io/instance: cert-manager - app.kubernetes.io/component: "controller" - app.kubernetes.io/version: "v1.14.7" -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: ClusterRole - name: cert-manager-controller-ingress-shim -subjects: - - name: cert-manager - namespace: cert-manager - kind: ServiceAccount ---- -# Source: cert-manager/templates/rbac.yaml -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRoleBinding -metadata: - name: cert-manager-controller-approve:cert-manager-io - labels: - app: cert-manager - app.kubernetes.io/name: cert-manager - app.kubernetes.io/instance: cert-manager - app.kubernetes.io/component: "cert-manager" - app.kubernetes.io/version: "v1.14.7" -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: ClusterRole - name: cert-manager-controller-approve:cert-manager-io -subjects: - - name: cert-manager - namespace: cert-manager - kind: ServiceAccount ---- -# Source: cert-manager/templates/rbac.yaml -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRoleBinding -metadata: - name: cert-manager-controller-certificatesigningrequests - labels: - app: cert-manager - app.kubernetes.io/name: cert-manager - app.kubernetes.io/instance: cert-manager - app.kubernetes.io/component: "cert-manager" - app.kubernetes.io/version: "v1.14.7" -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: ClusterRole - name: cert-manager-controller-certificatesigningrequests -subjects: - - name: cert-manager - namespace: cert-manager - kind: ServiceAccount ---- -# Source: cert-manager/templates/webhook-rbac.yaml -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRoleBinding -metadata: - name: cert-manager-webhook:subjectaccessreviews - labels: - app: webhook - app.kubernetes.io/name: webhook - app.kubernetes.io/instance: cert-manager - app.kubernetes.io/component: "webhook" - app.kubernetes.io/version: "v1.14.7" -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: ClusterRole - name: cert-manager-webhook:subjectaccessreviews -subjects: -- apiGroup: "" - kind: ServiceAccount - name: cert-manager-webhook - namespace: cert-manager ---- -# Source: cert-manager/templates/cainjector-rbac.yaml -# leader election rules -apiVersion: rbac.authorization.k8s.io/v1 -kind: Role -metadata: - name: cert-manager-cainjector:leaderelection - namespace: kube-system - labels: - app: cainjector - app.kubernetes.io/name: cainjector - app.kubernetes.io/instance: cert-manager - app.kubernetes.io/component: "cainjector" - app.kubernetes.io/version: "v1.14.7" -rules: - # Used for leader election by the controller - # cert-manager-cainjector-leader-election is used by the CertificateBased injector controller - # see cmd/cainjector/start.go#L113 - # cert-manager-cainjector-leader-election-core is used by the SecretBased injector controller - # see cmd/cainjector/start.go#L137 - - apiGroups: ["coordination.k8s.io"] - resources: ["leases"] - resourceNames: ["cert-manager-cainjector-leader-election", "cert-manager-cainjector-leader-election-core"] - verbs: ["get", "update", "patch"] - - apiGroups: ["coordination.k8s.io"] - resources: ["leases"] - verbs: ["create"] ---- -# Source: cert-manager/templates/rbac.yaml -apiVersion: rbac.authorization.k8s.io/v1 -kind: Role -metadata: - name: cert-manager:leaderelection - namespace: kube-system - labels: - app: cert-manager - app.kubernetes.io/name: cert-manager - app.kubernetes.io/instance: cert-manager - app.kubernetes.io/component: "controller" - app.kubernetes.io/version: "v1.14.7" -rules: - - apiGroups: ["coordination.k8s.io"] - resources: ["leases"] - resourceNames: ["cert-manager-controller"] - verbs: ["get", "update", "patch"] - - apiGroups: ["coordination.k8s.io"] - resources: ["leases"] - verbs: ["create"] ---- -# Source: cert-manager/templates/webhook-rbac.yaml -apiVersion: rbac.authorization.k8s.io/v1 -kind: Role -metadata: - name: cert-manager-webhook:dynamic-serving - namespace: cert-manager - labels: - app: webhook - app.kubernetes.io/name: webhook - app.kubernetes.io/instance: cert-manager - app.kubernetes.io/component: "webhook" - app.kubernetes.io/version: "v1.14.7" -rules: -- apiGroups: [""] - resources: ["secrets"] - resourceNames: - - 'cert-manager-webhook-ca' - verbs: ["get", "list", "watch", "update"] -# It's not possible to grant CREATE permission on a single resourceName. -- apiGroups: [""] - resources: ["secrets"] - verbs: ["create"] ---- -# Source: cert-manager/templates/cainjector-rbac.yaml -# grant cert-manager permission to manage the leaderelection configmap in the -# leader election namespace -apiVersion: rbac.authorization.k8s.io/v1 -kind: RoleBinding -metadata: - name: cert-manager-cainjector:leaderelection - namespace: kube-system - labels: - app: cainjector - app.kubernetes.io/name: cainjector - app.kubernetes.io/instance: cert-manager - app.kubernetes.io/component: "cainjector" - app.kubernetes.io/version: "v1.14.7" -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: Role - name: cert-manager-cainjector:leaderelection -subjects: - - kind: ServiceAccount - name: cert-manager-cainjector - namespace: cert-manager ---- -# Source: cert-manager/templates/rbac.yaml -# grant cert-manager permission to manage the leaderelection configmap in the -# leader election namespace -apiVersion: rbac.authorization.k8s.io/v1 -kind: RoleBinding -metadata: - name: cert-manager:leaderelection - namespace: kube-system - labels: - app: cert-manager - app.kubernetes.io/name: cert-manager - app.kubernetes.io/instance: cert-manager - app.kubernetes.io/component: "controller" - app.kubernetes.io/version: "v1.14.7" -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: Role - name: cert-manager:leaderelection -subjects: - - apiGroup: "" - kind: ServiceAccount - name: cert-manager - namespace: cert-manager ---- -# Source: cert-manager/templates/webhook-rbac.yaml -apiVersion: rbac.authorization.k8s.io/v1 -kind: RoleBinding -metadata: - name: cert-manager-webhook:dynamic-serving - namespace: cert-manager - labels: - app: webhook - app.kubernetes.io/name: webhook - app.kubernetes.io/instance: cert-manager - app.kubernetes.io/component: "webhook" - app.kubernetes.io/version: "v1.14.7" -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: Role - name: cert-manager-webhook:dynamic-serving -subjects: -- apiGroup: "" - kind: ServiceAccount - name: cert-manager-webhook - namespace: cert-manager ---- -# Source: cert-manager/templates/service.yaml -apiVersion: v1 -kind: Service -metadata: - name: cert-manager - namespace: cert-manager - labels: - app: cert-manager - app.kubernetes.io/name: cert-manager - app.kubernetes.io/instance: cert-manager - app.kubernetes.io/component: "controller" - app.kubernetes.io/version: "v1.14.7" -spec: - type: ClusterIP - ports: - - protocol: TCP - port: 9402 - name: tcp-prometheus-servicemonitor - targetPort: 9402 - selector: - app.kubernetes.io/name: cert-manager - app.kubernetes.io/instance: cert-manager - app.kubernetes.io/component: "controller" ---- -# Source: cert-manager/templates/webhook-service.yaml -apiVersion: v1 -kind: Service -metadata: - name: cert-manager-webhook - namespace: cert-manager - labels: - app: webhook - app.kubernetes.io/name: webhook - app.kubernetes.io/instance: cert-manager - app.kubernetes.io/component: "webhook" - app.kubernetes.io/version: "v1.14.7" -spec: - type: ClusterIP - ports: - - name: https - port: 443 - protocol: TCP - targetPort: "https" - selector: - app.kubernetes.io/name: webhook - app.kubernetes.io/instance: cert-manager - app.kubernetes.io/component: "webhook" ---- -# Source: cert-manager/templates/cainjector-deployment.yaml -apiVersion: apps/v1 -kind: Deployment -metadata: - name: cert-manager-cainjector - namespace: cert-manager - labels: - app: cainjector - app.kubernetes.io/name: cainjector - app.kubernetes.io/instance: cert-manager - app.kubernetes.io/component: "cainjector" - app.kubernetes.io/version: "v1.14.7" -spec: - replicas: 1 - selector: - matchLabels: - app.kubernetes.io/name: cainjector - app.kubernetes.io/instance: cert-manager - app.kubernetes.io/component: "cainjector" - template: - metadata: - labels: - app: cainjector - app.kubernetes.io/name: cainjector - app.kubernetes.io/instance: cert-manager - app.kubernetes.io/component: "cainjector" - app.kubernetes.io/version: "v1.14.7" - spec: - serviceAccountName: cert-manager-cainjector - enableServiceLinks: false - securityContext: - runAsNonRoot: true - seccompProfile: - type: RuntimeDefault - containers: - - name: cert-manager-cainjector - image: "quay.io/jetstack/cert-manager-cainjector:v1.14.7" - imagePullPolicy: IfNotPresent - args: - - --v=2 - - --leader-election-namespace=kube-system - env: - - name: POD_NAMESPACE - valueFrom: - fieldRef: - fieldPath: metadata.namespace - securityContext: - allowPrivilegeEscalation: false - capabilities: - drop: - - ALL - readOnlyRootFilesystem: true - nodeSelector: - kubernetes.io/os: linux ---- -# Source: cert-manager/templates/deployment.yaml -apiVersion: apps/v1 -kind: Deployment -metadata: - name: cert-manager - namespace: cert-manager - labels: - app: cert-manager - app.kubernetes.io/name: cert-manager - app.kubernetes.io/instance: cert-manager - app.kubernetes.io/component: "controller" - app.kubernetes.io/version: "v1.14.7" -spec: - replicas: 1 - selector: - matchLabels: - app.kubernetes.io/name: cert-manager - app.kubernetes.io/instance: cert-manager - app.kubernetes.io/component: "controller" - template: - metadata: - labels: - app: cert-manager - app.kubernetes.io/name: cert-manager - app.kubernetes.io/instance: cert-manager - app.kubernetes.io/component: "controller" - app.kubernetes.io/version: "v1.14.7" - annotations: - prometheus.io/path: "/metrics" - prometheus.io/scrape: 'true' - prometheus.io/port: '9402' - spec: - serviceAccountName: cert-manager - enableServiceLinks: false - securityContext: - runAsNonRoot: true - seccompProfile: - type: RuntimeDefault - containers: - - name: cert-manager-controller - image: "quay.io/jetstack/cert-manager-controller:v1.14.7" - imagePullPolicy: IfNotPresent - args: - - --v=2 - - --cluster-resource-namespace=$(POD_NAMESPACE) - - --leader-election-namespace=kube-system - - --acme-http01-solver-image=quay.io/jetstack/cert-manager-acmesolver:v1.14.7 - - --max-concurrent-challenges=60 - ports: - - containerPort: 9402 - name: http-metrics - protocol: TCP - - containerPort: 9403 - name: http-healthz - protocol: TCP - securityContext: - allowPrivilegeEscalation: false - capabilities: - drop: - - ALL - readOnlyRootFilesystem: true - env: - - name: POD_NAMESPACE - valueFrom: - fieldRef: - fieldPath: metadata.namespace - # LivenessProbe settings are based on those used for the Kubernetes - # controller-manager. See: - # https://github.com/kubernetes/kubernetes/blob/806b30170c61a38fedd54cc9ede4cd6275a1ad3b/cmd/kubeadm/app/util/staticpod/utils.go#L241-L245 - livenessProbe: - httpGet: - port: http-healthz - path: /livez - scheme: HTTP - initialDelaySeconds: 10 - periodSeconds: 10 - timeoutSeconds: 15 - successThreshold: 1 - failureThreshold: 8 - nodeSelector: - kubernetes.io/os: linux ---- -# Source: cert-manager/templates/webhook-deployment.yaml -apiVersion: apps/v1 -kind: Deployment -metadata: - name: cert-manager-webhook - namespace: cert-manager - labels: - app: webhook - app.kubernetes.io/name: webhook - app.kubernetes.io/instance: cert-manager - app.kubernetes.io/component: "webhook" - app.kubernetes.io/version: "v1.14.7" -spec: - replicas: 1 - selector: - matchLabels: - app.kubernetes.io/name: webhook - app.kubernetes.io/instance: cert-manager - app.kubernetes.io/component: "webhook" - template: - metadata: - labels: - app: webhook - app.kubernetes.io/name: webhook - app.kubernetes.io/instance: cert-manager - app.kubernetes.io/component: "webhook" - app.kubernetes.io/version: "v1.14.7" - spec: - serviceAccountName: cert-manager-webhook - enableServiceLinks: false - securityContext: - runAsNonRoot: true - seccompProfile: - type: RuntimeDefault - containers: - - name: cert-manager-webhook - image: "quay.io/jetstack/cert-manager-webhook:v1.14.7" - imagePullPolicy: IfNotPresent - args: - - --v=2 - - --secure-port=10250 - - --dynamic-serving-ca-secret-namespace=$(POD_NAMESPACE) - - --dynamic-serving-ca-secret-name=cert-manager-webhook-ca - - --dynamic-serving-dns-names=cert-manager-webhook - - --dynamic-serving-dns-names=cert-manager-webhook.$(POD_NAMESPACE) - - --dynamic-serving-dns-names=cert-manager-webhook.$(POD_NAMESPACE).svc - - ports: - - name: https - protocol: TCP - containerPort: 10250 - - name: healthcheck - protocol: TCP - containerPort: 6080 - livenessProbe: - httpGet: - path: /livez - port: 6080 - scheme: HTTP - initialDelaySeconds: 60 - periodSeconds: 10 - timeoutSeconds: 1 - successThreshold: 1 - failureThreshold: 3 - readinessProbe: - httpGet: - path: /healthz - port: 6080 - scheme: HTTP - initialDelaySeconds: 5 - periodSeconds: 5 - timeoutSeconds: 1 - successThreshold: 1 - failureThreshold: 3 - securityContext: - allowPrivilegeEscalation: false - capabilities: - drop: - - ALL - readOnlyRootFilesystem: true - env: - - name: POD_NAMESPACE - valueFrom: - fieldRef: - fieldPath: metadata.namespace - nodeSelector: - kubernetes.io/os: linux ---- -# Source: cert-manager/templates/webhook-mutating-webhook.yaml -apiVersion: admissionregistration.k8s.io/v1 -kind: MutatingWebhookConfiguration -metadata: - name: cert-manager-webhook - labels: - app: webhook - app.kubernetes.io/name: webhook - app.kubernetes.io/instance: cert-manager - app.kubernetes.io/component: "webhook" - app.kubernetes.io/version: "v1.14.7" - annotations: - cert-manager.io/inject-ca-from-secret: "cert-manager/cert-manager-webhook-ca" -webhooks: - - name: webhook.cert-manager.io - rules: - - apiGroups: - - "cert-manager.io" - apiVersions: - - "v1" - operations: - - CREATE - resources: - - "certificaterequests" - admissionReviewVersions: ["v1"] - # This webhook only accepts v1 cert-manager resources. - # Equivalent matchPolicy ensures that non-v1 resource requests are sent to - # this webhook (after the resources have been converted to v1). - matchPolicy: Equivalent - timeoutSeconds: 30 - failurePolicy: Fail - # Only include 'sideEffects' field in Kubernetes 1.12+ - sideEffects: None - clientConfig: - service: - name: cert-manager-webhook - namespace: cert-manager - path: /mutate ---- -# Source: cert-manager/templates/webhook-validating-webhook.yaml -apiVersion: admissionregistration.k8s.io/v1 -kind: ValidatingWebhookConfiguration -metadata: - name: cert-manager-webhook - labels: - app: webhook - app.kubernetes.io/name: webhook - app.kubernetes.io/instance: cert-manager - app.kubernetes.io/component: "webhook" - app.kubernetes.io/version: "v1.14.7" - annotations: - cert-manager.io/inject-ca-from-secret: "cert-manager/cert-manager-webhook-ca" -webhooks: - - name: webhook.cert-manager.io - namespaceSelector: - matchExpressions: - - key: cert-manager.io/disable-validation - operator: NotIn - values: - - "true" - rules: - - apiGroups: - - "cert-manager.io" - - "acme.cert-manager.io" - apiVersions: - - "v1" - operations: - - CREATE - - UPDATE - resources: - - "*/*" - admissionReviewVersions: ["v1"] - # This webhook only accepts v1 cert-manager resources. - # Equivalent matchPolicy ensures that non-v1 resource requests are sent to - # this webhook (after the resources have been converted to v1). - matchPolicy: Equivalent - timeoutSeconds: 30 - failurePolicy: Fail - sideEffects: None - clientConfig: - service: - name: cert-manager-webhook - namespace: cert-manager - path: /validate diff --git a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/cert-manager/values-schema.yaml b/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/cert-manager/values-schema.yaml deleted file mode 100644 index 048e9b813..000000000 --- a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/cert-manager/values-schema.yaml +++ /dev/null @@ -1,13 +0,0 @@ -#@data/values-schema ---- -#@schema/desc "The namespace in which to deploy cert-manager" -namespace: cert-manager -#@schema/nullable -serviceaccount: - #@schema/desc "Annotations to set on the cert-manager service account. Annotations must be in annotation format, that is, map[string]string" - #@schema/type any=True - annotations: -#@schema/desc "The namespace to use for cluster resources, e.g. Issuer, ClusterIssuer, Certificate, etc. If not set, the namespace will be the same as the cert-manager namespace" -clusterResourceNamespace: cert-manager -#@schema/desc "The namespace to use for leader election. Some infra providers can not use the default kube-system" -leaderElectionNamespace: kube-system diff --git a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/certs/downstream/cluster-issuer.yaml b/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/certs/downstream/cluster-issuer.yaml deleted file mode 100644 index a3f53ca07..000000000 --- a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/certs/downstream/cluster-issuer.yaml +++ /dev/null @@ -1,8 +0,0 @@ ---- -apiVersion: cert-manager.io/v1 -kind: ClusterIssuer -metadata: - name: educateswildcard -spec: - selfSigned: {} -#! namespace: By default, a ClusterIssuer will create secrets in cert-manager namespace diff --git a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/certs/downstream/wildcard-cert.yaml b/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/certs/downstream/wildcard-cert.yaml deleted file mode 100644 index 421356a9b..000000000 --- a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/certs/downstream/wildcard-cert.yaml +++ /dev/null @@ -1,12 +0,0 @@ ---- -apiVersion: cert-manager.io/v1 -kind: Certificate -metadata: - name: educateswildcard -spec: - secretName: educateswildcard - issuerRef: - name: educateswildcard - kind: ClusterIssuer - dnsNames: - - REPLACE_ME diff --git a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/certs/overlays/functions.star b/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/certs/overlays/functions.star deleted file mode 100644 index a76b5920b..000000000 --- a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/certs/overlays/functions.star +++ /dev/null @@ -1,9 +0,0 @@ -load("@ytt:data", "data") - -def get_domains(): - domains = [] - for domain in data.values.domains: - domains.append("*.{}".format(domain)) - end - return domains -end \ No newline at end of file diff --git a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/certs/overlays/overlay-acme-aws.yaml b/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/certs/overlays/overlay-acme-aws.yaml deleted file mode 100644 index fd5553819..000000000 --- a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/certs/overlays/overlay-acme-aws.yaml +++ /dev/null @@ -1,66 +0,0 @@ -#@ load("@ytt:data", "data") -#@ load("@ytt:overlay", "overlay") -#@ load("@ytt:base64", "base64") -#@ load("@ytt:assert", "assert") -#@ load("functions.star", "get_domains") - -#@ if data.values.certProvider=="acme-aws": - -#@ (hasEmail, _) = assert.try_to(lambda: len(data.values.acme.email) > 0) -#@ (hasAwsCredsAccessKey, _) = assert.try_to(lambda: len(data.values.acme.aws.credentials.accessKey) > 0) -#@ (hasAwsCredsSecretKey, _) = assert.try_to(lambda: len(data.values.acme.aws.credentials.secretKey) > 0) -#@ if (hasAwsCredsSecretKey and not hasAwsCredsAccessKey) or (not hasAwsCredsSecretKey and hasAwsCredsAccessKey): -#@ assert.fail("`acme.aws.credentials.accessKey` and `acme.aws.credentials.secretKey` must both be provided") -#@ end - -#@ if hasAwsCredsAccessKey and hasAwsCredsSecretKey: ---- -apiVersion: v1 -kind: Secret -metadata: - name: cert-manager-aws-values - namespace: #@ data.values.certmanagerClusterResourceNamespace -type: Opaque -data: - awsAccessKeyID: #@ base64.encode("{}".format(data.values.acme.aws.credentials.accessKey)) - awsSecretAccessKey: #@ base64.encode("{}".format(data.values.acme.aws.credentials.secretKey)) -#@ end - -#@overlay/match by=overlay.subset({"kind":"ClusterIssuer", "metadata": {"name": "educateswildcard"}}) ---- -spec: - #@overlay/remove - selfSigned: - #@overlay/match missing_ok=True - acme: - #@ if/end hasEmail: - email: #@ data.values.acme.email - privateKeySecretRef: - name: educates-wildcard-acme - server: https://acme-v02.api.letsencrypt.org/directory - solvers: - #@overlay/match by=lambda i,l,r: "dns01" in l - - dns01: - route53: - region: #@ data.values.acme.aws.certs.region - #@ if hasAwsCredsAccessKey and hasAwsCredsSecretKey: - accessKeyID: #@ data.values.acme.aws.credentials.accessKey - secretAccessKeySecretRef: - name: cert-manager-aws-values - key: awsSecretAccessKey - #@ end - #@overlay/match by=lambda i,l,r: "http01" in l - - http01: - ingress: - class: #@ data.values.acme.ingressClass - -#@overlay/match by=overlay.subset({"kind":"Certificate", "metadata": {"name": "educateswildcard"}}) ---- -metadata: - #@overlay/match missing_ok=True - namespace: #@ data.values.wildcardCertificateNamespace -spec: - #@overlay/replace - dnsNames: #@ get_domains() - -#@ end diff --git a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/certs/overlays/overlay-acme-gcp.yaml b/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/certs/overlays/overlay-acme-gcp.yaml deleted file mode 100644 index a2774034d..000000000 --- a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/certs/overlays/overlay-acme-gcp.yaml +++ /dev/null @@ -1,46 +0,0 @@ -#@ load("@ytt:data", "data") -#@ load("@ytt:overlay", "overlay") -#@ load("@ytt:base64", "base64") -#@ load("@ytt:assert", "assert") -#@ load("functions.star", "get_domains") - -#@ if data.values.certProvider=="acme-gcp": - -#@ (hasEmail, _) = assert.try_to(lambda: len(data.values.acme.email) > 0) -#@ (hasProject, _) = assert.try_to(lambda: len(data.values.acme.gcp.project) > 0) -#@ if (not hasProject): -#@ assert.fail("`acme.gcp.project` must be provided") -#@ end - -#@overlay/match by=overlay.subset({"kind":"ClusterIssuer", "metadata": {"name": "educateswildcard"}}) ---- -spec: - #@overlay/remove - selfSigned: - #@overlay/match missing_ok=True - acme: - #@ if/end hasEmail: - email: #@ data.values.acme.email - privateKeySecretRef: - name: educates-wildcard-acme - server: https://acme-v02.api.letsencrypt.org/directory - solvers: - #@overlay/match by=lambda i,l,r: "dns01" in l - - dns01: - cloudDNS: - project: #@ data.values.acme.gcp.project - #@overlay/match by=lambda i,l,r: "http01" in l - - http01: - ingress: - class: #@ data.values.acme.ingressClass - -#@overlay/match by=overlay.subset({"kind":"Certificate", "metadata": {"name": "educateswildcard"}}) ---- -metadata: - #@overlay/match missing_ok=True - namespace: #@ data.values.wildcardCertificateNamespace -spec: - #@overlay/replace - dnsNames: #@ get_domains() - -#@ end diff --git a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/certs/overlays/overlay-localca.yaml b/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/certs/overlays/overlay-localca.yaml deleted file mode 100644 index 0550f020d..000000000 --- a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/certs/overlays/overlay-localca.yaml +++ /dev/null @@ -1,50 +0,0 @@ -#@ load("@ytt:data", "data") -#@ load("@ytt:overlay", "overlay") -#@ load("@ytt:base64", "base64") -#@ load("functions.star", "get_domains") - -#@ if data.values.certProvider=="local": - -#@ if hasattr(data.values.local, "caCertificate") and data.values.local.caCertificate: ---- -apiVersion: v1 -kind: Secret -metadata: - name: local-root-ca - namespace: #@ data.values.certmanagerClusterResourceNamespace -data: - ca.crt: #@ base64.encode(data.values.local.caCertificate["ca.crt"]) - tls.crt: #@ base64.encode(data.values.local.caCertificate["ca.key"]) - -#@overlay/match by=overlay.subset({"kind":"ClusterIssuer", "metadata": {"name": "educateswildcard"}}) ---- -spec: - #@overlay/remove - selfSigned: - #@overlay/match missing_ok=True - ca: - secretName: local-root-ca - -#@ elif hasattr(data.values.local, "caCertificateRef"): - -#@overlay/match by=overlay.subset({"kind":"ClusterIssuer", "metadata": {"name": "educateswildcard"}}) ---- -spec: - #@overlay/remove - selfSigned: - #@overlay/match missing_ok=True - ca: - secretName: #@ data.values.local.caCertificateRef.name - -#@ end - -#@overlay/match by=overlay.subset({"kind":"Certificate", "metadata": {"name": "educateswildcard"}}) ---- -metadata: - #@overlay/match missing_ok=True - namespace: #@ data.values.wildcardCertificateNamespace -spec: - #@overlay/replace - dnsNames: #@ get_domains() - -#@ end diff --git a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/certs/upstream/.gitkeep b/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/certs/upstream/.gitkeep deleted file mode 100644 index e69de29bb..000000000 diff --git a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/certs/values-schema.yaml b/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/certs/values-schema.yaml deleted file mode 100644 index 7961eebf6..000000000 --- a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/certs/values-schema.yaml +++ /dev/null @@ -1,64 +0,0 @@ -#@data/values-schema -#@schema/validation one_not_null=["acme", "local"] ---- -#! Namespace that cert-manager has configured for ClusterResources -#@schema/validation min_len=1 -certmanagerClusterResourceNamespace: cert-manager - -#@schema/validation min_len=1 -wildcardCertificateNamespace: projectcontour - -#@schema/validation min_len=1 -domains: - - "" - -#! The provider to use for certificate management -#! acme-aws: Use AWS Route53 for DNS01 challenge -#! acme-gcp: Use GCP CloudDNS for DNS01 challenge -#! local: Use a cert-manager generated ClusterIssuer with the provided root CA -#@schema/validation one_of=["acme-aws", "acme-gcp", "local"] -#@schema/desc "The provider to use for certificate management\nacme-aws: Use AWS Route53 for DNS01 challenge\nlocal: Use a locally generated root CA\nprovided: Use a provided wildcard certificate" -certProvider: "" #! One of acme-aws, acme-gcp, local - -#@schema/desc "ACME provider related configuration" -#@schema/nullable -acme: - #@schema/validation min_len=1 - ingressClass: contour - #@schema/desc "If you want to get notified by Let's encrypt of certificate expiration" - #@schema/nullable - email: "" - #! Aws credentials for IAM user with privileges to use cert-manager DNS01 (Leave empty if using AWS IAM IRSA) - #@schema/nullable - aws: - #@schema/nullable - credentials: - #@schema/desc "AWS access key. When provided along with the aws.secretKey, a Secret will be created and referenced in the external-dns Deployment." - accessKey: "" - #@schema/desc "AWS secret key. When provided along with the aws.accessKey, a Secret will be created and referenced in the external-dns Deployment." - secretKey: "" - #@schema/nullable - certs: - #@schema/desc "Region where the cluster is located" - #@schema/validation min_len=1 - region: "" - #@schema/nullable - gcp: - #@schema/validation min_len=1 - project: "" - -#@schema/nullable -#@schema/validation one_not_null=["caCertificate", "caCertificateRef"] -local: - #@schema/nullable - caCertificate: - #@schema/validation min_len=1 - ca.crt: "" - ca.key: "" - #@schema/nullable - caCertificateRef: - #@schema/validation min_len=1 - name: "" - #@schema/validation min_len=1 - #@schema/desc "The namespace in which the Secret containing the root CA is located. When this is provided will overwrite cert-manager's ns" - namespace: "" diff --git a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/contour/overlays/.gitkeep b/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/contour/overlays/.gitkeep deleted file mode 100644 index e69de29bb..000000000 diff --git a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/contour/overlays/contour.star b/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/contour/overlays/contour.star deleted file mode 100644 index 41523a749..000000000 --- a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/contour/overlays/contour.star +++ /dev/null @@ -1,14 +0,0 @@ -load("@ytt:data", "data") - -def should_add_externaldns_annotation(): - return hasattr(data.values, "externaldns") and hasattr(data.values.externaldns, "domains") -end - - -def external_dns_annotation(): - dns_domains = [] - for domain in data.values.externaldns.domains: - dns_domains.append("*.{}.".format(domain)) - end - return ",".join(dns_domains) -end \ No newline at end of file diff --git a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/contour/overlays/overlay-configure-externaldns.yaml b/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/contour/overlays/overlay-configure-externaldns.yaml deleted file mode 100644 index 3834f79d2..000000000 --- a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/contour/overlays/overlay-configure-externaldns.yaml +++ /dev/null @@ -1,11 +0,0 @@ -#@ load("@ytt:overlay", "overlay") -#@ load("@ytt:data", "data") -#@ load("contour.star", "should_add_externaldns_annotation", "external_dns_annotation") - -#@overlay/match by=overlay.subset({"kind":"Service", "metadata": {"name": "envoy"}}) ---- -metadata: - annotations: - #@ if/end should_add_externaldns_annotation(): - #@overlay/match missing_ok=True - external-dns.alpha.kubernetes.io/hostname: #@ external_dns_annotation() diff --git a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/contour/overlays/overlay-contour.yaml b/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/contour/overlays/overlay-contour.yaml deleted file mode 100644 index 3fc1ae194..000000000 --- a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/contour/overlays/overlay-contour.yaml +++ /dev/null @@ -1,41 +0,0 @@ -#@ load("@ytt:overlay", "overlay") -#@ load("@ytt:data", "data") -#@ load("@ytt:yaml", "yaml") -#@ load("/rules.star", "default_HTTP_Versions") - -#@ def contour_config(): -incluster: true -disablePermitInsecure: false -tls: - fallback-certificate: - name: fallback-secret-name - namespace: #@ data.values.namespace - envoy-client-certificate: -accesslog-format: envoy -default-http-versions: #@ data.values.configFileContents.defaultHttpVersions or default_HTTP_Versions() -#@ end - -#@ if/end hasattr(data.values, "contour") and data.values.contour != None: -#@overlay/match by=overlay.subset({"kind":"Deployment", "metadata": {"name": "contour"}}) ---- -spec: - replicas: #@ data.values.contour.replicas - -#@overlay/match by=overlay.subset({"kind":"ConfigMap", "metadata": {"name": "contour"}}) ---- -data: - contour.yaml: #@ yaml.encode(contour_config()) - -#@overlay/match by=overlay.subset({"kind":"CustomResourceDefinition"}),expects="2+" ---- -#@overlay/remove -#@overlay/match missing_ok=True -status: - -#@overlay/match by=overlay.subset({"kind":"Job"}),expects=1 ---- -metadata: - #@overlay/match missing_ok=True - annotations: - #@overlay/match missing_ok=True - kapp.k14s.io/update-strategy: "fallback-on-replace" diff --git a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/contour/overlays/overlay-infra-kind.yaml b/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/contour/overlays/overlay-infra-kind.yaml deleted file mode 100644 index fa5b316f6..000000000 --- a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/contour/overlays/overlay-infra-kind.yaml +++ /dev/null @@ -1,21 +0,0 @@ -#@ load("@ytt:data", "data") -#@ load("@ytt:overlay", "overlay") - -#@ if data.values.infraProvider == "kind": -#@overlay/match by=overlay.subset({"kind": "DaemonSet", "metadata": {"name": "envoy", "namespace": "projectcontour"}}) ---- -spec: - template: - spec: - #@overlay/match missing_ok=True - nodeSelector: - ingress-ready: "true" - #@overlay/match missing_ok=True - tolerations: - - key: node-role.kubernetes.io/control-plane - operator: Equal - effect: NoSchedule - - key: node-role.kubernetes.io/master - operator: Equal - effect: NoSchedule -#@ end diff --git a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/contour/overlays/overlay-job.yaml b/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/contour/overlays/overlay-job.yaml deleted file mode 100644 index c5afa5cd0..000000000 --- a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/contour/overlays/overlay-job.yaml +++ /dev/null @@ -1,29 +0,0 @@ -#@ load("@ytt:overlay", "overlay") -#@ load("@ytt:data", "data") - -#! TODO: When cert-manager is installed on the cluster, we can remove this job - -#@overlay/match by=overlay.subset({"kind":"Job"}),expects="0+" ---- -spec: - template: - spec: - containers: - #@overlay/match by="name" - - name: contour - env: - #@overlay/match by="name" - - name: CONTOUR_NAMESPACE - valueFrom: - fieldRef: - #@overlay/match missing_ok=True - apiVersion: v1 - fieldPath: metadata.namespace - -#@overlay/match by=overlay.subset({"kind":"Job"}),expects="0+" ---- -metadata: - #@overlay/match missing_ok=True - annotations: - #@overlay/match missing_ok=True - kapp.k14s.io/update-strategy: "fallback-on-replace" \ No newline at end of file diff --git a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/contour/overlays/overlay-ns.yaml b/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/contour/overlays/overlay-ns.yaml deleted file mode 100644 index 869824988..000000000 --- a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/contour/overlays/overlay-ns.yaml +++ /dev/null @@ -1,33 +0,0 @@ -#@ load("@ytt:data", "data") -#@ load("@ytt:overlay", "overlay") - -#@ if/end not data.values.createNamespace: -#@overlay/match by=overlay.subset({"kind":"Namespace", "metadata":{"name": "projectcontour"}}) -#@overlay/remove ---- -#@overlay/match by=overlay.subset({"kind":"Namespace", "metadata":{"name": "projectcontour"}}), expects=[0,1] ---- -apiVersion: v1 -kind: Namespace -metadata: - name: #@ data.values.namespace - -#@overlay/match by=overlay.subset({"metadata": {"namespace": "projectcontour"}}), expects="1+" ---- -metadata: - #@overlay/match missing_ok=True - namespace: #@ data.values.namespace - -#@overlay/match by=overlay.subset({"kind":"RoleBinding"}),expects=[1,2,3] ---- -subjects: - #@overlay/match by=overlay.all - - kind: ServiceAccount - namespace: #@ data.values.namespace - -#@overlay/match by=overlay.subset({"kind":"ClusterRoleBinding", "metadata": {"name": "contour"}}) ---- -subjects: - #@overlay/match by=overlay.all - - kind: ServiceAccount - namespace: #@ data.values.namespace diff --git a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/contour/overlays/overlay-remove-hostports.yaml b/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/contour/overlays/overlay-remove-hostports.yaml deleted file mode 100644 index e3bc462b3..000000000 --- a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/contour/overlays/overlay-remove-hostports.yaml +++ /dev/null @@ -1,22 +0,0 @@ -#@ load("@ytt:overlay", "overlay") -#@ load("@ytt:data", "data") - -#@ if data.values.service.useHostPorts == False: -#@overlay/match by=overlay.subset({"kind":"DaemonSet", "metadata": {"name": "envoy"}}) ---- -spec: - template: - spec: - containers: - #@overlay/match by=overlay.subset({"name": "envoy"}) - - name: envoy - ports: - #@overlay/match by=overlay.subset({"name": "http"}) - - name: http - #@overlay/remove - hostPort: 80 - #@overlay/match by=overlay.subset({"name": "https"}) - - name: https - #@overlay/remove - hostPort: 443 -#@ end diff --git a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/contour/overlays/overlay-service.yaml b/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/contour/overlays/overlay-service.yaml deleted file mode 100644 index 8ae0a7631..000000000 --- a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/contour/overlays/overlay-service.yaml +++ /dev/null @@ -1,10 +0,0 @@ -#@ load("@ytt:overlay", "overlay") -#@ load("@ytt:data", "data") - -#@overlay/match by=overlay.subset({"kind":"Service", "metadata": {"name": "envoy"}}) ---- -spec: - type: #@ data.values.service.type - #@ if/end data.values.service.type=="ClusterIP": - #@overlay/remove - externalTrafficPolicy: diff --git a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/contour/rules.star b/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/contour/rules.star deleted file mode 100644 index 13fb44173..000000000 --- a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/contour/rules.star +++ /dev/null @@ -1,27 +0,0 @@ -def check_infra(val): - if val["infraProvider"] in ["minikube"]: - return val["service"]["type"] in ["ClusterIP", "LoadBalancer"] or fail("{} infra provider requires service.type to be ClusterIP or LoadBalancer".format(val["infraProvider"])) - end - if val["infraProvider"] in ["aws", "gcp", "azure"]: - return val["service"]["type"] == "LoadBalancer" or fail("{} infra provider requires service.type to be LoadBalancer".format(val["infraProvider"])) - end - if val["infraProvider"] in ["kind"]: - return val["service"]["type"] == "ClusterIP" or fail("{} infra provider requires service.type to be ClusterIP".format(val["infraProvider"])) - end - return True -end - -def check_host_ports(val): - if val["infraProvider"] in ["kind", "aws", "gcp", "azure", "minikube"]: - return val["service"]["useHostPorts"] == True or fail("{} infra provider requires service.useHostPorts to be True".format(val["infraProvider"])) - end - return True -end - -def check_all(val): - return check_infra(val) and check_host_ports(val) -end - -def default_HTTP_Versions(): - return ["HTTP/1.1", "HTTP/2"] -end diff --git a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/contour/upstream/00-common.yaml b/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/contour/upstream/00-common.yaml deleted file mode 100644 index c037ee61b..000000000 --- a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/contour/upstream/00-common.yaml +++ /dev/null @@ -1,17 +0,0 @@ ---- -apiVersion: v1 -kind: Namespace -metadata: - name: projectcontour ---- -apiVersion: v1 -kind: ServiceAccount -metadata: - name: contour - namespace: projectcontour ---- -apiVersion: v1 -kind: ServiceAccount -metadata: - name: envoy - namespace: projectcontour diff --git a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/contour/upstream/01-contour-config.yaml b/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/contour/upstream/01-contour-config.yaml deleted file mode 100644 index 6eb7720b9..000000000 --- a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/contour/upstream/01-contour-config.yaml +++ /dev/null @@ -1,186 +0,0 @@ ---- -apiVersion: v1 -kind: ConfigMap -metadata: - name: contour - namespace: projectcontour -data: - contour.yaml: | - # - # server: - # determine which XDS Server implementation to utilize in Contour. - # xds-server-type: envoy - # - # Specify the Gateway API configuration. - # gateway: - # namespace: projectcontour - # name: contour - # - # should contour expect to be running inside a k8s cluster - # incluster: true - # - # path to kubeconfig (if not running inside a k8s cluster) - # kubeconfig: /path/to/.kube/config - # - # Disable RFC-compliant behavior to strip "Content-Length" header if - # "Tranfer-Encoding: chunked" is also set. - # disableAllowChunkedLength: false - # - # Disable Envoy's non-standard merge_slashes path transformation option - # that strips duplicate slashes from request URLs. - # disableMergeSlashes: false - # - # Disable HTTPProxy permitInsecure field - disablePermitInsecure: false - tls: - # minimum TLS version that Contour will negotiate - # minimum-protocol-version: "1.2" - # TLS ciphers to be supported by Envoy TLS listeners when negotiating - # TLS 1.2. - # cipher-suites: - # - '[ECDHE-ECDSA-AES128-GCM-SHA256|ECDHE-ECDSA-CHACHA20-POLY1305]' - # - '[ECDHE-RSA-AES128-GCM-SHA256|ECDHE-RSA-CHACHA20-POLY1305]' - # - 'ECDHE-ECDSA-AES256-GCM-SHA384' - # - 'ECDHE-RSA-AES256-GCM-SHA384' - # Defines the Kubernetes name/namespace matching a secret to use - # as the fallback certificate when requests which don't match the - # SNI defined for a vhost. - fallback-certificate: - # name: fallback-secret-name - # namespace: projectcontour - envoy-client-certificate: - # name: envoy-client-cert-secret-name - # namespace: projectcontour - #### - # ExternalName Services are disabled by default due to CVE-2021-XXXXX - # You can re-enable them by setting this setting to `true`. - # This is not recommended without understanding the security implications. - # Please see the advisory at https://github.com/projectcontour/contour/security/advisories/GHSA-5ph6-qq5x-7jwc for the details. - # enableExternalNameService: false - ## - # Address to be placed in status.loadbalancer field of Ingress objects. - # May be either a literal IP address or a host name. - # The value will be placed directly into the relevant field inside the status.loadBalancer struct. - # ingress-status-address: local.projectcontour.io - ### Logging options - # Default setting - accesslog-format: envoy - # The default access log format is defined by Envoy but it can be customized by setting following variable. - # accesslog-format-string: "...\n" - # To enable JSON logging in Envoy - # accesslog-format: json - # accesslog-level: info - # The default fields that will be logged are specified below. - # To customise this list, just add or remove entries. - # The canonical list is available at - # https://godoc.org/github.com/projectcontour/contour/internal/envoy#JSONFields - # json-fields: - # - "@timestamp" - # - "authority" - # - "bytes_received" - # - "bytes_sent" - # - "downstream_local_address" - # - "downstream_remote_address" - # - "duration" - # - "method" - # - "path" - # - "protocol" - # - "request_id" - # - "requested_server_name" - # - "response_code" - # - "response_flags" - # - "uber_trace_id" - # - "upstream_cluster" - # - "upstream_host" - # - "upstream_local_address" - # - "upstream_service_time" - # - "user_agent" - # - "x_forwarded_for" - # - "grpc_status" - # - "grpc_status_number" - # - # default-http-versions: - # - "HTTP/2" - # - "HTTP/1.1" - # - # The following shows the default proxy timeout settings. - # timeouts: - # request-timeout: infinity - # connection-idle-timeout: 60s - # stream-idle-timeout: 5m - # max-connection-duration: infinity - # delayed-close-timeout: 1s - # connection-shutdown-grace-period: 5s - # connect-timeout: 2s - # - # Envoy cluster settings. - # cluster: - # configure the cluster dns lookup family - # valid options are: auto (default), v4, v6 - # dns-lookup-family: auto - # - # Envoy network settings. - # network: - # Configure the number of additional ingress proxy hops from the - # right side of the x-forwarded-for HTTP header to trust. - # num-trusted-hops: 0 - # Configure the port used to access the Envoy Admin interface. - # admin-port: 9001 - # - # Configure an optional global rate limit service. - # rateLimitService: - # Identifies the extension service defining the rate limit service, - # formatted as /. - # extensionService: projectcontour/ratelimit - # Defines the rate limit domain to pass to the rate limit service. - # Acts as a container for a set of rate limit definitions within - # the RLS. - # domain: contour - # Defines whether to allow requests to proceed when the rate limit - # service fails to respond with a valid rate limit decision within - # the timeout defined on the extension service. - # failOpen: false - # Defines whether to include the X-RateLimit headers X-RateLimit-Limit, - # X-RateLimit-Remaining, and X-RateLimit-Reset (as defined by the IETF - # Internet-Draft linked below), on responses to clients when the Rate - # Limit Service is consulted for a request. - # ref. https://tools.ietf.org/id/draft-polli-ratelimit-headers-03.html - # enableXRateLimitHeaders: false - # Defines whether to translate status code 429 to grpc code RESOURCE_EXHAUSTED - # instead of the default UNAVAILABLE - # enableResourceExhaustedCode: false - # - # Global Policy settings. - # policy: - # # Default headers to set on all requests (unless set/removed on the HTTPProxy object itself) - # request-headers: - # set: - # # example: the hostname of the Envoy instance that proxied the request - # X-Envoy-Hostname: %HOSTNAME% - # # example: add a l5d-dst-override header to instruct Linkerd what service the request is destined for - # l5d-dst-override: %CONTOUR_SERVICE_NAME%.%CONTOUR_NAMESPACE%.svc.cluster.local:%CONTOUR_SERVICE_PORT% - # # default headers to set on all responses (unless set/removed on the HTTPProxy object itself) - # response-headers: - # set: - # # example: Envoy flags that provide additional details about the response or connection - # X-Envoy-Response-Flags: %RESPONSE_FLAGS% - # - # metrics: - # contour: - # address: 0.0.0.0 - # port: 8000 - # server-certificate-path: /path/to/server-cert.pem - # server-key-path: /path/to/server-private-key.pem - # ca-certificate-path: /path/to/root-ca-for-client-validation.pem - # envoy: - # address: 0.0.0.0 - # port: 8002 - # server-certificate-path: /path/to/server-cert.pem - # server-key-path: /path/to/server-private-key.pem - # ca-certificate-path: /path/to/root-ca-for-client-validation.pem - # - # listener: - # connection-balancer: exact - # socket-options: - # tos: 64 - # traffic-class: 64 diff --git a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/contour/upstream/01-crds.yaml b/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/contour/upstream/01-crds.yaml deleted file mode 100644 index 0beece5bc..000000000 --- a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/contour/upstream/01-crds.yaml +++ /dev/null @@ -1,8666 +0,0 @@ ---- -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.15.0 - name: contourconfigurations.projectcontour.io -spec: - preserveUnknownFields: false - group: projectcontour.io - names: - kind: ContourConfiguration - listKind: ContourConfigurationList - plural: contourconfigurations - shortNames: - - contourconfig - singular: contourconfiguration - scope: Namespaced - versions: - - name: v1alpha1 - schema: - openAPIV3Schema: - description: ContourConfiguration is the schema for a Contour instance. - properties: - apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - type: string - kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - metadata: - type: object - spec: - description: |- - ContourConfigurationSpec represents a configuration of a Contour controller. - It contains most of all the options that can be customized, the - other remaining options being command line flags. - properties: - debug: - description: |- - Debug contains parameters to enable debug logging - and debug interfaces inside Contour. - properties: - address: - description: |- - Defines the Contour debug address interface. - Contour's default is "127.0.0.1". - type: string - port: - description: |- - Defines the Contour debug address port. - Contour's default is 6060. - type: integer - type: object - enableExternalNameService: - description: |- - EnableExternalNameService allows processing of ExternalNameServices - Contour's default is false for security reasons. - type: boolean - envoy: - description: |- - Envoy contains parameters for Envoy as well - as how to optionally configure a managed Envoy fleet. - properties: - clientCertificate: - description: |- - ClientCertificate defines the namespace/name of the Kubernetes - secret containing the client certificate and private key - to be used when establishing TLS connection to upstream - cluster. - properties: - name: - type: string - namespace: - type: string - required: - - name - - namespace - type: object - cluster: - description: |- - Cluster holds various configurable Envoy cluster values that can - be set in the config file. - properties: - circuitBreakers: - description: |- - GlobalCircuitBreakerDefaults specifies default circuit breaker budget across all services. - If defined, this will be used as the default for all services. - properties: - maxConnections: - description: The maximum number of connections that a - single Envoy instance allows to the Kubernetes Service; - defaults to 1024. - format: int32 - type: integer - maxPendingRequests: - description: The maximum number of pending requests that - a single Envoy instance allows to the Kubernetes Service; - defaults to 1024. - format: int32 - type: integer - maxRequests: - description: The maximum parallel requests a single Envoy - instance allows to the Kubernetes Service; defaults - to 1024 - format: int32 - type: integer - maxRetries: - description: The maximum number of parallel retries a - single Envoy instance allows to the Kubernetes Service; - defaults to 3. - format: int32 - type: integer - perHostMaxConnections: - description: |- - PerHostMaxConnections is the maximum number of connections - that Envoy will allow to each individual host in a cluster. - format: int32 - type: integer - type: object - dnsLookupFamily: - description: |- - DNSLookupFamily defines how external names are looked up - When configured as V4, the DNS resolver will only perform a lookup - for addresses in the IPv4 family. If V6 is configured, the DNS resolver - will only perform a lookup for addresses in the IPv6 family. - If AUTO is configured, the DNS resolver will first perform a lookup - for addresses in the IPv6 family and fallback to a lookup for addresses - in the IPv4 family. If ALL is specified, the DNS resolver will perform a lookup for - both IPv4 and IPv6 families, and return all resolved addresses. - When this is used, Happy Eyeballs will be enabled for upstream connections. - Refer to Happy Eyeballs Support for more information. - Note: This only applies to externalName clusters. - See https://www.envoyproxy.io/docs/envoy/latest/api-v3/config/cluster/v3/cluster.proto.html#envoy-v3-api-enum-config-cluster-v3-cluster-dnslookupfamily - for more information. - Values: `auto` (default), `v4`, `v6`, `all`. - Other values will produce an error. - type: string - maxRequestsPerConnection: - description: |- - Defines the maximum requests for upstream connections. If not specified, there is no limit. - see https://www.envoyproxy.io/docs/envoy/latest/api-v3/config/core/v3/protocol.proto#envoy-v3-api-msg-config-core-v3-httpprotocoloptions - for more information. - format: int32 - minimum: 1 - type: integer - per-connection-buffer-limit-bytes: - description: |- - Defines the soft limit on size of the cluster’s new connection read and write buffers in bytes. - If unspecified, an implementation defined default is applied (1MiB). - see https://www.envoyproxy.io/docs/envoy/latest/api-v3/config/cluster/v3/cluster.proto#envoy-v3-api-field-config-cluster-v3-cluster-per-connection-buffer-limit-bytes - for more information. - format: int32 - minimum: 1 - type: integer - upstreamTLS: - description: UpstreamTLS contains the TLS policy parameters - for upstream connections - properties: - cipherSuites: - description: |- - CipherSuites defines the TLS ciphers to be supported by Envoy TLS - listeners when negotiating TLS 1.2. Ciphers are validated against the - set that Envoy supports by default. This parameter should only be used - by advanced users. Note that these will be ignored when TLS 1.3 is in - use. - This field is optional; when it is undefined, a Contour-managed ciphersuite list - will be used, which may be updated to keep it secure. - Contour's default list is: - - "[ECDHE-ECDSA-AES128-GCM-SHA256|ECDHE-ECDSA-CHACHA20-POLY1305]" - - "[ECDHE-RSA-AES128-GCM-SHA256|ECDHE-RSA-CHACHA20-POLY1305]" - - "ECDHE-ECDSA-AES256-GCM-SHA384" - - "ECDHE-RSA-AES256-GCM-SHA384" - Ciphers provided are validated against the following list: - - "[ECDHE-ECDSA-AES128-GCM-SHA256|ECDHE-ECDSA-CHACHA20-POLY1305]" - - "[ECDHE-RSA-AES128-GCM-SHA256|ECDHE-RSA-CHACHA20-POLY1305]" - - "ECDHE-ECDSA-AES128-GCM-SHA256" - - "ECDHE-RSA-AES128-GCM-SHA256" - - "ECDHE-ECDSA-AES128-SHA" - - "ECDHE-RSA-AES128-SHA" - - "AES128-GCM-SHA256" - - "AES128-SHA" - - "ECDHE-ECDSA-AES256-GCM-SHA384" - - "ECDHE-RSA-AES256-GCM-SHA384" - - "ECDHE-ECDSA-AES256-SHA" - - "ECDHE-RSA-AES256-SHA" - - "AES256-GCM-SHA384" - - "AES256-SHA" - Contour recommends leaving this undefined unless you are sure you must. - See: https://www.envoyproxy.io/docs/envoy/latest/api-v3/extensions/transport_sockets/tls/v3/common.proto#extensions-transport-sockets-tls-v3-tlsparameters - Note: This list is a superset of what is valid for stock Envoy builds and those using BoringSSL FIPS. - items: - type: string - type: array - maximumProtocolVersion: - description: |- - MaximumProtocolVersion is the maximum TLS version this vhost should - negotiate. - Values: `1.2`, `1.3`(default). - Other values will produce an error. - type: string - minimumProtocolVersion: - description: |- - MinimumProtocolVersion is the minimum TLS version this vhost should - negotiate. - Values: `1.2` (default), `1.3`. - Other values will produce an error. - type: string - type: object - type: object - defaultHTTPVersions: - description: |- - DefaultHTTPVersions defines the default set of HTTPS - versions the proxy should accept. HTTP versions are - strings of the form "HTTP/xx". Supported versions are - "HTTP/1.1" and "HTTP/2". - Values: `HTTP/1.1`, `HTTP/2` (default: both). - Other values will produce an error. - items: - description: HTTPVersionType is the name of a supported HTTP - version. - type: string - type: array - health: - description: |- - Health defines the endpoint Envoy uses to serve health checks. - Contour's default is { address: "0.0.0.0", port: 8002 }. - properties: - address: - description: Defines the health address interface. - minLength: 1 - type: string - port: - description: Defines the health port. - type: integer - type: object - http: - description: |- - Defines the HTTP Listener for Envoy. - Contour's default is { address: "0.0.0.0", port: 8080, accessLog: "/dev/stdout" }. - properties: - accessLog: - description: AccessLog defines where Envoy logs are outputted - for this listener. - type: string - address: - description: Defines an Envoy Listener Address. - minLength: 1 - type: string - port: - description: Defines an Envoy listener Port. - type: integer - type: object - https: - description: |- - Defines the HTTPS Listener for Envoy. - Contour's default is { address: "0.0.0.0", port: 8443, accessLog: "/dev/stdout" }. - properties: - accessLog: - description: AccessLog defines where Envoy logs are outputted - for this listener. - type: string - address: - description: Defines an Envoy Listener Address. - minLength: 1 - type: string - port: - description: Defines an Envoy listener Port. - type: integer - type: object - listener: - description: Listener hold various configurable Envoy listener - values. - properties: - connectionBalancer: - description: |- - ConnectionBalancer. If the value is exact, the listener will use the exact connection balancer - See https://www.envoyproxy.io/docs/envoy/latest/api-v2/api/v2/listener.proto#envoy-api-msg-listener-connectionbalanceconfig - for more information. - Values: (empty string): use the default ConnectionBalancer, `exact`: use the Exact ConnectionBalancer. - Other values will produce an error. - type: string - disableAllowChunkedLength: - description: |- - DisableAllowChunkedLength disables the RFC-compliant Envoy behavior to - strip the "Content-Length" header if "Transfer-Encoding: chunked" is - also set. This is an emergency off-switch to revert back to Envoy's - default behavior in case of failures. Please file an issue if failures - are encountered. - See: https://github.com/projectcontour/contour/issues/3221 - Contour's default is false. - type: boolean - disableMergeSlashes: - description: |- - DisableMergeSlashes disables Envoy's non-standard merge_slashes path transformation option - which strips duplicate slashes from request URL paths. - Contour's default is false. - type: boolean - httpMaxConcurrentStreams: - description: |- - Defines the value for SETTINGS_MAX_CONCURRENT_STREAMS Envoy will advertise in the - SETTINGS frame in HTTP/2 connections and the limit for concurrent streams allowed - for a peer on a single HTTP/2 connection. It is recommended to not set this lower - than 100 but this field can be used to bound resource usage by HTTP/2 connections - and mitigate attacks like CVE-2023-44487. The default value when this is not set is - unlimited. - format: int32 - minimum: 1 - type: integer - maxConnectionsPerListener: - description: |- - Defines the limit on number of active connections to a listener. The limit is applied - per listener. The default value when this is not set is unlimited. - format: int32 - minimum: 1 - type: integer - maxRequestsPerConnection: - description: |- - Defines the maximum requests for downstream connections. If not specified, there is no limit. - see https://www.envoyproxy.io/docs/envoy/latest/api-v3/config/core/v3/protocol.proto#envoy-v3-api-msg-config-core-v3-httpprotocoloptions - for more information. - format: int32 - minimum: 1 - type: integer - maxRequestsPerIOCycle: - description: |- - Defines the limit on number of HTTP requests that Envoy will process from a single - connection in a single I/O cycle. Requests over this limit are processed in subsequent - I/O cycles. Can be used as a mitigation for CVE-2023-44487 when abusive traffic is - detected. Configures the http.max_requests_per_io_cycle Envoy runtime setting. The default - value when this is not set is no limit. - format: int32 - minimum: 1 - type: integer - per-connection-buffer-limit-bytes: - description: |- - Defines the soft limit on size of the listener’s new connection read and write buffers in bytes. - If unspecified, an implementation defined default is applied (1MiB). - see https://www.envoyproxy.io/docs/envoy/latest/api-v3/config/listener/v3/listener.proto#envoy-v3-api-field-config-listener-v3-listener-per-connection-buffer-limit-bytes - for more information. - format: int32 - minimum: 1 - type: integer - serverHeaderTransformation: - description: |- - Defines the action to be applied to the Server header on the response path. - When configured as overwrite, overwrites any Server header with "envoy". - When configured as append_if_absent, if a Server header is present, pass it through, otherwise set it to "envoy". - When configured as pass_through, pass through the value of the Server header, and do not append a header if none is present. - Values: `overwrite` (default), `append_if_absent`, `pass_through` - Other values will produce an error. - Contour's default is overwrite. - type: string - socketOptions: - description: |- - SocketOptions defines configurable socket options for the listeners. - Single set of options are applied to all listeners. - properties: - tos: - description: |- - Defines the value for IPv4 TOS field (including 6 bit DSCP field) for IP packets originating from Envoy listeners. - Single value is applied to all listeners. - If listeners are bound to IPv6-only addresses, setting this option will cause an error. - format: int32 - maximum: 255 - minimum: 0 - type: integer - trafficClass: - description: |- - Defines the value for IPv6 Traffic Class field (including 6 bit DSCP field) for IP packets originating from the Envoy listeners. - Single value is applied to all listeners. - If listeners are bound to IPv4-only addresses, setting this option will cause an error. - format: int32 - maximum: 255 - minimum: 0 - type: integer - type: object - tls: - description: TLS holds various configurable Envoy TLS listener - values. - properties: - cipherSuites: - description: |- - CipherSuites defines the TLS ciphers to be supported by Envoy TLS - listeners when negotiating TLS 1.2. Ciphers are validated against the - set that Envoy supports by default. This parameter should only be used - by advanced users. Note that these will be ignored when TLS 1.3 is in - use. - This field is optional; when it is undefined, a Contour-managed ciphersuite list - will be used, which may be updated to keep it secure. - Contour's default list is: - - "[ECDHE-ECDSA-AES128-GCM-SHA256|ECDHE-ECDSA-CHACHA20-POLY1305]" - - "[ECDHE-RSA-AES128-GCM-SHA256|ECDHE-RSA-CHACHA20-POLY1305]" - - "ECDHE-ECDSA-AES256-GCM-SHA384" - - "ECDHE-RSA-AES256-GCM-SHA384" - Ciphers provided are validated against the following list: - - "[ECDHE-ECDSA-AES128-GCM-SHA256|ECDHE-ECDSA-CHACHA20-POLY1305]" - - "[ECDHE-RSA-AES128-GCM-SHA256|ECDHE-RSA-CHACHA20-POLY1305]" - - "ECDHE-ECDSA-AES128-GCM-SHA256" - - "ECDHE-RSA-AES128-GCM-SHA256" - - "ECDHE-ECDSA-AES128-SHA" - - "ECDHE-RSA-AES128-SHA" - - "AES128-GCM-SHA256" - - "AES128-SHA" - - "ECDHE-ECDSA-AES256-GCM-SHA384" - - "ECDHE-RSA-AES256-GCM-SHA384" - - "ECDHE-ECDSA-AES256-SHA" - - "ECDHE-RSA-AES256-SHA" - - "AES256-GCM-SHA384" - - "AES256-SHA" - Contour recommends leaving this undefined unless you are sure you must. - See: https://www.envoyproxy.io/docs/envoy/latest/api-v3/extensions/transport_sockets/tls/v3/common.proto#extensions-transport-sockets-tls-v3-tlsparameters - Note: This list is a superset of what is valid for stock Envoy builds and those using BoringSSL FIPS. - items: - type: string - type: array - maximumProtocolVersion: - description: |- - MaximumProtocolVersion is the maximum TLS version this vhost should - negotiate. - Values: `1.2`, `1.3`(default). - Other values will produce an error. - type: string - minimumProtocolVersion: - description: |- - MinimumProtocolVersion is the minimum TLS version this vhost should - negotiate. - Values: `1.2` (default), `1.3`. - Other values will produce an error. - type: string - type: object - useProxyProtocol: - description: |- - Use PROXY protocol for all listeners. - Contour's default is false. - type: boolean - type: object - logging: - description: Logging defines how Envoy's logs can be configured. - properties: - accessLogFormat: - description: |- - AccessLogFormat sets the global access log format. - Values: `envoy` (default), `json`. - Other values will produce an error. - type: string - accessLogFormatString: - description: |- - AccessLogFormatString sets the access log format when format is set to `envoy`. - When empty, Envoy's default format is used. - type: string - accessLogJSONFields: - description: |- - AccessLogJSONFields sets the fields that JSON logging will - output when AccessLogFormat is json. - items: - type: string - type: array - accessLogLevel: - description: |- - AccessLogLevel sets the verbosity level of the access log. - Values: `info` (default, all requests are logged), `error` (all non-success requests, i.e. 300+ response code, are logged), `critical` (all 5xx requests are logged) and `disabled`. - Other values will produce an error. - type: string - type: object - metrics: - description: |- - Metrics defines the endpoint Envoy uses to serve metrics. - Contour's default is { address: "0.0.0.0", port: 8002 }. - properties: - address: - description: Defines the metrics address interface. - maxLength: 253 - minLength: 1 - type: string - port: - description: Defines the metrics port. - type: integer - tls: - description: |- - TLS holds TLS file config details. - Metrics and health endpoints cannot have same port number when metrics is served over HTTPS. - properties: - caFile: - description: CA filename. - type: string - certFile: - description: Client certificate filename. - type: string - keyFile: - description: Client key filename. - type: string - type: object - type: object - network: - description: Network holds various configurable Envoy network - values. - properties: - adminPort: - description: |- - Configure the port used to access the Envoy Admin interface. - If configured to port "0" then the admin interface is disabled. - Contour's default is 9001. - type: integer - numTrustedHops: - description: |- - XffNumTrustedHops defines the number of additional ingress proxy hops from the - right side of the x-forwarded-for HTTP header to trust when determining the origin - client’s IP address. - See https://www.envoyproxy.io/docs/envoy/v1.17.0/api-v3/extensions/filters/network/http_connection_manager/v3/http_connection_manager.proto?highlight=xff_num_trusted_hops - for more information. - Contour's default is 0. - format: int32 - type: integer - type: object - service: - description: |- - Service holds Envoy service parameters for setting Ingress status. - Contour's default is { namespace: "projectcontour", name: "envoy" }. - properties: - name: - type: string - namespace: - type: string - required: - - name - - namespace - type: object - timeouts: - description: |- - Timeouts holds various configurable timeouts that can - be set in the config file. - properties: - connectTimeout: - description: |- - ConnectTimeout defines how long the proxy should wait when establishing connection to upstream service. - If not set, a default value of 2 seconds will be used. - See https://www.envoyproxy.io/docs/envoy/latest/api-v3/config/cluster/v3/cluster.proto#envoy-v3-api-field-config-cluster-v3-cluster-connect-timeout - for more information. - type: string - connectionIdleTimeout: - description: |- - ConnectionIdleTimeout defines how long the proxy should wait while there are - no active requests (for HTTP/1.1) or streams (for HTTP/2) before terminating - an HTTP connection. Set to "infinity" to disable the timeout entirely. - See https://www.envoyproxy.io/docs/envoy/latest/api-v3/config/core/v3/protocol.proto#envoy-v3-api-field-config-core-v3-httpprotocoloptions-idle-timeout - for more information. - type: string - connectionShutdownGracePeriod: - description: |- - ConnectionShutdownGracePeriod defines how long the proxy will wait between sending an - initial GOAWAY frame and a second, final GOAWAY frame when terminating an HTTP/2 connection. - During this grace period, the proxy will continue to respond to new streams. After the final - GOAWAY frame has been sent, the proxy will refuse new streams. - See https://www.envoyproxy.io/docs/envoy/latest/api-v3/extensions/filters/network/http_connection_manager/v3/http_connection_manager.proto#envoy-v3-api-field-extensions-filters-network-http-connection-manager-v3-httpconnectionmanager-drain-timeout - for more information. - type: string - delayedCloseTimeout: - description: |- - DelayedCloseTimeout defines how long envoy will wait, once connection - close processing has been initiated, for the downstream peer to close - the connection before Envoy closes the socket associated with the connection. - Setting this timeout to 'infinity' will disable it, equivalent to setting it to '0' - in Envoy. Leaving it unset will result in the Envoy default value being used. - See https://www.envoyproxy.io/docs/envoy/latest/api-v3/extensions/filters/network/http_connection_manager/v3/http_connection_manager.proto#envoy-v3-api-field-extensions-filters-network-http-connection-manager-v3-httpconnectionmanager-delayed-close-timeout - for more information. - type: string - maxConnectionDuration: - description: |- - MaxConnectionDuration defines the maximum period of time after an HTTP connection - has been established from the client to the proxy before it is closed by the proxy, - regardless of whether there has been activity or not. Omit or set to "infinity" for - no max duration. - See https://www.envoyproxy.io/docs/envoy/latest/api-v3/config/core/v3/protocol.proto#envoy-v3-api-field-config-core-v3-httpprotocoloptions-max-connection-duration - for more information. - type: string - requestTimeout: - description: |- - RequestTimeout sets the client request timeout globally for Contour. Note that - this is a timeout for the entire request, not an idle timeout. Omit or set to - "infinity" to disable the timeout entirely. - See https://www.envoyproxy.io/docs/envoy/latest/api-v3/extensions/filters/network/http_connection_manager/v3/http_connection_manager.proto#envoy-v3-api-field-extensions-filters-network-http-connection-manager-v3-httpconnectionmanager-request-timeout - for more information. - type: string - streamIdleTimeout: - description: |- - StreamIdleTimeout defines how long the proxy should wait while there is no - request activity (for HTTP/1.1) or stream activity (for HTTP/2) before - terminating the HTTP request or stream. Set to "infinity" to disable the - timeout entirely. - See https://www.envoyproxy.io/docs/envoy/latest/api-v3/extensions/filters/network/http_connection_manager/v3/http_connection_manager.proto#envoy-v3-api-field-extensions-filters-network-http-connection-manager-v3-httpconnectionmanager-stream-idle-timeout - for more information. - type: string - type: object - type: object - featureFlags: - description: |- - FeatureFlags defines toggle to enable new contour features. - Available toggles are: - useEndpointSlices - Configures contour to fetch endpoint data - from k8s endpoint slices. defaults to true, - If false then reads endpoint data from the k8s endpoints. - items: - type: string - type: array - gateway: - description: |- - Gateway contains parameters for the gateway-api Gateway that Contour - is configured to serve traffic. - properties: - gatewayRef: - description: |- - GatewayRef defines the specific Gateway that this Contour - instance corresponds to. - properties: - name: - type: string - namespace: - type: string - required: - - name - - namespace - type: object - required: - - gatewayRef - type: object - globalExtAuth: - description: |- - GlobalExternalAuthorization allows envoys external authorization filter - to be enabled for all virtual hosts. - properties: - authPolicy: - description: |- - AuthPolicy sets a default authorization policy for client requests. - This policy will be used unless overridden by individual routes. - properties: - context: - additionalProperties: - type: string - description: |- - Context is a set of key/value pairs that are sent to the - authentication server in the check request. If a context - is provided at an enclosing scope, the entries are merged - such that the inner scope overrides matching keys from the - outer scope. - type: object - disabled: - description: |- - When true, this field disables client request authentication - for the scope of the policy. - type: boolean - type: object - extensionRef: - description: ExtensionServiceRef specifies the extension resource - that will authorize client requests. - properties: - apiVersion: - description: |- - API version of the referent. - If this field is not specified, the default "projectcontour.io/v1alpha1" will be used - minLength: 1 - type: string - name: - description: |- - Name of the referent. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - minLength: 1 - type: string - namespace: - description: |- - Namespace of the referent. - If this field is not specifies, the namespace of the resource that targets the referent will be used. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/ - minLength: 1 - type: string - type: object - failOpen: - description: |- - If FailOpen is true, the client request is forwarded to the upstream service - even if the authorization server fails to respond. This field should not be - set in most cases. It is intended for use only while migrating applications - from internal authorization to Contour external authorization. - type: boolean - responseTimeout: - description: |- - ResponseTimeout configures maximum time to wait for a check response from the authorization server. - Timeout durations are expressed in the Go [Duration format](https://godoc.org/time#ParseDuration). - Valid time units are "ns", "us" (or "µs"), "ms", "s", "m", "h". - The string "infinity" is also a valid input and specifies no timeout. - pattern: ^(((\d*(\.\d*)?h)|(\d*(\.\d*)?m)|(\d*(\.\d*)?s)|(\d*(\.\d*)?ms)|(\d*(\.\d*)?us)|(\d*(\.\d*)?µs)|(\d*(\.\d*)?ns))+|infinity|infinite)$ - type: string - withRequestBody: - description: WithRequestBody specifies configuration for sending - the client request's body to authorization server. - properties: - allowPartialMessage: - description: If AllowPartialMessage is true, then Envoy will - buffer the body until MaxRequestBytes are reached. - type: boolean - maxRequestBytes: - default: 1024 - description: MaxRequestBytes sets the maximum size of message - body ExtAuthz filter will hold in-memory. - format: int32 - minimum: 1 - type: integer - packAsBytes: - description: If PackAsBytes is true, the body sent to Authorization - Server is in raw bytes. - type: boolean - type: object - type: object - health: - description: |- - Health defines the endpoints Contour uses to serve health checks. - Contour's default is { address: "0.0.0.0", port: 8000 }. - properties: - address: - description: Defines the health address interface. - minLength: 1 - type: string - port: - description: Defines the health port. - type: integer - type: object - httpproxy: - description: HTTPProxy defines parameters on HTTPProxy. - properties: - disablePermitInsecure: - description: |- - DisablePermitInsecure disables the use of the - permitInsecure field in HTTPProxy. - Contour's default is false. - type: boolean - fallbackCertificate: - description: |- - FallbackCertificate defines the namespace/name of the Kubernetes secret to - use as fallback when a non-SNI request is received. - properties: - name: - type: string - namespace: - type: string - required: - - name - - namespace - type: object - rootNamespaces: - description: Restrict Contour to searching these namespaces for - root ingress routes. - items: - type: string - type: array - type: object - ingress: - description: Ingress contains parameters for ingress options. - properties: - classNames: - description: Ingress Class Names Contour should use. - items: - type: string - type: array - statusAddress: - description: Address to set in Ingress object status. - type: string - type: object - metrics: - description: |- - Metrics defines the endpoint Contour uses to serve metrics. - Contour's default is { address: "0.0.0.0", port: 8000 }. - properties: - address: - description: Defines the metrics address interface. - maxLength: 253 - minLength: 1 - type: string - port: - description: Defines the metrics port. - type: integer - tls: - description: |- - TLS holds TLS file config details. - Metrics and health endpoints cannot have same port number when metrics is served over HTTPS. - properties: - caFile: - description: CA filename. - type: string - certFile: - description: Client certificate filename. - type: string - keyFile: - description: Client key filename. - type: string - type: object - type: object - policy: - description: Policy specifies default policy applied if not overridden - by the user - properties: - applyToIngress: - description: |- - ApplyToIngress determines if the Policies will apply to ingress objects - Contour's default is false. - type: boolean - requestHeaders: - description: RequestHeadersPolicy defines the request headers - set/removed on all routes - properties: - remove: - items: - type: string - type: array - set: - additionalProperties: - type: string - type: object - type: object - responseHeaders: - description: ResponseHeadersPolicy defines the response headers - set/removed on all routes - properties: - remove: - items: - type: string - type: array - set: - additionalProperties: - type: string - type: object - type: object - type: object - rateLimitService: - description: |- - RateLimitService optionally holds properties of the Rate Limit Service - to be used for global rate limiting. - properties: - defaultGlobalRateLimitPolicy: - description: |- - DefaultGlobalRateLimitPolicy allows setting a default global rate limit policy for every HTTPProxy. - HTTPProxy can overwrite this configuration. - properties: - descriptors: - description: |- - Descriptors defines the list of descriptors that will - be generated and sent to the rate limit service. Each - descriptor contains 1+ key-value pair entries. - items: - description: RateLimitDescriptor defines a list of key-value - pair generators. - properties: - entries: - description: Entries is the list of key-value pair generators. - items: - description: |- - RateLimitDescriptorEntry is a key-value pair generator. Exactly - one field on this struct must be non-nil. - properties: - genericKey: - description: GenericKey defines a descriptor entry - with a static key and value. - properties: - key: - description: |- - Key defines the key of the descriptor entry. If not set, the - key is set to "generic_key". - type: string - value: - description: Value defines the value of the - descriptor entry. - minLength: 1 - type: string - type: object - remoteAddress: - description: |- - RemoteAddress defines a descriptor entry with a key of "remote_address" - and a value equal to the client's IP address (from x-forwarded-for). - type: object - requestHeader: - description: |- - RequestHeader defines a descriptor entry that's populated only if - a given header is present on the request. The descriptor key is static, - and the descriptor value is equal to the value of the header. - properties: - descriptorKey: - description: DescriptorKey defines the key - to use on the descriptor entry. - minLength: 1 - type: string - headerName: - description: HeaderName defines the name of - the header to look for on the request. - minLength: 1 - type: string - type: object - requestHeaderValueMatch: - description: |- - RequestHeaderValueMatch defines a descriptor entry that's populated - if the request's headers match a set of 1+ match criteria. The - descriptor key is "header_match", and the descriptor value is static. - properties: - expectMatch: - default: true - description: |- - ExpectMatch defines whether the request must positively match the match - criteria in order to generate a descriptor entry (i.e. true), or not - match the match criteria in order to generate a descriptor entry (i.e. false). - The default is true. - type: boolean - headers: - description: |- - Headers is a list of 1+ match criteria to apply against the request - to determine whether to populate the descriptor entry or not. - items: - description: |- - HeaderMatchCondition specifies how to conditionally match against HTTP - headers. The Name field is required, only one of Present, NotPresent, - Contains, NotContains, Exact, NotExact and Regex can be set. - For negative matching rules only (e.g. NotContains or NotExact) you can set - TreatMissingAsEmpty. - IgnoreCase has no effect for Regex. - properties: - contains: - description: |- - Contains specifies a substring that must be present in - the header value. - type: string - exact: - description: Exact specifies a string - that the header value must be equal - to. - type: string - ignoreCase: - description: |- - IgnoreCase specifies that string matching should be case insensitive. - Note that this has no effect on the Regex parameter. - type: boolean - name: - description: |- - Name is the name of the header to match against. Name is required. - Header names are case insensitive. - type: string - notcontains: - description: |- - NotContains specifies a substring that must not be present - in the header value. - type: string - notexact: - description: |- - NoExact specifies a string that the header value must not be - equal to. The condition is true if the header has any other value. - type: string - notpresent: - description: |- - NotPresent specifies that condition is true when the named header - is not present. Note that setting NotPresent to false does not - make the condition true if the named header is present. - type: boolean - present: - description: |- - Present specifies that condition is true when the named header - is present, regardless of its value. Note that setting Present - to false does not make the condition true if the named header - is absent. - type: boolean - regex: - description: |- - Regex specifies a regular expression pattern that must match the header - value. - type: string - treatMissingAsEmpty: - description: |- - TreatMissingAsEmpty specifies if the header match rule specified header - does not exist, this header value will be treated as empty. Defaults to false. - Unlike the underlying Envoy implementation this is **only** supported for - negative matches (e.g. NotContains, NotExact). - type: boolean - required: - - name - type: object - minItems: 1 - type: array - value: - description: Value defines the value of the - descriptor entry. - minLength: 1 - type: string - type: object - type: object - minItems: 1 - type: array - type: object - minItems: 1 - type: array - disabled: - description: |- - Disabled configures the HTTPProxy to not use - the default global rate limit policy defined by the Contour configuration. - type: boolean - type: object - domain: - description: Domain is passed to the Rate Limit Service. - type: string - enableResourceExhaustedCode: - description: |- - EnableResourceExhaustedCode enables translating error code 429 to - grpc code RESOURCE_EXHAUSTED. When disabled it's translated to UNAVAILABLE - type: boolean - enableXRateLimitHeaders: - description: |- - EnableXRateLimitHeaders defines whether to include the X-RateLimit - headers X-RateLimit-Limit, X-RateLimit-Remaining, and X-RateLimit-Reset - (as defined by the IETF Internet-Draft linked below), on responses - to clients when the Rate Limit Service is consulted for a request. - ref. https://tools.ietf.org/id/draft-polli-ratelimit-headers-03.html - type: boolean - extensionService: - description: ExtensionService identifies the extension service - defining the RLS. - properties: - name: - type: string - namespace: - type: string - required: - - name - - namespace - type: object - failOpen: - description: |- - FailOpen defines whether to allow requests to proceed when the - Rate Limit Service fails to respond with a valid rate limit - decision within the timeout defined on the extension service. - type: boolean - required: - - extensionService - type: object - tracing: - description: Tracing defines properties for exporting trace data to - OpenTelemetry. - properties: - customTags: - description: CustomTags defines a list of custom tags with unique - tag name. - items: - description: |- - CustomTag defines custom tags with unique tag name - to create tags for the active span. - properties: - literal: - description: |- - Literal is a static custom tag value. - Precisely one of Literal, RequestHeaderName must be set. - type: string - requestHeaderName: - description: |- - RequestHeaderName indicates which request header - the label value is obtained from. - Precisely one of Literal, RequestHeaderName must be set. - type: string - tagName: - description: TagName is the unique name of the custom tag. - type: string - required: - - tagName - type: object - type: array - extensionService: - description: ExtensionService identifies the extension service - defining the otel-collector. - properties: - name: - type: string - namespace: - type: string - required: - - name - - namespace - type: object - includePodDetail: - description: |- - IncludePodDetail defines a flag. - If it is true, contour will add the pod name and namespace to the span of the trace. - the default is true. - Note: The Envoy pods MUST have the HOSTNAME and CONTOUR_NAMESPACE environment variables set for this to work properly. - type: boolean - maxPathTagLength: - description: |- - MaxPathTagLength defines maximum length of the request path - to extract and include in the HttpUrl tag. - contour's default is 256. - format: int32 - type: integer - overallSampling: - description: |- - OverallSampling defines the sampling rate of trace data. - contour's default is 100. - type: string - serviceName: - description: |- - ServiceName defines the name for the service. - contour's default is contour. - type: string - required: - - extensionService - type: object - xdsServer: - description: XDSServer contains parameters for the xDS server. - properties: - address: - description: |- - Defines the xDS gRPC API address which Contour will serve. - Contour's default is "0.0.0.0". - minLength: 1 - type: string - port: - description: |- - Defines the xDS gRPC API port which Contour will serve. - Contour's default is 8001. - type: integer - tls: - description: |- - TLS holds TLS file config details. - Contour's default is { caFile: "/certs/ca.crt", certFile: "/certs/tls.cert", keyFile: "/certs/tls.key", insecure: false }. - properties: - caFile: - description: CA filename. - type: string - certFile: - description: Client certificate filename. - type: string - insecure: - description: Allow serving the xDS gRPC API without TLS. - type: boolean - keyFile: - description: Client key filename. - type: string - type: object - type: - description: |- - Defines the XDSServer to use for `contour serve`. - Values: `envoy` (default), `contour (deprecated)`. - Other values will produce an error. - Deprecated: this field will be removed in a future release when - the `contour` xDS server implementation is removed. - type: string - type: object - type: object - status: - description: ContourConfigurationStatus defines the observed state of - a ContourConfiguration resource. - properties: - conditions: - description: |- - Conditions contains the current status of the Contour resource. - Contour will update a single condition, `Valid`, that is in normal-true polarity. - Contour will not modify any other Conditions set in this block, - in case some other controller wants to add a Condition. - items: - description: |- - DetailedCondition is an extension of the normal Kubernetes conditions, with two extra - fields to hold sub-conditions, which provide more detailed reasons for the state (True or False) - of the condition. - `errors` holds information about sub-conditions which are fatal to that condition and render its state False. - `warnings` holds information about sub-conditions which are not fatal to that condition and do not force the state to be False. - Remember that Conditions have a type, a status, and a reason. - The type is the type of the condition, the most important one in this CRD set is `Valid`. - `Valid` is a positive-polarity condition: when it is `status: true` there are no problems. - In more detail, `status: true` means that the object is has been ingested into Contour with no errors. - `warnings` may still be present, and will be indicated in the Reason field. There must be zero entries in the `errors` - slice in this case. - `Valid`, `status: false` means that the object has had one or more fatal errors during processing into Contour. - The details of the errors will be present under the `errors` field. There must be at least one error in the `errors` - slice if `status` is `false`. - For DetailedConditions of types other than `Valid`, the Condition must be in the negative polarity. - When they have `status` `true`, there is an error. There must be at least one entry in the `errors` Subcondition slice. - When they have `status` `false`, there are no serious errors, and there must be zero entries in the `errors` slice. - In either case, there may be entries in the `warnings` slice. - Regardless of the polarity, the `reason` and `message` fields must be updated with either the detail of the reason - (if there is one and only one entry in total across both the `errors` and `warnings` slices), or - `MultipleReasons` if there is more than one entry. - properties: - errors: - description: |- - Errors contains a slice of relevant error subconditions for this object. - Subconditions are expected to appear when relevant (when there is a error), and disappear when not relevant. - An empty slice here indicates no errors. - items: - description: |- - SubCondition is a Condition-like type intended for use as a subcondition inside a DetailedCondition. - It contains a subset of the Condition fields. - It is intended for warnings and errors, so `type` names should use abnormal-true polarity, - that is, they should be of the form "ErrorPresent: true". - The expected lifecycle for these errors is that they should only be present when the error or warning is, - and should be removed when they are not relevant. - properties: - message: - description: |- - Message is a human readable message indicating details about the transition. - This may be an empty string. - maxLength: 32768 - type: string - reason: - description: |- - Reason contains a programmatic identifier indicating the reason for the condition's last transition. - Producers of specific condition types may define expected values and meanings for this field, - and whether the values are considered a guaranteed API. - The value should be a CamelCase string. - This field may not be empty. - maxLength: 1024 - minLength: 1 - pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ - type: string - status: - description: Status of the condition, one of True, False, - Unknown. - enum: - - "True" - - "False" - - Unknown - type: string - type: - description: |- - Type of condition in `CamelCase` or in `foo.example.com/CamelCase`. - This must be in abnormal-true polarity, that is, `ErrorFound` or `controller.io/ErrorFound`. - The regex it matches is (dns1123SubdomainFmt/)?(qualifiedNameFmt) - maxLength: 316 - pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ - type: string - required: - - message - - reason - - status - - type - type: object - type: array - lastTransitionTime: - description: |- - lastTransitionTime is the last time the condition transitioned from one status to another. - This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable. - format: date-time - type: string - message: - description: |- - message is a human readable message indicating details about the transition. - This may be an empty string. - maxLength: 32768 - type: string - observedGeneration: - description: |- - observedGeneration represents the .metadata.generation that the condition was set based upon. - For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date - with respect to the current state of the instance. - format: int64 - minimum: 0 - type: integer - reason: - description: |- - reason contains a programmatic identifier indicating the reason for the condition's last transition. - Producers of specific condition types may define expected values and meanings for this field, - and whether the values are considered a guaranteed API. - The value should be a CamelCase string. - This field may not be empty. - maxLength: 1024 - minLength: 1 - pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ - type: string - status: - description: status of the condition, one of True, False, Unknown. - enum: - - "True" - - "False" - - Unknown - type: string - type: - description: |- - type of condition in CamelCase or in foo.example.com/CamelCase. - --- - Many .condition.type values are consistent across resources like Available, but because arbitrary conditions can be - useful (see .node.status.conditions), the ability to deconflict is important. - The regex it matches is (dns1123SubdomainFmt/)?(qualifiedNameFmt) - maxLength: 316 - pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ - type: string - warnings: - description: |- - Warnings contains a slice of relevant warning subconditions for this object. - Subconditions are expected to appear when relevant (when there is a warning), and disappear when not relevant. - An empty slice here indicates no warnings. - items: - description: |- - SubCondition is a Condition-like type intended for use as a subcondition inside a DetailedCondition. - It contains a subset of the Condition fields. - It is intended for warnings and errors, so `type` names should use abnormal-true polarity, - that is, they should be of the form "ErrorPresent: true". - The expected lifecycle for these errors is that they should only be present when the error or warning is, - and should be removed when they are not relevant. - properties: - message: - description: |- - Message is a human readable message indicating details about the transition. - This may be an empty string. - maxLength: 32768 - type: string - reason: - description: |- - Reason contains a programmatic identifier indicating the reason for the condition's last transition. - Producers of specific condition types may define expected values and meanings for this field, - and whether the values are considered a guaranteed API. - The value should be a CamelCase string. - This field may not be empty. - maxLength: 1024 - minLength: 1 - pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ - type: string - status: - description: Status of the condition, one of True, False, - Unknown. - enum: - - "True" - - "False" - - Unknown - type: string - type: - description: |- - Type of condition in `CamelCase` or in `foo.example.com/CamelCase`. - This must be in abnormal-true polarity, that is, `ErrorFound` or `controller.io/ErrorFound`. - The regex it matches is (dns1123SubdomainFmt/)?(qualifiedNameFmt) - maxLength: 316 - pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ - type: string - required: - - message - - reason - - status - - type - type: object - type: array - required: - - lastTransitionTime - - message - - reason - - status - - type - type: object - type: array - x-kubernetes-list-map-keys: - - type - x-kubernetes-list-type: map - type: object - required: - - spec - type: object - served: true - storage: true - subresources: - status: {} ---- -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.15.0 - name: contourdeployments.projectcontour.io -spec: - preserveUnknownFields: false - group: projectcontour.io - names: - kind: ContourDeployment - listKind: ContourDeploymentList - plural: contourdeployments - shortNames: - - contourdeploy - singular: contourdeployment - scope: Namespaced - versions: - - name: v1alpha1 - schema: - openAPIV3Schema: - description: ContourDeployment is the schema for a Contour Deployment. - properties: - apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - type: string - kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - metadata: - type: object - spec: - description: |- - ContourDeploymentSpec specifies options for how a Contour - instance should be provisioned. - properties: - contour: - description: |- - Contour specifies deployment-time settings for the Contour - part of the installation, i.e. the xDS server/control plane - and associated resources, including things like replica count - for the Deployment, and node placement constraints for the pods. - properties: - deployment: - description: Deployment describes the settings for running contour - as a `Deployment`. - properties: - replicas: - description: Replicas is the desired number of replicas. - format: int32 - minimum: 0 - type: integer - strategy: - description: Strategy describes the deployment strategy to - use to replace existing pods with new pods. - properties: - rollingUpdate: - description: |- - Rolling update config params. Present only if DeploymentStrategyType = - RollingUpdate. - --- - TODO: Update this to follow our convention for oneOf, whatever we decide it - to be. - properties: - maxSurge: - anyOf: - - type: integer - - type: string - description: |- - The maximum number of pods that can be scheduled above the desired number of - pods. - Value can be an absolute number (ex: 5) or a percentage of desired pods (ex: 10%). - This can not be 0 if MaxUnavailable is 0. - Absolute number is calculated from percentage by rounding up. - Defaults to 25%. - Example: when this is set to 30%, the new ReplicaSet can be scaled up immediately when - the rolling update starts, such that the total number of old and new pods do not exceed - 130% of desired pods. Once old pods have been killed, - new ReplicaSet can be scaled up further, ensuring that total number of pods running - at any time during the update is at most 130% of desired pods. - x-kubernetes-int-or-string: true - maxUnavailable: - anyOf: - - type: integer - - type: string - description: |- - The maximum number of pods that can be unavailable during the update. - Value can be an absolute number (ex: 5) or a percentage of desired pods (ex: 10%). - Absolute number is calculated from percentage by rounding down. - This can not be 0 if MaxSurge is 0. - Defaults to 25%. - Example: when this is set to 30%, the old ReplicaSet can be scaled down to 70% of desired pods - immediately when the rolling update starts. Once new pods are ready, old ReplicaSet - can be scaled down further, followed by scaling up the new ReplicaSet, ensuring - that the total number of pods available at all times during the update is at - least 70% of desired pods. - x-kubernetes-int-or-string: true - type: object - type: - description: Type of deployment. Can be "Recreate" or - "RollingUpdate". Default is RollingUpdate. - type: string - type: object - type: object - disabledFeatures: - description: |- - DisabledFeatures defines an array of resources that will be ignored by - contour reconciler. - items: - enum: - - grpcroutes - - tlsroutes - - extensionservices - - backendtlspolicies - type: string - maxItems: 42 - minItems: 1 - type: array - kubernetesLogLevel: - description: |- - KubernetesLogLevel Enable Kubernetes client debug logging with log level. If unset, - defaults to 0. - maximum: 9 - minimum: 0 - type: integer - logLevel: - description: |- - LogLevel sets the log level for Contour - Allowed values are "info", "debug". - type: string - nodePlacement: - description: NodePlacement describes node scheduling configuration - of Contour pods. - properties: - nodeSelector: - additionalProperties: - type: string - description: |- - NodeSelector is the simplest recommended form of node selection constraint - and specifies a map of key-value pairs. For the pod to be eligible - to run on a node, the node must have each of the indicated key-value pairs - as labels (it can have additional labels as well). - If unset, the pod(s) will be scheduled to any available node. - type: object - tolerations: - description: |- - Tolerations work with taints to ensure that pods are not scheduled - onto inappropriate nodes. One or more taints are applied to a node; this - marks that the node should not accept any pods that do not tolerate the - taints. - The default is an empty list. - See https://kubernetes.io/docs/concepts/configuration/taint-and-toleration/ - for additional details. - items: - description: |- - The pod this Toleration is attached to tolerates any taint that matches - the triple using the matching operator . - properties: - effect: - description: |- - Effect indicates the taint effect to match. Empty means match all taint effects. - When specified, allowed values are NoSchedule, PreferNoSchedule and NoExecute. - type: string - key: - description: |- - Key is the taint key that the toleration applies to. Empty means match all taint keys. - If the key is empty, operator must be Exists; this combination means to match all values and all keys. - type: string - operator: - description: |- - Operator represents a key's relationship to the value. - Valid operators are Exists and Equal. Defaults to Equal. - Exists is equivalent to wildcard for value, so that a pod can - tolerate all taints of a particular category. - type: string - tolerationSeconds: - description: |- - TolerationSeconds represents the period of time the toleration (which must be - of effect NoExecute, otherwise this field is ignored) tolerates the taint. By default, - it is not set, which means tolerate the taint forever (do not evict). Zero and - negative values will be treated as 0 (evict immediately) by the system. - format: int64 - type: integer - value: - description: |- - Value is the taint value the toleration matches to. - If the operator is Exists, the value should be empty, otherwise just a regular string. - type: string - type: object - type: array - type: object - podAnnotations: - additionalProperties: - type: string - description: |- - PodAnnotations defines annotations to add to the Contour pods. - the annotations for Prometheus will be appended or overwritten with predefined value. - type: object - replicas: - description: |- - Deprecated: Use `DeploymentSettings.Replicas` instead. - Replicas is the desired number of Contour replicas. If if unset, - defaults to 2. - if both `DeploymentSettings.Replicas` and this one is set, use `DeploymentSettings.Replicas`. - format: int32 - minimum: 0 - type: integer - resources: - description: |- - Compute Resources required by contour container. - Cannot be updated. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ - properties: - claims: - description: |- - Claims lists the names of resources, defined in spec.resourceClaims, - that are used by this container. - This is an alpha field and requires enabling the - DynamicResourceAllocation feature gate. - This field is immutable. It can only be set for containers. - items: - description: ResourceClaim references one entry in PodSpec.ResourceClaims. - properties: - name: - description: |- - Name must match the name of one entry in pod.spec.resourceClaims of - the Pod where this field is used. It makes that resource available - inside a container. - type: string - required: - - name - type: object - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map - limits: - additionalProperties: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - description: |- - Limits describes the maximum amount of compute resources allowed. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ - type: object - requests: - additionalProperties: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - description: |- - Requests describes the minimum amount of compute resources required. - If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, - otherwise to an implementation-defined value. Requests cannot exceed Limits. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ - type: object - type: object - watchNamespaces: - description: |- - WatchNamespaces is an array of namespaces. Setting it will instruct the contour instance - to only watch this subset of namespaces. - items: - description: |- - Namespace refers to a Kubernetes namespace. It must be a RFC 1123 label. - This validation is based off of the corresponding Kubernetes validation: - https://github.com/kubernetes/apimachinery/blob/02cfb53916346d085a6c6c7c66f882e3c6b0eca6/pkg/util/validation/validation.go#L187 - This is used for Namespace name validation here: - https://github.com/kubernetes/apimachinery/blob/02cfb53916346d085a6c6c7c66f882e3c6b0eca6/pkg/api/validation/generic.go#L63 - Valid values include: - * "example" - Invalid values include: - * "example.com" - "." is an invalid character - maxLength: 63 - minLength: 1 - pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ - type: string - maxItems: 42 - minItems: 1 - type: array - type: object - envoy: - description: |- - Envoy specifies deployment-time settings for the Envoy - part of the installation, i.e. the xDS client/data plane - and associated resources, including things like the workload - type to use (DaemonSet or Deployment), node placement constraints - for the pods, and various options for the Envoy service. - properties: - baseID: - description: |- - The base ID to use when allocating shared memory regions. - if Envoy needs to be run multiple times on the same machine, each running Envoy will need a unique base ID - so that the shared memory regions do not conflict. - defaults to 0. - format: int32 - minimum: 0 - type: integer - daemonSet: - description: |- - DaemonSet describes the settings for running envoy as a `DaemonSet`. - if `WorkloadType` is `Deployment`,it's must be nil - properties: - updateStrategy: - description: Strategy describes the deployment strategy to - use to replace existing DaemonSet pods with new pods. - properties: - rollingUpdate: - description: |- - Rolling update config params. Present only if type = "RollingUpdate". - --- - TODO: Update this to follow our convention for oneOf, whatever we decide it - to be. Same as Deployment `strategy.rollingUpdate`. - See https://github.com/kubernetes/kubernetes/issues/35345 - properties: - maxSurge: - anyOf: - - type: integer - - type: string - description: |- - The maximum number of nodes with an existing available DaemonSet pod that - can have an updated DaemonSet pod during during an update. - Value can be an absolute number (ex: 5) or a percentage of desired pods (ex: 10%). - This can not be 0 if MaxUnavailable is 0. - Absolute number is calculated from percentage by rounding up to a minimum of 1. - Default value is 0. - Example: when this is set to 30%, at most 30% of the total number of nodes - that should be running the daemon pod (i.e. status.desiredNumberScheduled) - can have their a new pod created before the old pod is marked as deleted. - The update starts by launching new pods on 30% of nodes. Once an updated - pod is available (Ready for at least minReadySeconds) the old DaemonSet pod - on that node is marked deleted. If the old pod becomes unavailable for any - reason (Ready transitions to false, is evicted, or is drained) an updated - pod is immediatedly created on that node without considering surge limits. - Allowing surge implies the possibility that the resources consumed by the - daemonset on any given node can double if the readiness check fails, and - so resource intensive daemonsets should take into account that they may - cause evictions during disruption. - x-kubernetes-int-or-string: true - maxUnavailable: - anyOf: - - type: integer - - type: string - description: |- - The maximum number of DaemonSet pods that can be unavailable during the - update. Value can be an absolute number (ex: 5) or a percentage of total - number of DaemonSet pods at the start of the update (ex: 10%). Absolute - number is calculated from percentage by rounding up. - This cannot be 0 if MaxSurge is 0 - Default value is 1. - Example: when this is set to 30%, at most 30% of the total number of nodes - that should be running the daemon pod (i.e. status.desiredNumberScheduled) - can have their pods stopped for an update at any given time. The update - starts by stopping at most 30% of those DaemonSet pods and then brings - up new DaemonSet pods in their place. Once the new pods are available, - it then proceeds onto other DaemonSet pods, thus ensuring that at least - 70% of original number of DaemonSet pods are available at all times during - the update. - x-kubernetes-int-or-string: true - type: object - type: - description: Type of daemon set update. Can be "RollingUpdate" - or "OnDelete". Default is RollingUpdate. - type: string - type: object - type: object - deployment: - description: |- - Deployment describes the settings for running envoy as a `Deployment`. - if `WorkloadType` is `DaemonSet`,it's must be nil - properties: - replicas: - description: Replicas is the desired number of replicas. - format: int32 - minimum: 0 - type: integer - strategy: - description: Strategy describes the deployment strategy to - use to replace existing pods with new pods. - properties: - rollingUpdate: - description: |- - Rolling update config params. Present only if DeploymentStrategyType = - RollingUpdate. - --- - TODO: Update this to follow our convention for oneOf, whatever we decide it - to be. - properties: - maxSurge: - anyOf: - - type: integer - - type: string - description: |- - The maximum number of pods that can be scheduled above the desired number of - pods. - Value can be an absolute number (ex: 5) or a percentage of desired pods (ex: 10%). - This can not be 0 if MaxUnavailable is 0. - Absolute number is calculated from percentage by rounding up. - Defaults to 25%. - Example: when this is set to 30%, the new ReplicaSet can be scaled up immediately when - the rolling update starts, such that the total number of old and new pods do not exceed - 130% of desired pods. Once old pods have been killed, - new ReplicaSet can be scaled up further, ensuring that total number of pods running - at any time during the update is at most 130% of desired pods. - x-kubernetes-int-or-string: true - maxUnavailable: - anyOf: - - type: integer - - type: string - description: |- - The maximum number of pods that can be unavailable during the update. - Value can be an absolute number (ex: 5) or a percentage of desired pods (ex: 10%). - Absolute number is calculated from percentage by rounding down. - This can not be 0 if MaxSurge is 0. - Defaults to 25%. - Example: when this is set to 30%, the old ReplicaSet can be scaled down to 70% of desired pods - immediately when the rolling update starts. Once new pods are ready, old ReplicaSet - can be scaled down further, followed by scaling up the new ReplicaSet, ensuring - that the total number of pods available at all times during the update is at - least 70% of desired pods. - x-kubernetes-int-or-string: true - type: object - type: - description: Type of deployment. Can be "Recreate" or - "RollingUpdate". Default is RollingUpdate. - type: string - type: object - type: object - extraVolumeMounts: - description: ExtraVolumeMounts holds the extra volume mounts to - add (normally used with extraVolumes). - items: - description: VolumeMount describes a mounting of a Volume within - a container. - properties: - mountPath: - description: |- - Path within the container at which the volume should be mounted. Must - not contain ':'. - type: string - mountPropagation: - description: |- - mountPropagation determines how mounts are propagated from the host - to container and the other way around. - When not set, MountPropagationNone is used. - This field is beta in 1.10. - When RecursiveReadOnly is set to IfPossible or to Enabled, MountPropagation must be None or unspecified - (which defaults to None). - type: string - name: - description: This must match the Name of a Volume. - type: string - readOnly: - description: |- - Mounted read-only if true, read-write otherwise (false or unspecified). - Defaults to false. - type: boolean - recursiveReadOnly: - description: |- - RecursiveReadOnly specifies whether read-only mounts should be handled - recursively. - If ReadOnly is false, this field has no meaning and must be unspecified. - If ReadOnly is true, and this field is set to Disabled, the mount is not made - recursively read-only. If this field is set to IfPossible, the mount is made - recursively read-only, if it is supported by the container runtime. If this - field is set to Enabled, the mount is made recursively read-only if it is - supported by the container runtime, otherwise the pod will not be started and - an error will be generated to indicate the reason. - If this field is set to IfPossible or Enabled, MountPropagation must be set to - None (or be unspecified, which defaults to None). - If this field is not specified, it is treated as an equivalent of Disabled. - type: string - subPath: - description: |- - Path within the volume from which the container's volume should be mounted. - Defaults to "" (volume's root). - type: string - subPathExpr: - description: |- - Expanded path within the volume from which the container's volume should be mounted. - Behaves similarly to SubPath but environment variable references $(VAR_NAME) are expanded using the container's environment. - Defaults to "" (volume's root). - SubPathExpr and SubPath are mutually exclusive. - type: string - required: - - mountPath - - name - type: object - type: array - extraVolumes: - description: ExtraVolumes holds the extra volumes to add. - items: - description: Volume represents a named volume in a pod that - may be accessed by any container in the pod. - properties: - awsElasticBlockStore: - description: |- - awsElasticBlockStore represents an AWS Disk resource that is attached to a - kubelet's host machine and then exposed to the pod. - More info: https://kubernetes.io/docs/concepts/storage/volumes#awselasticblockstore - properties: - fsType: - description: |- - fsType is the filesystem type of the volume that you want to mount. - Tip: Ensure that the filesystem type is supported by the host operating system. - Examples: "ext4", "xfs", "ntfs". Implicitly inferred to be "ext4" if unspecified. - More info: https://kubernetes.io/docs/concepts/storage/volumes#awselasticblockstore - TODO: how do we prevent errors in the filesystem from compromising the machine - type: string - partition: - description: |- - partition is the partition in the volume that you want to mount. - If omitted, the default is to mount by volume name. - Examples: For volume /dev/sda1, you specify the partition as "1". - Similarly, the volume partition for /dev/sda is "0" (or you can leave the property empty). - format: int32 - type: integer - readOnly: - description: |- - readOnly value true will force the readOnly setting in VolumeMounts. - More info: https://kubernetes.io/docs/concepts/storage/volumes#awselasticblockstore - type: boolean - volumeID: - description: |- - volumeID is unique ID of the persistent disk resource in AWS (Amazon EBS volume). - More info: https://kubernetes.io/docs/concepts/storage/volumes#awselasticblockstore - type: string - required: - - volumeID - type: object - azureDisk: - description: azureDisk represents an Azure Data Disk mount - on the host and bind mount to the pod. - properties: - cachingMode: - description: 'cachingMode is the Host Caching mode: - None, Read Only, Read Write.' - type: string - diskName: - description: diskName is the Name of the data disk in - the blob storage - type: string - diskURI: - description: diskURI is the URI of data disk in the - blob storage - type: string - fsType: - description: |- - fsType is Filesystem type to mount. - Must be a filesystem type supported by the host operating system. - Ex. "ext4", "xfs", "ntfs". Implicitly inferred to be "ext4" if unspecified. - type: string - kind: - description: 'kind expected values are Shared: multiple - blob disks per storage account Dedicated: single - blob disk per storage account Managed: azure managed - data disk (only in managed availability set). defaults - to shared' - type: string - readOnly: - description: |- - readOnly Defaults to false (read/write). ReadOnly here will force - the ReadOnly setting in VolumeMounts. - type: boolean - required: - - diskName - - diskURI - type: object - azureFile: - description: azureFile represents an Azure File Service - mount on the host and bind mount to the pod. - properties: - readOnly: - description: |- - readOnly defaults to false (read/write). ReadOnly here will force - the ReadOnly setting in VolumeMounts. - type: boolean - secretName: - description: secretName is the name of secret that - contains Azure Storage Account Name and Key - type: string - shareName: - description: shareName is the azure share Name - type: string - required: - - secretName - - shareName - type: object - cephfs: - description: cephFS represents a Ceph FS mount on the host - that shares a pod's lifetime - properties: - monitors: - description: |- - monitors is Required: Monitors is a collection of Ceph monitors - More info: https://examples.k8s.io/volumes/cephfs/README.md#how-to-use-it - items: - type: string - type: array - x-kubernetes-list-type: atomic - path: - description: 'path is Optional: Used as the mounted - root, rather than the full Ceph tree, default is /' - type: string - readOnly: - description: |- - readOnly is Optional: Defaults to false (read/write). ReadOnly here will force - the ReadOnly setting in VolumeMounts. - More info: https://examples.k8s.io/volumes/cephfs/README.md#how-to-use-it - type: boolean - secretFile: - description: |- - secretFile is Optional: SecretFile is the path to key ring for User, default is /etc/ceph/user.secret - More info: https://examples.k8s.io/volumes/cephfs/README.md#how-to-use-it - type: string - secretRef: - description: |- - secretRef is Optional: SecretRef is reference to the authentication secret for User, default is empty. - More info: https://examples.k8s.io/volumes/cephfs/README.md#how-to-use-it - properties: - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - TODO: Add other useful fields. apiVersion, kind, uid? - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - TODO: Drop `kubebuilder:default` when controller-gen doesn't need it https://github.com/kubernetes-sigs/kubebuilder/issues/3896. - type: string - type: object - x-kubernetes-map-type: atomic - user: - description: |- - user is optional: User is the rados user name, default is admin - More info: https://examples.k8s.io/volumes/cephfs/README.md#how-to-use-it - type: string - required: - - monitors - type: object - cinder: - description: |- - cinder represents a cinder volume attached and mounted on kubelets host machine. - More info: https://examples.k8s.io/mysql-cinder-pd/README.md - properties: - fsType: - description: |- - fsType is the filesystem type to mount. - Must be a filesystem type supported by the host operating system. - Examples: "ext4", "xfs", "ntfs". Implicitly inferred to be "ext4" if unspecified. - More info: https://examples.k8s.io/mysql-cinder-pd/README.md - type: string - readOnly: - description: |- - readOnly defaults to false (read/write). ReadOnly here will force - the ReadOnly setting in VolumeMounts. - More info: https://examples.k8s.io/mysql-cinder-pd/README.md - type: boolean - secretRef: - description: |- - secretRef is optional: points to a secret object containing parameters used to connect - to OpenStack. - properties: - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - TODO: Add other useful fields. apiVersion, kind, uid? - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - TODO: Drop `kubebuilder:default` when controller-gen doesn't need it https://github.com/kubernetes-sigs/kubebuilder/issues/3896. - type: string - type: object - x-kubernetes-map-type: atomic - volumeID: - description: |- - volumeID used to identify the volume in cinder. - More info: https://examples.k8s.io/mysql-cinder-pd/README.md - type: string - required: - - volumeID - type: object - configMap: - description: configMap represents a configMap that should - populate this volume - properties: - defaultMode: - description: |- - defaultMode is optional: mode bits used to set permissions on created files by default. - Must be an octal value between 0000 and 0777 or a decimal value between 0 and 511. - YAML accepts both octal and decimal values, JSON requires decimal values for mode bits. - Defaults to 0644. - Directories within the path are not affected by this setting. - This might be in conflict with other options that affect the file - mode, like fsGroup, and the result can be other mode bits set. - format: int32 - type: integer - items: - description: |- - items if unspecified, each key-value pair in the Data field of the referenced - ConfigMap will be projected into the volume as a file whose name is the - key and content is the value. If specified, the listed keys will be - projected into the specified paths, and unlisted keys will not be - present. If a key is specified which is not present in the ConfigMap, - the volume setup will error unless it is marked optional. Paths must be - relative and may not contain the '..' path or start with '..'. - items: - description: Maps a string key to a path within a - volume. - properties: - key: - description: key is the key to project. - type: string - mode: - description: |- - mode is Optional: mode bits used to set permissions on this file. - Must be an octal value between 0000 and 0777 or a decimal value between 0 and 511. - YAML accepts both octal and decimal values, JSON requires decimal values for mode bits. - If not specified, the volume defaultMode will be used. - This might be in conflict with other options that affect the file - mode, like fsGroup, and the result can be other mode bits set. - format: int32 - type: integer - path: - description: |- - path is the relative path of the file to map the key to. - May not be an absolute path. - May not contain the path element '..'. - May not start with the string '..'. - type: string - required: - - key - - path - type: object - type: array - x-kubernetes-list-type: atomic - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - TODO: Add other useful fields. apiVersion, kind, uid? - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - TODO: Drop `kubebuilder:default` when controller-gen doesn't need it https://github.com/kubernetes-sigs/kubebuilder/issues/3896. - type: string - optional: - description: optional specify whether the ConfigMap - or its keys must be defined - type: boolean - type: object - x-kubernetes-map-type: atomic - csi: - description: csi (Container Storage Interface) represents - ephemeral storage that is handled by certain external - CSI drivers (Beta feature). - properties: - driver: - description: |- - driver is the name of the CSI driver that handles this volume. - Consult with your admin for the correct name as registered in the cluster. - type: string - fsType: - description: |- - fsType to mount. Ex. "ext4", "xfs", "ntfs". - If not provided, the empty value is passed to the associated CSI driver - which will determine the default filesystem to apply. - type: string - nodePublishSecretRef: - description: |- - nodePublishSecretRef is a reference to the secret object containing - sensitive information to pass to the CSI driver to complete the CSI - NodePublishVolume and NodeUnpublishVolume calls. - This field is optional, and may be empty if no secret is required. If the - secret object contains more than one secret, all secret references are passed. - properties: - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - TODO: Add other useful fields. apiVersion, kind, uid? - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - TODO: Drop `kubebuilder:default` when controller-gen doesn't need it https://github.com/kubernetes-sigs/kubebuilder/issues/3896. - type: string - type: object - x-kubernetes-map-type: atomic - readOnly: - description: |- - readOnly specifies a read-only configuration for the volume. - Defaults to false (read/write). - type: boolean - volumeAttributes: - additionalProperties: - type: string - description: |- - volumeAttributes stores driver-specific properties that are passed to the CSI - driver. Consult your driver's documentation for supported values. - type: object - required: - - driver - type: object - downwardAPI: - description: downwardAPI represents downward API about the - pod that should populate this volume - properties: - defaultMode: - description: |- - Optional: mode bits to use on created files by default. Must be a - Optional: mode bits used to set permissions on created files by default. - Must be an octal value between 0000 and 0777 or a decimal value between 0 and 511. - YAML accepts both octal and decimal values, JSON requires decimal values for mode bits. - Defaults to 0644. - Directories within the path are not affected by this setting. - This might be in conflict with other options that affect the file - mode, like fsGroup, and the result can be other mode bits set. - format: int32 - type: integer - items: - description: Items is a list of downward API volume - file - items: - description: DownwardAPIVolumeFile represents information - to create the file containing the pod field - properties: - fieldRef: - description: 'Required: Selects a field of the - pod: only annotations, labels, name, namespace - and uid are supported.' - properties: - apiVersion: - description: Version of the schema the FieldPath - is written in terms of, defaults to "v1". - type: string - fieldPath: - description: Path of the field to select in - the specified API version. - type: string - required: - - fieldPath - type: object - x-kubernetes-map-type: atomic - mode: - description: |- - Optional: mode bits used to set permissions on this file, must be an octal value - between 0000 and 0777 or a decimal value between 0 and 511. - YAML accepts both octal and decimal values, JSON requires decimal values for mode bits. - If not specified, the volume defaultMode will be used. - This might be in conflict with other options that affect the file - mode, like fsGroup, and the result can be other mode bits set. - format: int32 - type: integer - path: - description: 'Required: Path is the relative - path name of the file to be created. Must not - be absolute or contain the ''..'' path. Must - be utf-8 encoded. The first item of the relative - path must not start with ''..''' - type: string - resourceFieldRef: - description: |- - Selects a resource of the container: only resources limits and requests - (limits.cpu, limits.memory, requests.cpu and requests.memory) are currently supported. - properties: - containerName: - description: 'Container name: required for - volumes, optional for env vars' - type: string - divisor: - anyOf: - - type: integer - - type: string - description: Specifies the output format of - the exposed resources, defaults to "1" - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - resource: - description: 'Required: resource to select' - type: string - required: - - resource - type: object - x-kubernetes-map-type: atomic - required: - - path - type: object - type: array - x-kubernetes-list-type: atomic - type: object - emptyDir: - description: |- - emptyDir represents a temporary directory that shares a pod's lifetime. - More info: https://kubernetes.io/docs/concepts/storage/volumes#emptydir - properties: - medium: - description: |- - medium represents what type of storage medium should back this directory. - The default is "" which means to use the node's default medium. - Must be an empty string (default) or Memory. - More info: https://kubernetes.io/docs/concepts/storage/volumes#emptydir - type: string - sizeLimit: - anyOf: - - type: integer - - type: string - description: |- - sizeLimit is the total amount of local storage required for this EmptyDir volume. - The size limit is also applicable for memory medium. - The maximum usage on memory medium EmptyDir would be the minimum value between - the SizeLimit specified here and the sum of memory limits of all containers in a pod. - The default is nil which means that the limit is undefined. - More info: https://kubernetes.io/docs/concepts/storage/volumes#emptydir - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - type: object - ephemeral: - description: |- - ephemeral represents a volume that is handled by a cluster storage driver. - The volume's lifecycle is tied to the pod that defines it - it will be created before the pod starts, - and deleted when the pod is removed. - Use this if: - a) the volume is only needed while the pod runs, - b) features of normal volumes like restoring from snapshot or capacity - tracking are needed, - c) the storage driver is specified through a storage class, and - d) the storage driver supports dynamic volume provisioning through - a PersistentVolumeClaim (see EphemeralVolumeSource for more - information on the connection between this volume type - and PersistentVolumeClaim). - Use PersistentVolumeClaim or one of the vendor-specific - APIs for volumes that persist for longer than the lifecycle - of an individual pod. - Use CSI for light-weight local ephemeral volumes if the CSI driver is meant to - be used that way - see the documentation of the driver for - more information. - A pod can use both types of ephemeral volumes and - persistent volumes at the same time. - properties: - volumeClaimTemplate: - description: |- - Will be used to create a stand-alone PVC to provision the volume. - The pod in which this EphemeralVolumeSource is embedded will be the - owner of the PVC, i.e. the PVC will be deleted together with the - pod. The name of the PVC will be `-` where - `` is the name from the `PodSpec.Volumes` array - entry. Pod validation will reject the pod if the concatenated name - is not valid for a PVC (for example, too long). - An existing PVC with that name that is not owned by the pod - will *not* be used for the pod to avoid using an unrelated - volume by mistake. Starting the pod is then blocked until - the unrelated PVC is removed. If such a pre-created PVC is - meant to be used by the pod, the PVC has to updated with an - owner reference to the pod once the pod exists. Normally - this should not be necessary, but it may be useful when - manually reconstructing a broken cluster. - This field is read-only and no changes will be made by Kubernetes - to the PVC after it has been created. - Required, must not be nil. - properties: - metadata: - description: |- - May contain labels and annotations that will be copied into the PVC - when creating it. No other fields are allowed and will be rejected during - validation. - type: object - spec: - description: |- - The specification for the PersistentVolumeClaim. The entire content is - copied unchanged into the PVC that gets created from this - template. The same fields as in a PersistentVolumeClaim - are also valid here. - properties: - accessModes: - description: |- - accessModes contains the desired access modes the volume should have. - More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#access-modes-1 - items: - type: string - type: array - x-kubernetes-list-type: atomic - dataSource: - description: |- - dataSource field can be used to specify either: - * An existing VolumeSnapshot object (snapshot.storage.k8s.io/VolumeSnapshot) - * An existing PVC (PersistentVolumeClaim) - If the provisioner or an external controller can support the specified data source, - it will create a new volume based on the contents of the specified data source. - When the AnyVolumeDataSource feature gate is enabled, dataSource contents will be copied to dataSourceRef, - and dataSourceRef contents will be copied to dataSource when dataSourceRef.namespace is not specified. - If the namespace is specified, then dataSourceRef will not be copied to dataSource. - properties: - apiGroup: - description: |- - APIGroup is the group for the resource being referenced. - If APIGroup is not specified, the specified Kind must be in the core API group. - For any other third-party types, APIGroup is required. - type: string - kind: - description: Kind is the type of resource - being referenced - type: string - name: - description: Name is the name of resource - being referenced - type: string - required: - - kind - - name - type: object - x-kubernetes-map-type: atomic - dataSourceRef: - description: |- - dataSourceRef specifies the object from which to populate the volume with data, if a non-empty - volume is desired. This may be any object from a non-empty API group (non - core object) or a PersistentVolumeClaim object. - When this field is specified, volume binding will only succeed if the type of - the specified object matches some installed volume populator or dynamic - provisioner. - This field will replace the functionality of the dataSource field and as such - if both fields are non-empty, they must have the same value. For backwards - compatibility, when namespace isn't specified in dataSourceRef, - both fields (dataSource and dataSourceRef) will be set to the same - value automatically if one of them is empty and the other is non-empty. - When namespace is specified in dataSourceRef, - dataSource isn't set to the same value and must be empty. - There are three important differences between dataSource and dataSourceRef: - * While dataSource only allows two specific types of objects, dataSourceRef - allows any non-core object, as well as PersistentVolumeClaim objects. - * While dataSource ignores disallowed values (dropping them), dataSourceRef - preserves all values, and generates an error if a disallowed value is - specified. - * While dataSource only allows local objects, dataSourceRef allows objects - in any namespaces. - (Beta) Using this field requires the AnyVolumeDataSource feature gate to be enabled. - (Alpha) Using the namespace field of dataSourceRef requires the CrossNamespaceVolumeDataSource feature gate to be enabled. - properties: - apiGroup: - description: |- - APIGroup is the group for the resource being referenced. - If APIGroup is not specified, the specified Kind must be in the core API group. - For any other third-party types, APIGroup is required. - type: string - kind: - description: Kind is the type of resource - being referenced - type: string - name: - description: Name is the name of resource - being referenced - type: string - namespace: - description: |- - Namespace is the namespace of resource being referenced - Note that when a namespace is specified, a gateway.networking.k8s.io/ReferenceGrant object is required in the referent namespace to allow that namespace's owner to accept the reference. See the ReferenceGrant documentation for details. - (Alpha) This field requires the CrossNamespaceVolumeDataSource feature gate to be enabled. - type: string - required: - - kind - - name - type: object - resources: - description: |- - resources represents the minimum resources the volume should have. - If RecoverVolumeExpansionFailure feature is enabled users are allowed to specify resource requirements - that are lower than previous value but must still be higher than capacity recorded in the - status field of the claim. - More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#resources - properties: - limits: - additionalProperties: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - description: |- - Limits describes the maximum amount of compute resources allowed. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ - type: object - requests: - additionalProperties: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - description: |- - Requests describes the minimum amount of compute resources required. - If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, - otherwise to an implementation-defined value. Requests cannot exceed Limits. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ - type: object - type: object - selector: - description: selector is a label query over - volumes to consider for binding. - properties: - matchExpressions: - description: matchExpressions is a list - of label selector requirements. The requirements - are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key - that the selector applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - storageClassName: - description: |- - storageClassName is the name of the StorageClass required by the claim. - More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#class-1 - type: string - volumeAttributesClassName: - description: |- - volumeAttributesClassName may be used to set the VolumeAttributesClass used by this claim. - If specified, the CSI driver will create or update the volume with the attributes defined - in the corresponding VolumeAttributesClass. This has a different purpose than storageClassName, - it can be changed after the claim is created. An empty string value means that no VolumeAttributesClass - will be applied to the claim but it's not allowed to reset this field to empty string once it is set. - If unspecified and the PersistentVolumeClaim is unbound, the default VolumeAttributesClass - will be set by the persistentvolume controller if it exists. - If the resource referred to by volumeAttributesClass does not exist, this PersistentVolumeClaim will be - set to a Pending state, as reflected by the modifyVolumeStatus field, until such as a resource - exists. - More info: https://kubernetes.io/docs/concepts/storage/volume-attributes-classes/ - (Alpha) Using this field requires the VolumeAttributesClass feature gate to be enabled. - type: string - volumeMode: - description: |- - volumeMode defines what type of volume is required by the claim. - Value of Filesystem is implied when not included in claim spec. - type: string - volumeName: - description: volumeName is the binding reference - to the PersistentVolume backing this claim. - type: string - type: object - required: - - spec - type: object - type: object - fc: - description: fc represents a Fibre Channel resource that - is attached to a kubelet's host machine and then exposed - to the pod. - properties: - fsType: - description: |- - fsType is the filesystem type to mount. - Must be a filesystem type supported by the host operating system. - Ex. "ext4", "xfs", "ntfs". Implicitly inferred to be "ext4" if unspecified. - TODO: how do we prevent errors in the filesystem from compromising the machine - type: string - lun: - description: 'lun is Optional: FC target lun number' - format: int32 - type: integer - readOnly: - description: |- - readOnly is Optional: Defaults to false (read/write). ReadOnly here will force - the ReadOnly setting in VolumeMounts. - type: boolean - targetWWNs: - description: 'targetWWNs is Optional: FC target worldwide - names (WWNs)' - items: - type: string - type: array - x-kubernetes-list-type: atomic - wwids: - description: |- - wwids Optional: FC volume world wide identifiers (wwids) - Either wwids or combination of targetWWNs and lun must be set, but not both simultaneously. - items: - type: string - type: array - x-kubernetes-list-type: atomic - type: object - flexVolume: - description: |- - flexVolume represents a generic volume resource that is - provisioned/attached using an exec based plugin. - properties: - driver: - description: driver is the name of the driver to use - for this volume. - type: string - fsType: - description: |- - fsType is the filesystem type to mount. - Must be a filesystem type supported by the host operating system. - Ex. "ext4", "xfs", "ntfs". The default filesystem depends on FlexVolume script. - type: string - options: - additionalProperties: - type: string - description: 'options is Optional: this field holds - extra command options if any.' - type: object - readOnly: - description: |- - readOnly is Optional: defaults to false (read/write). ReadOnly here will force - the ReadOnly setting in VolumeMounts. - type: boolean - secretRef: - description: |- - secretRef is Optional: secretRef is reference to the secret object containing - sensitive information to pass to the plugin scripts. This may be - empty if no secret object is specified. If the secret object - contains more than one secret, all secrets are passed to the plugin - scripts. - properties: - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - TODO: Add other useful fields. apiVersion, kind, uid? - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - TODO: Drop `kubebuilder:default` when controller-gen doesn't need it https://github.com/kubernetes-sigs/kubebuilder/issues/3896. - type: string - type: object - x-kubernetes-map-type: atomic - required: - - driver - type: object - flocker: - description: flocker represents a Flocker volume attached - to a kubelet's host machine. This depends on the Flocker - control service being running - properties: - datasetName: - description: |- - datasetName is Name of the dataset stored as metadata -> name on the dataset for Flocker - should be considered as deprecated - type: string - datasetUUID: - description: datasetUUID is the UUID of the dataset. - This is unique identifier of a Flocker dataset - type: string - type: object - gcePersistentDisk: - description: |- - gcePersistentDisk represents a GCE Disk resource that is attached to a - kubelet's host machine and then exposed to the pod. - More info: https://kubernetes.io/docs/concepts/storage/volumes#gcepersistentdisk - properties: - fsType: - description: |- - fsType is filesystem type of the volume that you want to mount. - Tip: Ensure that the filesystem type is supported by the host operating system. - Examples: "ext4", "xfs", "ntfs". Implicitly inferred to be "ext4" if unspecified. - More info: https://kubernetes.io/docs/concepts/storage/volumes#gcepersistentdisk - TODO: how do we prevent errors in the filesystem from compromising the machine - type: string - partition: - description: |- - partition is the partition in the volume that you want to mount. - If omitted, the default is to mount by volume name. - Examples: For volume /dev/sda1, you specify the partition as "1". - Similarly, the volume partition for /dev/sda is "0" (or you can leave the property empty). - More info: https://kubernetes.io/docs/concepts/storage/volumes#gcepersistentdisk - format: int32 - type: integer - pdName: - description: |- - pdName is unique name of the PD resource in GCE. Used to identify the disk in GCE. - More info: https://kubernetes.io/docs/concepts/storage/volumes#gcepersistentdisk - type: string - readOnly: - description: |- - readOnly here will force the ReadOnly setting in VolumeMounts. - Defaults to false. - More info: https://kubernetes.io/docs/concepts/storage/volumes#gcepersistentdisk - type: boolean - required: - - pdName - type: object - gitRepo: - description: |- - gitRepo represents a git repository at a particular revision. - DEPRECATED: GitRepo is deprecated. To provision a container with a git repo, mount an - EmptyDir into an InitContainer that clones the repo using git, then mount the EmptyDir - into the Pod's container. - properties: - directory: - description: |- - directory is the target directory name. - Must not contain or start with '..'. If '.' is supplied, the volume directory will be the - git repository. Otherwise, if specified, the volume will contain the git repository in - the subdirectory with the given name. - type: string - repository: - description: repository is the URL - type: string - revision: - description: revision is the commit hash for the specified - revision. - type: string - required: - - repository - type: object - glusterfs: - description: |- - glusterfs represents a Glusterfs mount on the host that shares a pod's lifetime. - More info: https://examples.k8s.io/volumes/glusterfs/README.md - properties: - endpoints: - description: |- - endpoints is the endpoint name that details Glusterfs topology. - More info: https://examples.k8s.io/volumes/glusterfs/README.md#create-a-pod - type: string - path: - description: |- - path is the Glusterfs volume path. - More info: https://examples.k8s.io/volumes/glusterfs/README.md#create-a-pod - type: string - readOnly: - description: |- - readOnly here will force the Glusterfs volume to be mounted with read-only permissions. - Defaults to false. - More info: https://examples.k8s.io/volumes/glusterfs/README.md#create-a-pod - type: boolean - required: - - endpoints - - path - type: object - hostPath: - description: |- - hostPath represents a pre-existing file or directory on the host - machine that is directly exposed to the container. This is generally - used for system agents or other privileged things that are allowed - to see the host machine. Most containers will NOT need this. - More info: https://kubernetes.io/docs/concepts/storage/volumes#hostpath - --- - TODO(jonesdl) We need to restrict who can use host directory mounts and who can/can not - mount host directories as read/write. - properties: - path: - description: |- - path of the directory on the host. - If the path is a symlink, it will follow the link to the real path. - More info: https://kubernetes.io/docs/concepts/storage/volumes#hostpath - type: string - type: - description: |- - type for HostPath Volume - Defaults to "" - More info: https://kubernetes.io/docs/concepts/storage/volumes#hostpath - type: string - required: - - path - type: object - iscsi: - description: |- - iscsi represents an ISCSI Disk resource that is attached to a - kubelet's host machine and then exposed to the pod. - More info: https://examples.k8s.io/volumes/iscsi/README.md - properties: - chapAuthDiscovery: - description: chapAuthDiscovery defines whether support - iSCSI Discovery CHAP authentication - type: boolean - chapAuthSession: - description: chapAuthSession defines whether support - iSCSI Session CHAP authentication - type: boolean - fsType: - description: |- - fsType is the filesystem type of the volume that you want to mount. - Tip: Ensure that the filesystem type is supported by the host operating system. - Examples: "ext4", "xfs", "ntfs". Implicitly inferred to be "ext4" if unspecified. - More info: https://kubernetes.io/docs/concepts/storage/volumes#iscsi - TODO: how do we prevent errors in the filesystem from compromising the machine - type: string - initiatorName: - description: |- - initiatorName is the custom iSCSI Initiator Name. - If initiatorName is specified with iscsiInterface simultaneously, new iSCSI interface - : will be created for the connection. - type: string - iqn: - description: iqn is the target iSCSI Qualified Name. - type: string - iscsiInterface: - description: |- - iscsiInterface is the interface Name that uses an iSCSI transport. - Defaults to 'default' (tcp). - type: string - lun: - description: lun represents iSCSI Target Lun number. - format: int32 - type: integer - portals: - description: |- - portals is the iSCSI Target Portal List. The portal is either an IP or ip_addr:port if the port - is other than default (typically TCP ports 860 and 3260). - items: - type: string - type: array - x-kubernetes-list-type: atomic - readOnly: - description: |- - readOnly here will force the ReadOnly setting in VolumeMounts. - Defaults to false. - type: boolean - secretRef: - description: secretRef is the CHAP Secret for iSCSI - target and initiator authentication - properties: - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - TODO: Add other useful fields. apiVersion, kind, uid? - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - TODO: Drop `kubebuilder:default` when controller-gen doesn't need it https://github.com/kubernetes-sigs/kubebuilder/issues/3896. - type: string - type: object - x-kubernetes-map-type: atomic - targetPortal: - description: |- - targetPortal is iSCSI Target Portal. The Portal is either an IP or ip_addr:port if the port - is other than default (typically TCP ports 860 and 3260). - type: string - required: - - iqn - - lun - - targetPortal - type: object - name: - description: |- - name of the volume. - Must be a DNS_LABEL and unique within the pod. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - type: string - nfs: - description: |- - nfs represents an NFS mount on the host that shares a pod's lifetime - More info: https://kubernetes.io/docs/concepts/storage/volumes#nfs - properties: - path: - description: |- - path that is exported by the NFS server. - More info: https://kubernetes.io/docs/concepts/storage/volumes#nfs - type: string - readOnly: - description: |- - readOnly here will force the NFS export to be mounted with read-only permissions. - Defaults to false. - More info: https://kubernetes.io/docs/concepts/storage/volumes#nfs - type: boolean - server: - description: |- - server is the hostname or IP address of the NFS server. - More info: https://kubernetes.io/docs/concepts/storage/volumes#nfs - type: string - required: - - path - - server - type: object - persistentVolumeClaim: - description: |- - persistentVolumeClaimVolumeSource represents a reference to a - PersistentVolumeClaim in the same namespace. - More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#persistentvolumeclaims - properties: - claimName: - description: |- - claimName is the name of a PersistentVolumeClaim in the same namespace as the pod using this volume. - More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#persistentvolumeclaims - type: string - readOnly: - description: |- - readOnly Will force the ReadOnly setting in VolumeMounts. - Default false. - type: boolean - required: - - claimName - type: object - photonPersistentDisk: - description: photonPersistentDisk represents a PhotonController - persistent disk attached and mounted on kubelets host - machine - properties: - fsType: - description: |- - fsType is the filesystem type to mount. - Must be a filesystem type supported by the host operating system. - Ex. "ext4", "xfs", "ntfs". Implicitly inferred to be "ext4" if unspecified. - type: string - pdID: - description: pdID is the ID that identifies Photon Controller - persistent disk - type: string - required: - - pdID - type: object - portworxVolume: - description: portworxVolume represents a portworx volume - attached and mounted on kubelets host machine - properties: - fsType: - description: |- - fSType represents the filesystem type to mount - Must be a filesystem type supported by the host operating system. - Ex. "ext4", "xfs". Implicitly inferred to be "ext4" if unspecified. - type: string - readOnly: - description: |- - readOnly defaults to false (read/write). ReadOnly here will force - the ReadOnly setting in VolumeMounts. - type: boolean - volumeID: - description: volumeID uniquely identifies a Portworx - volume - type: string - required: - - volumeID - type: object - projected: - description: projected items for all in one resources secrets, - configmaps, and downward API - properties: - defaultMode: - description: |- - defaultMode are the mode bits used to set permissions on created files by default. - Must be an octal value between 0000 and 0777 or a decimal value between 0 and 511. - YAML accepts both octal and decimal values, JSON requires decimal values for mode bits. - Directories within the path are not affected by this setting. - This might be in conflict with other options that affect the file - mode, like fsGroup, and the result can be other mode bits set. - format: int32 - type: integer - sources: - description: sources is the list of volume projections - items: - description: Projection that may be projected along - with other supported volume types - properties: - clusterTrustBundle: - description: |- - ClusterTrustBundle allows a pod to access the `.spec.trustBundle` field - of ClusterTrustBundle objects in an auto-updating file. - Alpha, gated by the ClusterTrustBundleProjection feature gate. - ClusterTrustBundle objects can either be selected by name, or by the - combination of signer name and a label selector. - Kubelet performs aggressive normalization of the PEM contents written - into the pod filesystem. Esoteric PEM features such as inter-block - comments and block headers are stripped. Certificates are deduplicated. - The ordering of certificates within the file is arbitrary, and Kubelet - may change the order over time. - properties: - labelSelector: - description: |- - Select all ClusterTrustBundles that match this label selector. Only has - effect if signerName is set. Mutually-exclusive with name. If unset, - interpreted as "match nothing". If set but empty, interpreted as "match - everything". - properties: - matchExpressions: - description: matchExpressions is a list - of label selector requirements. The - requirements are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key - that the selector applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - name: - description: |- - Select a single ClusterTrustBundle by object name. Mutually-exclusive - with signerName and labelSelector. - type: string - optional: - description: |- - If true, don't block pod startup if the referenced ClusterTrustBundle(s) - aren't available. If using name, then the named ClusterTrustBundle is - allowed not to exist. If using signerName, then the combination of - signerName and labelSelector is allowed to match zero - ClusterTrustBundles. - type: boolean - path: - description: Relative path from the volume - root to write the bundle. - type: string - signerName: - description: |- - Select all ClusterTrustBundles that match this signer name. - Mutually-exclusive with name. The contents of all selected - ClusterTrustBundles will be unified and deduplicated. - type: string - required: - - path - type: object - configMap: - description: configMap information about the configMap - data to project - properties: - items: - description: |- - items if unspecified, each key-value pair in the Data field of the referenced - ConfigMap will be projected into the volume as a file whose name is the - key and content is the value. If specified, the listed keys will be - projected into the specified paths, and unlisted keys will not be - present. If a key is specified which is not present in the ConfigMap, - the volume setup will error unless it is marked optional. Paths must be - relative and may not contain the '..' path or start with '..'. - items: - description: Maps a string key to a path - within a volume. - properties: - key: - description: key is the key to project. - type: string - mode: - description: |- - mode is Optional: mode bits used to set permissions on this file. - Must be an octal value between 0000 and 0777 or a decimal value between 0 and 511. - YAML accepts both octal and decimal values, JSON requires decimal values for mode bits. - If not specified, the volume defaultMode will be used. - This might be in conflict with other options that affect the file - mode, like fsGroup, and the result can be other mode bits set. - format: int32 - type: integer - path: - description: |- - path is the relative path of the file to map the key to. - May not be an absolute path. - May not contain the path element '..'. - May not start with the string '..'. - type: string - required: - - key - - path - type: object - type: array - x-kubernetes-list-type: atomic - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - TODO: Add other useful fields. apiVersion, kind, uid? - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - TODO: Drop `kubebuilder:default` when controller-gen doesn't need it https://github.com/kubernetes-sigs/kubebuilder/issues/3896. - type: string - optional: - description: optional specify whether the - ConfigMap or its keys must be defined - type: boolean - type: object - x-kubernetes-map-type: atomic - downwardAPI: - description: downwardAPI information about the - downwardAPI data to project - properties: - items: - description: Items is a list of DownwardAPIVolume - file - items: - description: DownwardAPIVolumeFile represents - information to create the file containing - the pod field - properties: - fieldRef: - description: 'Required: Selects a field - of the pod: only annotations, labels, - name, namespace and uid are supported.' - properties: - apiVersion: - description: Version of the schema - the FieldPath is written in terms - of, defaults to "v1". - type: string - fieldPath: - description: Path of the field to - select in the specified API version. - type: string - required: - - fieldPath - type: object - x-kubernetes-map-type: atomic - mode: - description: |- - Optional: mode bits used to set permissions on this file, must be an octal value - between 0000 and 0777 or a decimal value between 0 and 511. - YAML accepts both octal and decimal values, JSON requires decimal values for mode bits. - If not specified, the volume defaultMode will be used. - This might be in conflict with other options that affect the file - mode, like fsGroup, and the result can be other mode bits set. - format: int32 - type: integer - path: - description: 'Required: Path is the - relative path name of the file to - be created. Must not be absolute or - contain the ''..'' path. Must be utf-8 - encoded. The first item of the relative - path must not start with ''..''' - type: string - resourceFieldRef: - description: |- - Selects a resource of the container: only resources limits and requests - (limits.cpu, limits.memory, requests.cpu and requests.memory) are currently supported. - properties: - containerName: - description: 'Container name: required - for volumes, optional for env - vars' - type: string - divisor: - anyOf: - - type: integer - - type: string - description: Specifies the output - format of the exposed resources, - defaults to "1" - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - resource: - description: 'Required: resource - to select' - type: string - required: - - resource - type: object - x-kubernetes-map-type: atomic - required: - - path - type: object - type: array - x-kubernetes-list-type: atomic - type: object - secret: - description: secret information about the secret - data to project - properties: - items: - description: |- - items if unspecified, each key-value pair in the Data field of the referenced - Secret will be projected into the volume as a file whose name is the - key and content is the value. If specified, the listed keys will be - projected into the specified paths, and unlisted keys will not be - present. If a key is specified which is not present in the Secret, - the volume setup will error unless it is marked optional. Paths must be - relative and may not contain the '..' path or start with '..'. - items: - description: Maps a string key to a path - within a volume. - properties: - key: - description: key is the key to project. - type: string - mode: - description: |- - mode is Optional: mode bits used to set permissions on this file. - Must be an octal value between 0000 and 0777 or a decimal value between 0 and 511. - YAML accepts both octal and decimal values, JSON requires decimal values for mode bits. - If not specified, the volume defaultMode will be used. - This might be in conflict with other options that affect the file - mode, like fsGroup, and the result can be other mode bits set. - format: int32 - type: integer - path: - description: |- - path is the relative path of the file to map the key to. - May not be an absolute path. - May not contain the path element '..'. - May not start with the string '..'. - type: string - required: - - key - - path - type: object - type: array - x-kubernetes-list-type: atomic - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - TODO: Add other useful fields. apiVersion, kind, uid? - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - TODO: Drop `kubebuilder:default` when controller-gen doesn't need it https://github.com/kubernetes-sigs/kubebuilder/issues/3896. - type: string - optional: - description: optional field specify whether - the Secret or its key must be defined - type: boolean - type: object - x-kubernetes-map-type: atomic - serviceAccountToken: - description: serviceAccountToken is information - about the serviceAccountToken data to project - properties: - audience: - description: |- - audience is the intended audience of the token. A recipient of a token - must identify itself with an identifier specified in the audience of the - token, and otherwise should reject the token. The audience defaults to the - identifier of the apiserver. - type: string - expirationSeconds: - description: |- - expirationSeconds is the requested duration of validity of the service - account token. As the token approaches expiration, the kubelet volume - plugin will proactively rotate the service account token. The kubelet will - start trying to rotate the token if the token is older than 80 percent of - its time to live or if the token is older than 24 hours.Defaults to 1 hour - and must be at least 10 minutes. - format: int64 - type: integer - path: - description: |- - path is the path relative to the mount point of the file to project the - token into. - type: string - required: - - path - type: object - type: object - type: array - x-kubernetes-list-type: atomic - type: object - quobyte: - description: quobyte represents a Quobyte mount on the host - that shares a pod's lifetime - properties: - group: - description: |- - group to map volume access to - Default is no group - type: string - readOnly: - description: |- - readOnly here will force the Quobyte volume to be mounted with read-only permissions. - Defaults to false. - type: boolean - registry: - description: |- - registry represents a single or multiple Quobyte Registry services - specified as a string as host:port pair (multiple entries are separated with commas) - which acts as the central registry for volumes - type: string - tenant: - description: |- - tenant owning the given Quobyte volume in the Backend - Used with dynamically provisioned Quobyte volumes, value is set by the plugin - type: string - user: - description: |- - user to map volume access to - Defaults to serivceaccount user - type: string - volume: - description: volume is a string that references an already - created Quobyte volume by name. - type: string - required: - - registry - - volume - type: object - rbd: - description: |- - rbd represents a Rados Block Device mount on the host that shares a pod's lifetime. - More info: https://examples.k8s.io/volumes/rbd/README.md - properties: - fsType: - description: |- - fsType is the filesystem type of the volume that you want to mount. - Tip: Ensure that the filesystem type is supported by the host operating system. - Examples: "ext4", "xfs", "ntfs". Implicitly inferred to be "ext4" if unspecified. - More info: https://kubernetes.io/docs/concepts/storage/volumes#rbd - TODO: how do we prevent errors in the filesystem from compromising the machine - type: string - image: - description: |- - image is the rados image name. - More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it - type: string - keyring: - description: |- - keyring is the path to key ring for RBDUser. - Default is /etc/ceph/keyring. - More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it - type: string - monitors: - description: |- - monitors is a collection of Ceph monitors. - More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it - items: - type: string - type: array - x-kubernetes-list-type: atomic - pool: - description: |- - pool is the rados pool name. - Default is rbd. - More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it - type: string - readOnly: - description: |- - readOnly here will force the ReadOnly setting in VolumeMounts. - Defaults to false. - More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it - type: boolean - secretRef: - description: |- - secretRef is name of the authentication secret for RBDUser. If provided - overrides keyring. - Default is nil. - More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it - properties: - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - TODO: Add other useful fields. apiVersion, kind, uid? - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - TODO: Drop `kubebuilder:default` when controller-gen doesn't need it https://github.com/kubernetes-sigs/kubebuilder/issues/3896. - type: string - type: object - x-kubernetes-map-type: atomic - user: - description: |- - user is the rados user name. - Default is admin. - More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it - type: string - required: - - image - - monitors - type: object - scaleIO: - description: scaleIO represents a ScaleIO persistent volume - attached and mounted on Kubernetes nodes. - properties: - fsType: - description: |- - fsType is the filesystem type to mount. - Must be a filesystem type supported by the host operating system. - Ex. "ext4", "xfs", "ntfs". - Default is "xfs". - type: string - gateway: - description: gateway is the host address of the ScaleIO - API Gateway. - type: string - protectionDomain: - description: protectionDomain is the name of the ScaleIO - Protection Domain for the configured storage. - type: string - readOnly: - description: |- - readOnly Defaults to false (read/write). ReadOnly here will force - the ReadOnly setting in VolumeMounts. - type: boolean - secretRef: - description: |- - secretRef references to the secret for ScaleIO user and other - sensitive information. If this is not provided, Login operation will fail. - properties: - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - TODO: Add other useful fields. apiVersion, kind, uid? - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - TODO: Drop `kubebuilder:default` when controller-gen doesn't need it https://github.com/kubernetes-sigs/kubebuilder/issues/3896. - type: string - type: object - x-kubernetes-map-type: atomic - sslEnabled: - description: sslEnabled Flag enable/disable SSL communication - with Gateway, default false - type: boolean - storageMode: - description: |- - storageMode indicates whether the storage for a volume should be ThickProvisioned or ThinProvisioned. - Default is ThinProvisioned. - type: string - storagePool: - description: storagePool is the ScaleIO Storage Pool - associated with the protection domain. - type: string - system: - description: system is the name of the storage system - as configured in ScaleIO. - type: string - volumeName: - description: |- - volumeName is the name of a volume already created in the ScaleIO system - that is associated with this volume source. - type: string - required: - - gateway - - secretRef - - system - type: object - secret: - description: |- - secret represents a secret that should populate this volume. - More info: https://kubernetes.io/docs/concepts/storage/volumes#secret - properties: - defaultMode: - description: |- - defaultMode is Optional: mode bits used to set permissions on created files by default. - Must be an octal value between 0000 and 0777 or a decimal value between 0 and 511. - YAML accepts both octal and decimal values, JSON requires decimal values - for mode bits. Defaults to 0644. - Directories within the path are not affected by this setting. - This might be in conflict with other options that affect the file - mode, like fsGroup, and the result can be other mode bits set. - format: int32 - type: integer - items: - description: |- - items If unspecified, each key-value pair in the Data field of the referenced - Secret will be projected into the volume as a file whose name is the - key and content is the value. If specified, the listed keys will be - projected into the specified paths, and unlisted keys will not be - present. If a key is specified which is not present in the Secret, - the volume setup will error unless it is marked optional. Paths must be - relative and may not contain the '..' path or start with '..'. - items: - description: Maps a string key to a path within a - volume. - properties: - key: - description: key is the key to project. - type: string - mode: - description: |- - mode is Optional: mode bits used to set permissions on this file. - Must be an octal value between 0000 and 0777 or a decimal value between 0 and 511. - YAML accepts both octal and decimal values, JSON requires decimal values for mode bits. - If not specified, the volume defaultMode will be used. - This might be in conflict with other options that affect the file - mode, like fsGroup, and the result can be other mode bits set. - format: int32 - type: integer - path: - description: |- - path is the relative path of the file to map the key to. - May not be an absolute path. - May not contain the path element '..'. - May not start with the string '..'. - type: string - required: - - key - - path - type: object - type: array - x-kubernetes-list-type: atomic - optional: - description: optional field specify whether the Secret - or its keys must be defined - type: boolean - secretName: - description: |- - secretName is the name of the secret in the pod's namespace to use. - More info: https://kubernetes.io/docs/concepts/storage/volumes#secret - type: string - type: object - storageos: - description: storageOS represents a StorageOS volume attached - and mounted on Kubernetes nodes. - properties: - fsType: - description: |- - fsType is the filesystem type to mount. - Must be a filesystem type supported by the host operating system. - Ex. "ext4", "xfs", "ntfs". Implicitly inferred to be "ext4" if unspecified. - type: string - readOnly: - description: |- - readOnly defaults to false (read/write). ReadOnly here will force - the ReadOnly setting in VolumeMounts. - type: boolean - secretRef: - description: |- - secretRef specifies the secret to use for obtaining the StorageOS API - credentials. If not specified, default values will be attempted. - properties: - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - TODO: Add other useful fields. apiVersion, kind, uid? - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - TODO: Drop `kubebuilder:default` when controller-gen doesn't need it https://github.com/kubernetes-sigs/kubebuilder/issues/3896. - type: string - type: object - x-kubernetes-map-type: atomic - volumeName: - description: |- - volumeName is the human-readable name of the StorageOS volume. Volume - names are only unique within a namespace. - type: string - volumeNamespace: - description: |- - volumeNamespace specifies the scope of the volume within StorageOS. If no - namespace is specified then the Pod's namespace will be used. This allows the - Kubernetes name scoping to be mirrored within StorageOS for tighter integration. - Set VolumeName to any name to override the default behaviour. - Set to "default" if you are not using namespaces within StorageOS. - Namespaces that do not pre-exist within StorageOS will be created. - type: string - type: object - vsphereVolume: - description: vsphereVolume represents a vSphere volume attached - and mounted on kubelets host machine - properties: - fsType: - description: |- - fsType is filesystem type to mount. - Must be a filesystem type supported by the host operating system. - Ex. "ext4", "xfs", "ntfs". Implicitly inferred to be "ext4" if unspecified. - type: string - storagePolicyID: - description: storagePolicyID is the storage Policy Based - Management (SPBM) profile ID associated with the StoragePolicyName. - type: string - storagePolicyName: - description: storagePolicyName is the storage Policy - Based Management (SPBM) profile name. - type: string - volumePath: - description: volumePath is the path that identifies - vSphere volume vmdk - type: string - required: - - volumePath - type: object - required: - - name - type: object - type: array - logLevel: - description: |- - LogLevel sets the log level for Envoy. - Allowed values are "trace", "debug", "info", "warn", "error", "critical", "off". - type: string - networkPublishing: - description: NetworkPublishing defines how to expose Envoy to - a network. - properties: - externalTrafficPolicy: - description: |- - ExternalTrafficPolicy describes how nodes distribute service traffic they - receive on one of the Service's "externally-facing" addresses (NodePorts, ExternalIPs, - and LoadBalancer IPs). - If unset, defaults to "Local". - type: string - ipFamilyPolicy: - description: |- - IPFamilyPolicy represents the dual-stack-ness requested or required by - this Service. If there is no value provided, then this field will be set - to SingleStack. Services can be "SingleStack" (a single IP family), - "PreferDualStack" (two IP families on dual-stack configured clusters or - a single IP family on single-stack clusters), or "RequireDualStack" - (two IP families on dual-stack configured clusters, otherwise fail). - type: string - serviceAnnotations: - additionalProperties: - type: string - description: |- - ServiceAnnotations is the annotations to add to - the provisioned Envoy service. - type: object - type: - description: |- - NetworkPublishingType is the type of publishing strategy to use. Valid values are: - * LoadBalancerService - In this configuration, network endpoints for Envoy use container networking. - A Kubernetes LoadBalancer Service is created to publish Envoy network - endpoints. - See: https://kubernetes.io/docs/concepts/services-networking/service/#loadbalancer - * NodePortService - Publishes Envoy network endpoints using a Kubernetes NodePort Service. - In this configuration, Envoy network endpoints use container networking. A Kubernetes - NodePort Service is created to publish the network endpoints. - See: https://kubernetes.io/docs/concepts/services-networking/service/#nodeport - NOTE: - When provisioning an Envoy `NodePortService`, use Gateway Listeners' port numbers to populate - the Service's node port values, there's no way to auto-allocate them. - See: https://github.com/projectcontour/contour/issues/4499 - * ClusterIPService - Publishes Envoy network endpoints using a Kubernetes ClusterIP Service. - In this configuration, Envoy network endpoints use container networking. A Kubernetes - ClusterIP Service is created to publish the network endpoints. - See: https://kubernetes.io/docs/concepts/services-networking/service/#publishing-services-service-types - If unset, defaults to LoadBalancerService. - type: string - type: object - nodePlacement: - description: NodePlacement describes node scheduling configuration - of Envoy pods. - properties: - nodeSelector: - additionalProperties: - type: string - description: |- - NodeSelector is the simplest recommended form of node selection constraint - and specifies a map of key-value pairs. For the pod to be eligible - to run on a node, the node must have each of the indicated key-value pairs - as labels (it can have additional labels as well). - If unset, the pod(s) will be scheduled to any available node. - type: object - tolerations: - description: |- - Tolerations work with taints to ensure that pods are not scheduled - onto inappropriate nodes. One or more taints are applied to a node; this - marks that the node should not accept any pods that do not tolerate the - taints. - The default is an empty list. - See https://kubernetes.io/docs/concepts/configuration/taint-and-toleration/ - for additional details. - items: - description: |- - The pod this Toleration is attached to tolerates any taint that matches - the triple using the matching operator . - properties: - effect: - description: |- - Effect indicates the taint effect to match. Empty means match all taint effects. - When specified, allowed values are NoSchedule, PreferNoSchedule and NoExecute. - type: string - key: - description: |- - Key is the taint key that the toleration applies to. Empty means match all taint keys. - If the key is empty, operator must be Exists; this combination means to match all values and all keys. - type: string - operator: - description: |- - Operator represents a key's relationship to the value. - Valid operators are Exists and Equal. Defaults to Equal. - Exists is equivalent to wildcard for value, so that a pod can - tolerate all taints of a particular category. - type: string - tolerationSeconds: - description: |- - TolerationSeconds represents the period of time the toleration (which must be - of effect NoExecute, otherwise this field is ignored) tolerates the taint. By default, - it is not set, which means tolerate the taint forever (do not evict). Zero and - negative values will be treated as 0 (evict immediately) by the system. - format: int64 - type: integer - value: - description: |- - Value is the taint value the toleration matches to. - If the operator is Exists, the value should be empty, otherwise just a regular string. - type: string - type: object - type: array - type: object - overloadMaxHeapSize: - description: |- - OverloadMaxHeapSize defines the maximum heap memory of the envoy controlled by the overload manager. - When the value is greater than 0, the overload manager is enabled, - and when envoy reaches 95% of the maximum heap size, it performs a shrink heap operation, - When it reaches 98% of the maximum heap size, Envoy Will stop accepting requests. - More info: https://projectcontour.io/docs/main/config/overload-manager/ - format: int64 - type: integer - podAnnotations: - additionalProperties: - type: string - description: |- - PodAnnotations defines annotations to add to the Envoy pods. - the annotations for Prometheus will be appended or overwritten with predefined value. - type: object - replicas: - description: |- - Deprecated: Use `DeploymentSettings.Replicas` instead. - Replicas is the desired number of Envoy replicas. If WorkloadType - is not "Deployment", this field is ignored. Otherwise, if unset, - defaults to 2. - if both `DeploymentSettings.Replicas` and this one is set, use `DeploymentSettings.Replicas`. - format: int32 - minimum: 0 - type: integer - resources: - description: |- - Compute Resources required by envoy container. - Cannot be updated. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ - properties: - claims: - description: |- - Claims lists the names of resources, defined in spec.resourceClaims, - that are used by this container. - This is an alpha field and requires enabling the - DynamicResourceAllocation feature gate. - This field is immutable. It can only be set for containers. - items: - description: ResourceClaim references one entry in PodSpec.ResourceClaims. - properties: - name: - description: |- - Name must match the name of one entry in pod.spec.resourceClaims of - the Pod where this field is used. It makes that resource available - inside a container. - type: string - required: - - name - type: object - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map - limits: - additionalProperties: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - description: |- - Limits describes the maximum amount of compute resources allowed. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ - type: object - requests: - additionalProperties: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - description: |- - Requests describes the minimum amount of compute resources required. - If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, - otherwise to an implementation-defined value. Requests cannot exceed Limits. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ - type: object - type: object - workloadType: - description: |- - WorkloadType is the type of workload to install Envoy - as. Choices are DaemonSet and Deployment. If unset, defaults - to DaemonSet. - type: string - type: object - resourceLabels: - additionalProperties: - type: string - description: |- - ResourceLabels is a set of labels to add to the provisioned Contour resources. - Deprecated: use Gateway.Spec.Infrastructure.Labels instead. This field will be - removed in a future release. - type: object - runtimeSettings: - description: |- - RuntimeSettings is a ContourConfiguration spec to be used when - provisioning a Contour instance that will influence aspects of - the Contour instance's runtime behavior. - properties: - debug: - description: |- - Debug contains parameters to enable debug logging - and debug interfaces inside Contour. - properties: - address: - description: |- - Defines the Contour debug address interface. - Contour's default is "127.0.0.1". - type: string - port: - description: |- - Defines the Contour debug address port. - Contour's default is 6060. - type: integer - type: object - enableExternalNameService: - description: |- - EnableExternalNameService allows processing of ExternalNameServices - Contour's default is false for security reasons. - type: boolean - envoy: - description: |- - Envoy contains parameters for Envoy as well - as how to optionally configure a managed Envoy fleet. - properties: - clientCertificate: - description: |- - ClientCertificate defines the namespace/name of the Kubernetes - secret containing the client certificate and private key - to be used when establishing TLS connection to upstream - cluster. - properties: - name: - type: string - namespace: - type: string - required: - - name - - namespace - type: object - cluster: - description: |- - Cluster holds various configurable Envoy cluster values that can - be set in the config file. - properties: - circuitBreakers: - description: |- - GlobalCircuitBreakerDefaults specifies default circuit breaker budget across all services. - If defined, this will be used as the default for all services. - properties: - maxConnections: - description: The maximum number of connections that - a single Envoy instance allows to the Kubernetes - Service; defaults to 1024. - format: int32 - type: integer - maxPendingRequests: - description: The maximum number of pending requests - that a single Envoy instance allows to the Kubernetes - Service; defaults to 1024. - format: int32 - type: integer - maxRequests: - description: The maximum parallel requests a single - Envoy instance allows to the Kubernetes Service; - defaults to 1024 - format: int32 - type: integer - maxRetries: - description: The maximum number of parallel retries - a single Envoy instance allows to the Kubernetes - Service; defaults to 3. - format: int32 - type: integer - perHostMaxConnections: - description: |- - PerHostMaxConnections is the maximum number of connections - that Envoy will allow to each individual host in a cluster. - format: int32 - type: integer - type: object - dnsLookupFamily: - description: |- - DNSLookupFamily defines how external names are looked up - When configured as V4, the DNS resolver will only perform a lookup - for addresses in the IPv4 family. If V6 is configured, the DNS resolver - will only perform a lookup for addresses in the IPv6 family. - If AUTO is configured, the DNS resolver will first perform a lookup - for addresses in the IPv6 family and fallback to a lookup for addresses - in the IPv4 family. If ALL is specified, the DNS resolver will perform a lookup for - both IPv4 and IPv6 families, and return all resolved addresses. - When this is used, Happy Eyeballs will be enabled for upstream connections. - Refer to Happy Eyeballs Support for more information. - Note: This only applies to externalName clusters. - See https://www.envoyproxy.io/docs/envoy/latest/api-v3/config/cluster/v3/cluster.proto.html#envoy-v3-api-enum-config-cluster-v3-cluster-dnslookupfamily - for more information. - Values: `auto` (default), `v4`, `v6`, `all`. - Other values will produce an error. - type: string - maxRequestsPerConnection: - description: |- - Defines the maximum requests for upstream connections. If not specified, there is no limit. - see https://www.envoyproxy.io/docs/envoy/latest/api-v3/config/core/v3/protocol.proto#envoy-v3-api-msg-config-core-v3-httpprotocoloptions - for more information. - format: int32 - minimum: 1 - type: integer - per-connection-buffer-limit-bytes: - description: |- - Defines the soft limit on size of the cluster’s new connection read and write buffers in bytes. - If unspecified, an implementation defined default is applied (1MiB). - see https://www.envoyproxy.io/docs/envoy/latest/api-v3/config/cluster/v3/cluster.proto#envoy-v3-api-field-config-cluster-v3-cluster-per-connection-buffer-limit-bytes - for more information. - format: int32 - minimum: 1 - type: integer - upstreamTLS: - description: UpstreamTLS contains the TLS policy parameters - for upstream connections - properties: - cipherSuites: - description: |- - CipherSuites defines the TLS ciphers to be supported by Envoy TLS - listeners when negotiating TLS 1.2. Ciphers are validated against the - set that Envoy supports by default. This parameter should only be used - by advanced users. Note that these will be ignored when TLS 1.3 is in - use. - This field is optional; when it is undefined, a Contour-managed ciphersuite list - will be used, which may be updated to keep it secure. - Contour's default list is: - - "[ECDHE-ECDSA-AES128-GCM-SHA256|ECDHE-ECDSA-CHACHA20-POLY1305]" - - "[ECDHE-RSA-AES128-GCM-SHA256|ECDHE-RSA-CHACHA20-POLY1305]" - - "ECDHE-ECDSA-AES256-GCM-SHA384" - - "ECDHE-RSA-AES256-GCM-SHA384" - Ciphers provided are validated against the following list: - - "[ECDHE-ECDSA-AES128-GCM-SHA256|ECDHE-ECDSA-CHACHA20-POLY1305]" - - "[ECDHE-RSA-AES128-GCM-SHA256|ECDHE-RSA-CHACHA20-POLY1305]" - - "ECDHE-ECDSA-AES128-GCM-SHA256" - - "ECDHE-RSA-AES128-GCM-SHA256" - - "ECDHE-ECDSA-AES128-SHA" - - "ECDHE-RSA-AES128-SHA" - - "AES128-GCM-SHA256" - - "AES128-SHA" - - "ECDHE-ECDSA-AES256-GCM-SHA384" - - "ECDHE-RSA-AES256-GCM-SHA384" - - "ECDHE-ECDSA-AES256-SHA" - - "ECDHE-RSA-AES256-SHA" - - "AES256-GCM-SHA384" - - "AES256-SHA" - Contour recommends leaving this undefined unless you are sure you must. - See: https://www.envoyproxy.io/docs/envoy/latest/api-v3/extensions/transport_sockets/tls/v3/common.proto#extensions-transport-sockets-tls-v3-tlsparameters - Note: This list is a superset of what is valid for stock Envoy builds and those using BoringSSL FIPS. - items: - type: string - type: array - maximumProtocolVersion: - description: |- - MaximumProtocolVersion is the maximum TLS version this vhost should - negotiate. - Values: `1.2`, `1.3`(default). - Other values will produce an error. - type: string - minimumProtocolVersion: - description: |- - MinimumProtocolVersion is the minimum TLS version this vhost should - negotiate. - Values: `1.2` (default), `1.3`. - Other values will produce an error. - type: string - type: object - type: object - defaultHTTPVersions: - description: |- - DefaultHTTPVersions defines the default set of HTTPS - versions the proxy should accept. HTTP versions are - strings of the form "HTTP/xx". Supported versions are - "HTTP/1.1" and "HTTP/2". - Values: `HTTP/1.1`, `HTTP/2` (default: both). - Other values will produce an error. - items: - description: HTTPVersionType is the name of a supported - HTTP version. - type: string - type: array - health: - description: |- - Health defines the endpoint Envoy uses to serve health checks. - Contour's default is { address: "0.0.0.0", port: 8002 }. - properties: - address: - description: Defines the health address interface. - minLength: 1 - type: string - port: - description: Defines the health port. - type: integer - type: object - http: - description: |- - Defines the HTTP Listener for Envoy. - Contour's default is { address: "0.0.0.0", port: 8080, accessLog: "/dev/stdout" }. - properties: - accessLog: - description: AccessLog defines where Envoy logs are outputted - for this listener. - type: string - address: - description: Defines an Envoy Listener Address. - minLength: 1 - type: string - port: - description: Defines an Envoy listener Port. - type: integer - type: object - https: - description: |- - Defines the HTTPS Listener for Envoy. - Contour's default is { address: "0.0.0.0", port: 8443, accessLog: "/dev/stdout" }. - properties: - accessLog: - description: AccessLog defines where Envoy logs are outputted - for this listener. - type: string - address: - description: Defines an Envoy Listener Address. - minLength: 1 - type: string - port: - description: Defines an Envoy listener Port. - type: integer - type: object - listener: - description: Listener hold various configurable Envoy listener - values. - properties: - connectionBalancer: - description: |- - ConnectionBalancer. If the value is exact, the listener will use the exact connection balancer - See https://www.envoyproxy.io/docs/envoy/latest/api-v2/api/v2/listener.proto#envoy-api-msg-listener-connectionbalanceconfig - for more information. - Values: (empty string): use the default ConnectionBalancer, `exact`: use the Exact ConnectionBalancer. - Other values will produce an error. - type: string - disableAllowChunkedLength: - description: |- - DisableAllowChunkedLength disables the RFC-compliant Envoy behavior to - strip the "Content-Length" header if "Transfer-Encoding: chunked" is - also set. This is an emergency off-switch to revert back to Envoy's - default behavior in case of failures. Please file an issue if failures - are encountered. - See: https://github.com/projectcontour/contour/issues/3221 - Contour's default is false. - type: boolean - disableMergeSlashes: - description: |- - DisableMergeSlashes disables Envoy's non-standard merge_slashes path transformation option - which strips duplicate slashes from request URL paths. - Contour's default is false. - type: boolean - httpMaxConcurrentStreams: - description: |- - Defines the value for SETTINGS_MAX_CONCURRENT_STREAMS Envoy will advertise in the - SETTINGS frame in HTTP/2 connections and the limit for concurrent streams allowed - for a peer on a single HTTP/2 connection. It is recommended to not set this lower - than 100 but this field can be used to bound resource usage by HTTP/2 connections - and mitigate attacks like CVE-2023-44487. The default value when this is not set is - unlimited. - format: int32 - minimum: 1 - type: integer - maxConnectionsPerListener: - description: |- - Defines the limit on number of active connections to a listener. The limit is applied - per listener. The default value when this is not set is unlimited. - format: int32 - minimum: 1 - type: integer - maxRequestsPerConnection: - description: |- - Defines the maximum requests for downstream connections. If not specified, there is no limit. - see https://www.envoyproxy.io/docs/envoy/latest/api-v3/config/core/v3/protocol.proto#envoy-v3-api-msg-config-core-v3-httpprotocoloptions - for more information. - format: int32 - minimum: 1 - type: integer - maxRequestsPerIOCycle: - description: |- - Defines the limit on number of HTTP requests that Envoy will process from a single - connection in a single I/O cycle. Requests over this limit are processed in subsequent - I/O cycles. Can be used as a mitigation for CVE-2023-44487 when abusive traffic is - detected. Configures the http.max_requests_per_io_cycle Envoy runtime setting. The default - value when this is not set is no limit. - format: int32 - minimum: 1 - type: integer - per-connection-buffer-limit-bytes: - description: |- - Defines the soft limit on size of the listener’s new connection read and write buffers in bytes. - If unspecified, an implementation defined default is applied (1MiB). - see https://www.envoyproxy.io/docs/envoy/latest/api-v3/config/listener/v3/listener.proto#envoy-v3-api-field-config-listener-v3-listener-per-connection-buffer-limit-bytes - for more information. - format: int32 - minimum: 1 - type: integer - serverHeaderTransformation: - description: |- - Defines the action to be applied to the Server header on the response path. - When configured as overwrite, overwrites any Server header with "envoy". - When configured as append_if_absent, if a Server header is present, pass it through, otherwise set it to "envoy". - When configured as pass_through, pass through the value of the Server header, and do not append a header if none is present. - Values: `overwrite` (default), `append_if_absent`, `pass_through` - Other values will produce an error. - Contour's default is overwrite. - type: string - socketOptions: - description: |- - SocketOptions defines configurable socket options for the listeners. - Single set of options are applied to all listeners. - properties: - tos: - description: |- - Defines the value for IPv4 TOS field (including 6 bit DSCP field) for IP packets originating from Envoy listeners. - Single value is applied to all listeners. - If listeners are bound to IPv6-only addresses, setting this option will cause an error. - format: int32 - maximum: 255 - minimum: 0 - type: integer - trafficClass: - description: |- - Defines the value for IPv6 Traffic Class field (including 6 bit DSCP field) for IP packets originating from the Envoy listeners. - Single value is applied to all listeners. - If listeners are bound to IPv4-only addresses, setting this option will cause an error. - format: int32 - maximum: 255 - minimum: 0 - type: integer - type: object - tls: - description: TLS holds various configurable Envoy TLS - listener values. - properties: - cipherSuites: - description: |- - CipherSuites defines the TLS ciphers to be supported by Envoy TLS - listeners when negotiating TLS 1.2. Ciphers are validated against the - set that Envoy supports by default. This parameter should only be used - by advanced users. Note that these will be ignored when TLS 1.3 is in - use. - This field is optional; when it is undefined, a Contour-managed ciphersuite list - will be used, which may be updated to keep it secure. - Contour's default list is: - - "[ECDHE-ECDSA-AES128-GCM-SHA256|ECDHE-ECDSA-CHACHA20-POLY1305]" - - "[ECDHE-RSA-AES128-GCM-SHA256|ECDHE-RSA-CHACHA20-POLY1305]" - - "ECDHE-ECDSA-AES256-GCM-SHA384" - - "ECDHE-RSA-AES256-GCM-SHA384" - Ciphers provided are validated against the following list: - - "[ECDHE-ECDSA-AES128-GCM-SHA256|ECDHE-ECDSA-CHACHA20-POLY1305]" - - "[ECDHE-RSA-AES128-GCM-SHA256|ECDHE-RSA-CHACHA20-POLY1305]" - - "ECDHE-ECDSA-AES128-GCM-SHA256" - - "ECDHE-RSA-AES128-GCM-SHA256" - - "ECDHE-ECDSA-AES128-SHA" - - "ECDHE-RSA-AES128-SHA" - - "AES128-GCM-SHA256" - - "AES128-SHA" - - "ECDHE-ECDSA-AES256-GCM-SHA384" - - "ECDHE-RSA-AES256-GCM-SHA384" - - "ECDHE-ECDSA-AES256-SHA" - - "ECDHE-RSA-AES256-SHA" - - "AES256-GCM-SHA384" - - "AES256-SHA" - Contour recommends leaving this undefined unless you are sure you must. - See: https://www.envoyproxy.io/docs/envoy/latest/api-v3/extensions/transport_sockets/tls/v3/common.proto#extensions-transport-sockets-tls-v3-tlsparameters - Note: This list is a superset of what is valid for stock Envoy builds and those using BoringSSL FIPS. - items: - type: string - type: array - maximumProtocolVersion: - description: |- - MaximumProtocolVersion is the maximum TLS version this vhost should - negotiate. - Values: `1.2`, `1.3`(default). - Other values will produce an error. - type: string - minimumProtocolVersion: - description: |- - MinimumProtocolVersion is the minimum TLS version this vhost should - negotiate. - Values: `1.2` (default), `1.3`. - Other values will produce an error. - type: string - type: object - useProxyProtocol: - description: |- - Use PROXY protocol for all listeners. - Contour's default is false. - type: boolean - type: object - logging: - description: Logging defines how Envoy's logs can be configured. - properties: - accessLogFormat: - description: |- - AccessLogFormat sets the global access log format. - Values: `envoy` (default), `json`. - Other values will produce an error. - type: string - accessLogFormatString: - description: |- - AccessLogFormatString sets the access log format when format is set to `envoy`. - When empty, Envoy's default format is used. - type: string - accessLogJSONFields: - description: |- - AccessLogJSONFields sets the fields that JSON logging will - output when AccessLogFormat is json. - items: - type: string - type: array - accessLogLevel: - description: |- - AccessLogLevel sets the verbosity level of the access log. - Values: `info` (default, all requests are logged), `error` (all non-success requests, i.e. 300+ response code, are logged), `critical` (all 5xx requests are logged) and `disabled`. - Other values will produce an error. - type: string - type: object - metrics: - description: |- - Metrics defines the endpoint Envoy uses to serve metrics. - Contour's default is { address: "0.0.0.0", port: 8002 }. - properties: - address: - description: Defines the metrics address interface. - maxLength: 253 - minLength: 1 - type: string - port: - description: Defines the metrics port. - type: integer - tls: - description: |- - TLS holds TLS file config details. - Metrics and health endpoints cannot have same port number when metrics is served over HTTPS. - properties: - caFile: - description: CA filename. - type: string - certFile: - description: Client certificate filename. - type: string - keyFile: - description: Client key filename. - type: string - type: object - type: object - network: - description: Network holds various configurable Envoy network - values. - properties: - adminPort: - description: |- - Configure the port used to access the Envoy Admin interface. - If configured to port "0" then the admin interface is disabled. - Contour's default is 9001. - type: integer - numTrustedHops: - description: |- - XffNumTrustedHops defines the number of additional ingress proxy hops from the - right side of the x-forwarded-for HTTP header to trust when determining the origin - client’s IP address. - See https://www.envoyproxy.io/docs/envoy/v1.17.0/api-v3/extensions/filters/network/http_connection_manager/v3/http_connection_manager.proto?highlight=xff_num_trusted_hops - for more information. - Contour's default is 0. - format: int32 - type: integer - type: object - service: - description: |- - Service holds Envoy service parameters for setting Ingress status. - Contour's default is { namespace: "projectcontour", name: "envoy" }. - properties: - name: - type: string - namespace: - type: string - required: - - name - - namespace - type: object - timeouts: - description: |- - Timeouts holds various configurable timeouts that can - be set in the config file. - properties: - connectTimeout: - description: |- - ConnectTimeout defines how long the proxy should wait when establishing connection to upstream service. - If not set, a default value of 2 seconds will be used. - See https://www.envoyproxy.io/docs/envoy/latest/api-v3/config/cluster/v3/cluster.proto#envoy-v3-api-field-config-cluster-v3-cluster-connect-timeout - for more information. - type: string - connectionIdleTimeout: - description: |- - ConnectionIdleTimeout defines how long the proxy should wait while there are - no active requests (for HTTP/1.1) or streams (for HTTP/2) before terminating - an HTTP connection. Set to "infinity" to disable the timeout entirely. - See https://www.envoyproxy.io/docs/envoy/latest/api-v3/config/core/v3/protocol.proto#envoy-v3-api-field-config-core-v3-httpprotocoloptions-idle-timeout - for more information. - type: string - connectionShutdownGracePeriod: - description: |- - ConnectionShutdownGracePeriod defines how long the proxy will wait between sending an - initial GOAWAY frame and a second, final GOAWAY frame when terminating an HTTP/2 connection. - During this grace period, the proxy will continue to respond to new streams. After the final - GOAWAY frame has been sent, the proxy will refuse new streams. - See https://www.envoyproxy.io/docs/envoy/latest/api-v3/extensions/filters/network/http_connection_manager/v3/http_connection_manager.proto#envoy-v3-api-field-extensions-filters-network-http-connection-manager-v3-httpconnectionmanager-drain-timeout - for more information. - type: string - delayedCloseTimeout: - description: |- - DelayedCloseTimeout defines how long envoy will wait, once connection - close processing has been initiated, for the downstream peer to close - the connection before Envoy closes the socket associated with the connection. - Setting this timeout to 'infinity' will disable it, equivalent to setting it to '0' - in Envoy. Leaving it unset will result in the Envoy default value being used. - See https://www.envoyproxy.io/docs/envoy/latest/api-v3/extensions/filters/network/http_connection_manager/v3/http_connection_manager.proto#envoy-v3-api-field-extensions-filters-network-http-connection-manager-v3-httpconnectionmanager-delayed-close-timeout - for more information. - type: string - maxConnectionDuration: - description: |- - MaxConnectionDuration defines the maximum period of time after an HTTP connection - has been established from the client to the proxy before it is closed by the proxy, - regardless of whether there has been activity or not. Omit or set to "infinity" for - no max duration. - See https://www.envoyproxy.io/docs/envoy/latest/api-v3/config/core/v3/protocol.proto#envoy-v3-api-field-config-core-v3-httpprotocoloptions-max-connection-duration - for more information. - type: string - requestTimeout: - description: |- - RequestTimeout sets the client request timeout globally for Contour. Note that - this is a timeout for the entire request, not an idle timeout. Omit or set to - "infinity" to disable the timeout entirely. - See https://www.envoyproxy.io/docs/envoy/latest/api-v3/extensions/filters/network/http_connection_manager/v3/http_connection_manager.proto#envoy-v3-api-field-extensions-filters-network-http-connection-manager-v3-httpconnectionmanager-request-timeout - for more information. - type: string - streamIdleTimeout: - description: |- - StreamIdleTimeout defines how long the proxy should wait while there is no - request activity (for HTTP/1.1) or stream activity (for HTTP/2) before - terminating the HTTP request or stream. Set to "infinity" to disable the - timeout entirely. - See https://www.envoyproxy.io/docs/envoy/latest/api-v3/extensions/filters/network/http_connection_manager/v3/http_connection_manager.proto#envoy-v3-api-field-extensions-filters-network-http-connection-manager-v3-httpconnectionmanager-stream-idle-timeout - for more information. - type: string - type: object - type: object - featureFlags: - description: |- - FeatureFlags defines toggle to enable new contour features. - Available toggles are: - useEndpointSlices - Configures contour to fetch endpoint data - from k8s endpoint slices. defaults to true, - If false then reads endpoint data from the k8s endpoints. - items: - type: string - type: array - gateway: - description: |- - Gateway contains parameters for the gateway-api Gateway that Contour - is configured to serve traffic. - properties: - gatewayRef: - description: |- - GatewayRef defines the specific Gateway that this Contour - instance corresponds to. - properties: - name: - type: string - namespace: - type: string - required: - - name - - namespace - type: object - required: - - gatewayRef - type: object - globalExtAuth: - description: |- - GlobalExternalAuthorization allows envoys external authorization filter - to be enabled for all virtual hosts. - properties: - authPolicy: - description: |- - AuthPolicy sets a default authorization policy for client requests. - This policy will be used unless overridden by individual routes. - properties: - context: - additionalProperties: - type: string - description: |- - Context is a set of key/value pairs that are sent to the - authentication server in the check request. If a context - is provided at an enclosing scope, the entries are merged - such that the inner scope overrides matching keys from the - outer scope. - type: object - disabled: - description: |- - When true, this field disables client request authentication - for the scope of the policy. - type: boolean - type: object - extensionRef: - description: ExtensionServiceRef specifies the extension resource - that will authorize client requests. - properties: - apiVersion: - description: |- - API version of the referent. - If this field is not specified, the default "projectcontour.io/v1alpha1" will be used - minLength: 1 - type: string - name: - description: |- - Name of the referent. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - minLength: 1 - type: string - namespace: - description: |- - Namespace of the referent. - If this field is not specifies, the namespace of the resource that targets the referent will be used. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/ - minLength: 1 - type: string - type: object - failOpen: - description: |- - If FailOpen is true, the client request is forwarded to the upstream service - even if the authorization server fails to respond. This field should not be - set in most cases. It is intended for use only while migrating applications - from internal authorization to Contour external authorization. - type: boolean - responseTimeout: - description: |- - ResponseTimeout configures maximum time to wait for a check response from the authorization server. - Timeout durations are expressed in the Go [Duration format](https://godoc.org/time#ParseDuration). - Valid time units are "ns", "us" (or "µs"), "ms", "s", "m", "h". - The string "infinity" is also a valid input and specifies no timeout. - pattern: ^(((\d*(\.\d*)?h)|(\d*(\.\d*)?m)|(\d*(\.\d*)?s)|(\d*(\.\d*)?ms)|(\d*(\.\d*)?us)|(\d*(\.\d*)?µs)|(\d*(\.\d*)?ns))+|infinity|infinite)$ - type: string - withRequestBody: - description: WithRequestBody specifies configuration for sending - the client request's body to authorization server. - properties: - allowPartialMessage: - description: If AllowPartialMessage is true, then Envoy - will buffer the body until MaxRequestBytes are reached. - type: boolean - maxRequestBytes: - default: 1024 - description: MaxRequestBytes sets the maximum size of - message body ExtAuthz filter will hold in-memory. - format: int32 - minimum: 1 - type: integer - packAsBytes: - description: If PackAsBytes is true, the body sent to - Authorization Server is in raw bytes. - type: boolean - type: object - type: object - health: - description: |- - Health defines the endpoints Contour uses to serve health checks. - Contour's default is { address: "0.0.0.0", port: 8000 }. - properties: - address: - description: Defines the health address interface. - minLength: 1 - type: string - port: - description: Defines the health port. - type: integer - type: object - httpproxy: - description: HTTPProxy defines parameters on HTTPProxy. - properties: - disablePermitInsecure: - description: |- - DisablePermitInsecure disables the use of the - permitInsecure field in HTTPProxy. - Contour's default is false. - type: boolean - fallbackCertificate: - description: |- - FallbackCertificate defines the namespace/name of the Kubernetes secret to - use as fallback when a non-SNI request is received. - properties: - name: - type: string - namespace: - type: string - required: - - name - - namespace - type: object - rootNamespaces: - description: Restrict Contour to searching these namespaces - for root ingress routes. - items: - type: string - type: array - type: object - ingress: - description: Ingress contains parameters for ingress options. - properties: - classNames: - description: Ingress Class Names Contour should use. - items: - type: string - type: array - statusAddress: - description: Address to set in Ingress object status. - type: string - type: object - metrics: - description: |- - Metrics defines the endpoint Contour uses to serve metrics. - Contour's default is { address: "0.0.0.0", port: 8000 }. - properties: - address: - description: Defines the metrics address interface. - maxLength: 253 - minLength: 1 - type: string - port: - description: Defines the metrics port. - type: integer - tls: - description: |- - TLS holds TLS file config details. - Metrics and health endpoints cannot have same port number when metrics is served over HTTPS. - properties: - caFile: - description: CA filename. - type: string - certFile: - description: Client certificate filename. - type: string - keyFile: - description: Client key filename. - type: string - type: object - type: object - policy: - description: Policy specifies default policy applied if not overridden - by the user - properties: - applyToIngress: - description: |- - ApplyToIngress determines if the Policies will apply to ingress objects - Contour's default is false. - type: boolean - requestHeaders: - description: RequestHeadersPolicy defines the request headers - set/removed on all routes - properties: - remove: - items: - type: string - type: array - set: - additionalProperties: - type: string - type: object - type: object - responseHeaders: - description: ResponseHeadersPolicy defines the response headers - set/removed on all routes - properties: - remove: - items: - type: string - type: array - set: - additionalProperties: - type: string - type: object - type: object - type: object - rateLimitService: - description: |- - RateLimitService optionally holds properties of the Rate Limit Service - to be used for global rate limiting. - properties: - defaultGlobalRateLimitPolicy: - description: |- - DefaultGlobalRateLimitPolicy allows setting a default global rate limit policy for every HTTPProxy. - HTTPProxy can overwrite this configuration. - properties: - descriptors: - description: |- - Descriptors defines the list of descriptors that will - be generated and sent to the rate limit service. Each - descriptor contains 1+ key-value pair entries. - items: - description: RateLimitDescriptor defines a list of key-value - pair generators. - properties: - entries: - description: Entries is the list of key-value pair - generators. - items: - description: |- - RateLimitDescriptorEntry is a key-value pair generator. Exactly - one field on this struct must be non-nil. - properties: - genericKey: - description: GenericKey defines a descriptor - entry with a static key and value. - properties: - key: - description: |- - Key defines the key of the descriptor entry. If not set, the - key is set to "generic_key". - type: string - value: - description: Value defines the value of - the descriptor entry. - minLength: 1 - type: string - type: object - remoteAddress: - description: |- - RemoteAddress defines a descriptor entry with a key of "remote_address" - and a value equal to the client's IP address (from x-forwarded-for). - type: object - requestHeader: - description: |- - RequestHeader defines a descriptor entry that's populated only if - a given header is present on the request. The descriptor key is static, - and the descriptor value is equal to the value of the header. - properties: - descriptorKey: - description: DescriptorKey defines the - key to use on the descriptor entry. - minLength: 1 - type: string - headerName: - description: HeaderName defines the name - of the header to look for on the request. - minLength: 1 - type: string - type: object - requestHeaderValueMatch: - description: |- - RequestHeaderValueMatch defines a descriptor entry that's populated - if the request's headers match a set of 1+ match criteria. The - descriptor key is "header_match", and the descriptor value is static. - properties: - expectMatch: - default: true - description: |- - ExpectMatch defines whether the request must positively match the match - criteria in order to generate a descriptor entry (i.e. true), or not - match the match criteria in order to generate a descriptor entry (i.e. false). - The default is true. - type: boolean - headers: - description: |- - Headers is a list of 1+ match criteria to apply against the request - to determine whether to populate the descriptor entry or not. - items: - description: |- - HeaderMatchCondition specifies how to conditionally match against HTTP - headers. The Name field is required, only one of Present, NotPresent, - Contains, NotContains, Exact, NotExact and Regex can be set. - For negative matching rules only (e.g. NotContains or NotExact) you can set - TreatMissingAsEmpty. - IgnoreCase has no effect for Regex. - properties: - contains: - description: |- - Contains specifies a substring that must be present in - the header value. - type: string - exact: - description: Exact specifies a string - that the header value must be - equal to. - type: string - ignoreCase: - description: |- - IgnoreCase specifies that string matching should be case insensitive. - Note that this has no effect on the Regex parameter. - type: boolean - name: - description: |- - Name is the name of the header to match against. Name is required. - Header names are case insensitive. - type: string - notcontains: - description: |- - NotContains specifies a substring that must not be present - in the header value. - type: string - notexact: - description: |- - NoExact specifies a string that the header value must not be - equal to. The condition is true if the header has any other value. - type: string - notpresent: - description: |- - NotPresent specifies that condition is true when the named header - is not present. Note that setting NotPresent to false does not - make the condition true if the named header is present. - type: boolean - present: - description: |- - Present specifies that condition is true when the named header - is present, regardless of its value. Note that setting Present - to false does not make the condition true if the named header - is absent. - type: boolean - regex: - description: |- - Regex specifies a regular expression pattern that must match the header - value. - type: string - treatMissingAsEmpty: - description: |- - TreatMissingAsEmpty specifies if the header match rule specified header - does not exist, this header value will be treated as empty. Defaults to false. - Unlike the underlying Envoy implementation this is **only** supported for - negative matches (e.g. NotContains, NotExact). - type: boolean - required: - - name - type: object - minItems: 1 - type: array - value: - description: Value defines the value of - the descriptor entry. - minLength: 1 - type: string - type: object - type: object - minItems: 1 - type: array - type: object - minItems: 1 - type: array - disabled: - description: |- - Disabled configures the HTTPProxy to not use - the default global rate limit policy defined by the Contour configuration. - type: boolean - type: object - domain: - description: Domain is passed to the Rate Limit Service. - type: string - enableResourceExhaustedCode: - description: |- - EnableResourceExhaustedCode enables translating error code 429 to - grpc code RESOURCE_EXHAUSTED. When disabled it's translated to UNAVAILABLE - type: boolean - enableXRateLimitHeaders: - description: |- - EnableXRateLimitHeaders defines whether to include the X-RateLimit - headers X-RateLimit-Limit, X-RateLimit-Remaining, and X-RateLimit-Reset - (as defined by the IETF Internet-Draft linked below), on responses - to clients when the Rate Limit Service is consulted for a request. - ref. https://tools.ietf.org/id/draft-polli-ratelimit-headers-03.html - type: boolean - extensionService: - description: ExtensionService identifies the extension service - defining the RLS. - properties: - name: - type: string - namespace: - type: string - required: - - name - - namespace - type: object - failOpen: - description: |- - FailOpen defines whether to allow requests to proceed when the - Rate Limit Service fails to respond with a valid rate limit - decision within the timeout defined on the extension service. - type: boolean - required: - - extensionService - type: object - tracing: - description: Tracing defines properties for exporting trace data - to OpenTelemetry. - properties: - customTags: - description: CustomTags defines a list of custom tags with - unique tag name. - items: - description: |- - CustomTag defines custom tags with unique tag name - to create tags for the active span. - properties: - literal: - description: |- - Literal is a static custom tag value. - Precisely one of Literal, RequestHeaderName must be set. - type: string - requestHeaderName: - description: |- - RequestHeaderName indicates which request header - the label value is obtained from. - Precisely one of Literal, RequestHeaderName must be set. - type: string - tagName: - description: TagName is the unique name of the custom - tag. - type: string - required: - - tagName - type: object - type: array - extensionService: - description: ExtensionService identifies the extension service - defining the otel-collector. - properties: - name: - type: string - namespace: - type: string - required: - - name - - namespace - type: object - includePodDetail: - description: |- - IncludePodDetail defines a flag. - If it is true, contour will add the pod name and namespace to the span of the trace. - the default is true. - Note: The Envoy pods MUST have the HOSTNAME and CONTOUR_NAMESPACE environment variables set for this to work properly. - type: boolean - maxPathTagLength: - description: |- - MaxPathTagLength defines maximum length of the request path - to extract and include in the HttpUrl tag. - contour's default is 256. - format: int32 - type: integer - overallSampling: - description: |- - OverallSampling defines the sampling rate of trace data. - contour's default is 100. - type: string - serviceName: - description: |- - ServiceName defines the name for the service. - contour's default is contour. - type: string - required: - - extensionService - type: object - xdsServer: - description: XDSServer contains parameters for the xDS server. - properties: - address: - description: |- - Defines the xDS gRPC API address which Contour will serve. - Contour's default is "0.0.0.0". - minLength: 1 - type: string - port: - description: |- - Defines the xDS gRPC API port which Contour will serve. - Contour's default is 8001. - type: integer - tls: - description: |- - TLS holds TLS file config details. - Contour's default is { caFile: "/certs/ca.crt", certFile: "/certs/tls.cert", keyFile: "/certs/tls.key", insecure: false }. - properties: - caFile: - description: CA filename. - type: string - certFile: - description: Client certificate filename. - type: string - insecure: - description: Allow serving the xDS gRPC API without TLS. - type: boolean - keyFile: - description: Client key filename. - type: string - type: object - type: - description: |- - Defines the XDSServer to use for `contour serve`. - Values: `envoy` (default), `contour (deprecated)`. - Other values will produce an error. - Deprecated: this field will be removed in a future release when - the `contour` xDS server implementation is removed. - type: string - type: object - type: object - type: object - status: - description: ContourDeploymentStatus defines the observed state of a ContourDeployment - resource. - properties: - conditions: - description: Conditions describe the current conditions of the ContourDeployment - resource. - items: - description: "Condition contains details for one aspect of the current - state of this API Resource.\n---\nThis struct is intended for - direct use as an array at the field path .status.conditions. For - example,\n\n\n\ttype FooStatus struct{\n\t // Represents the - observations of a foo's current state.\n\t // Known .status.conditions.type - are: \"Available\", \"Progressing\", and \"Degraded\"\n\t // - +patchMergeKey=type\n\t // +patchStrategy=merge\n\t // +listType=map\n\t - \ // +listMapKey=type\n\t Conditions []metav1.Condition `json:\"conditions,omitempty\" - patchStrategy:\"merge\" patchMergeKey:\"type\" protobuf:\"bytes,1,rep,name=conditions\"`\n\n\n\t - \ // other fields\n\t}" - properties: - lastTransitionTime: - description: |- - lastTransitionTime is the last time the condition transitioned from one status to another. - This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable. - format: date-time - type: string - message: - description: |- - message is a human readable message indicating details about the transition. - This may be an empty string. - maxLength: 32768 - type: string - observedGeneration: - description: |- - observedGeneration represents the .metadata.generation that the condition was set based upon. - For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date - with respect to the current state of the instance. - format: int64 - minimum: 0 - type: integer - reason: - description: |- - reason contains a programmatic identifier indicating the reason for the condition's last transition. - Producers of specific condition types may define expected values and meanings for this field, - and whether the values are considered a guaranteed API. - The value should be a CamelCase string. - This field may not be empty. - maxLength: 1024 - minLength: 1 - pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ - type: string - status: - description: status of the condition, one of True, False, Unknown. - enum: - - "True" - - "False" - - Unknown - type: string - type: - description: |- - type of condition in CamelCase or in foo.example.com/CamelCase. - --- - Many .condition.type values are consistent across resources like Available, but because arbitrary conditions can be - useful (see .node.status.conditions), the ability to deconflict is important. - The regex it matches is (dns1123SubdomainFmt/)?(qualifiedNameFmt) - maxLength: 316 - pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ - type: string - required: - - lastTransitionTime - - message - - reason - - status - - type - type: object - type: array - x-kubernetes-list-map-keys: - - type - x-kubernetes-list-type: map - type: object - type: object - served: true - storage: true - subresources: - status: {} ---- -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.15.0 - name: extensionservices.projectcontour.io -spec: - preserveUnknownFields: false - group: projectcontour.io - names: - kind: ExtensionService - listKind: ExtensionServiceList - plural: extensionservices - shortNames: - - extensionservice - - extensionservices - singular: extensionservice - scope: Namespaced - versions: - - name: v1alpha1 - schema: - openAPIV3Schema: - description: |- - ExtensionService is the schema for the Contour extension services API. - An ExtensionService resource binds a network service to the Contour - API so that Contour API features can be implemented by collaborating - components. - properties: - apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - type: string - kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - metadata: - type: object - spec: - description: ExtensionServiceSpec defines the desired state of an ExtensionService - resource. - properties: - circuitBreakerPolicy: - description: |- - CircuitBreakerPolicy specifies the circuit breaker budget across the extension service. - If defined this overrides the global circuit breaker budget. - properties: - maxConnections: - description: The maximum number of connections that a single Envoy - instance allows to the Kubernetes Service; defaults to 1024. - format: int32 - type: integer - maxPendingRequests: - description: The maximum number of pending requests that a single - Envoy instance allows to the Kubernetes Service; defaults to - 1024. - format: int32 - type: integer - maxRequests: - description: The maximum parallel requests a single Envoy instance - allows to the Kubernetes Service; defaults to 1024 - format: int32 - type: integer - maxRetries: - description: The maximum number of parallel retries a single Envoy - instance allows to the Kubernetes Service; defaults to 3. - format: int32 - type: integer - perHostMaxConnections: - description: |- - PerHostMaxConnections is the maximum number of connections - that Envoy will allow to each individual host in a cluster. - format: int32 - type: integer - type: object - loadBalancerPolicy: - description: |- - The policy for load balancing GRPC service requests. Note that the - `Cookie` and `RequestHash` load balancing strategies cannot be used - here. - properties: - requestHashPolicies: - description: |- - RequestHashPolicies contains a list of hash policies to apply when the - `RequestHash` load balancing strategy is chosen. If an element of the - supplied list of hash policies is invalid, it will be ignored. If the - list of hash policies is empty after validation, the load balancing - strategy will fall back to the default `RoundRobin`. - items: - description: |- - RequestHashPolicy contains configuration for an individual hash policy - on a request attribute. - properties: - hashSourceIP: - description: |- - HashSourceIP should be set to true when request source IP hash based - load balancing is desired. It must be the only hash option field set, - otherwise this request hash policy object will be ignored. - type: boolean - headerHashOptions: - description: |- - HeaderHashOptions should be set when request header hash based load - balancing is desired. It must be the only hash option field set, - otherwise this request hash policy object will be ignored. - properties: - headerName: - description: |- - HeaderName is the name of the HTTP request header that will be used to - calculate the hash key. If the header specified is not present on a - request, no hash will be produced. - minLength: 1 - type: string - type: object - queryParameterHashOptions: - description: |- - QueryParameterHashOptions should be set when request query parameter hash based load - balancing is desired. It must be the only hash option field set, - otherwise this request hash policy object will be ignored. - properties: - parameterName: - description: |- - ParameterName is the name of the HTTP request query parameter that will be used to - calculate the hash key. If the query parameter specified is not present on a - request, no hash will be produced. - minLength: 1 - type: string - type: object - terminal: - description: |- - Terminal is a flag that allows for short-circuiting computing of a hash - for a given request. If set to true, and the request attribute specified - in the attribute hash options is present, no further hash policies will - be used to calculate a hash for the request. - type: boolean - type: object - type: array - strategy: - description: |- - Strategy specifies the policy used to balance requests - across the pool of backend pods. Valid policy names are - `Random`, `RoundRobin`, `WeightedLeastRequest`, `Cookie`, - and `RequestHash`. If an unknown strategy name is specified - or no policy is supplied, the default `RoundRobin` policy - is used. - type: string - type: object - protocol: - description: |- - Protocol may be used to specify (or override) the protocol used to reach this Service. - Values may be h2 or h2c. If omitted, protocol-selection falls back on Service annotations. - enum: - - h2 - - h2c - type: string - protocolVersion: - description: |- - This field sets the version of the GRPC protocol that Envoy uses to - send requests to the extension service. Since Contour always uses the - v3 Envoy API, this is currently fixed at "v3". However, other - protocol options will be available in future. - enum: - - v3 - type: string - services: - description: |- - Services specifies the set of Kubernetes Service resources that - receive GRPC extension API requests. - If no weights are specified for any of the entries in - this array, traffic will be spread evenly across all the - services. - Otherwise, traffic is balanced proportionally to the - Weight field in each entry. - items: - description: |- - ExtensionServiceTarget defines an Kubernetes Service to target with - extension service traffic. - properties: - name: - description: |- - Name is the name of Kubernetes service that will accept service - traffic. - type: string - port: - description: Port (defined as Integer) to proxy traffic to since - a service can have multiple defined. - exclusiveMaximum: true - maximum: 65536 - minimum: 1 - type: integer - weight: - description: Weight defines proportion of traffic to balance - to the Kubernetes Service. - format: int32 - type: integer - required: - - name - - port - type: object - minItems: 1 - type: array - timeoutPolicy: - description: The timeout policy for requests to the services. - properties: - idle: - description: |- - Timeout for how long the proxy should wait while there is no activity during single request/response (for HTTP/1.1) or stream (for HTTP/2). - Timeout will not trigger while HTTP/1.1 connection is idle between two consecutive requests. - If not specified, there is no per-route idle timeout, though a connection manager-wide - stream_idle_timeout default of 5m still applies. - pattern: ^(((\d*(\.\d*)?h)|(\d*(\.\d*)?m)|(\d*(\.\d*)?s)|(\d*(\.\d*)?ms)|(\d*(\.\d*)?us)|(\d*(\.\d*)?µs)|(\d*(\.\d*)?ns))+|infinity|infinite)$ - type: string - idleConnection: - description: |- - Timeout for how long connection from the proxy to the upstream service is kept when there are no active requests. - If not supplied, Envoy's default value of 1h applies. - pattern: ^(((\d*(\.\d*)?h)|(\d*(\.\d*)?m)|(\d*(\.\d*)?s)|(\d*(\.\d*)?ms)|(\d*(\.\d*)?us)|(\d*(\.\d*)?µs)|(\d*(\.\d*)?ns))+|infinity|infinite)$ - type: string - response: - description: |- - Timeout for receiving a response from the server after processing a request from client. - If not supplied, Envoy's default value of 15s applies. - pattern: ^(((\d*(\.\d*)?h)|(\d*(\.\d*)?m)|(\d*(\.\d*)?s)|(\d*(\.\d*)?ms)|(\d*(\.\d*)?us)|(\d*(\.\d*)?µs)|(\d*(\.\d*)?ns))+|infinity|infinite)$ - type: string - type: object - validation: - description: UpstreamValidation defines how to verify the backend - service's certificate - properties: - caSecret: - description: |- - Name or namespaced name of the Kubernetes secret used to validate the certificate presented by the backend. - The secret must contain key named ca.crt. - The name can be optionally prefixed with namespace "namespace/name". - When cross-namespace reference is used, TLSCertificateDelegation resource must exist in the namespace to grant access to the secret. - Max length should be the actual max possible length of a namespaced name (63 + 253 + 1 = 317) - maxLength: 317 - minLength: 1 - type: string - subjectName: - description: |- - Key which is expected to be present in the 'subjectAltName' of the presented certificate. - Deprecated: migrate to using the plural field subjectNames. - maxLength: 250 - minLength: 1 - type: string - subjectNames: - description: |- - List of keys, of which at least one is expected to be present in the 'subjectAltName of the - presented certificate. - items: - type: string - maxItems: 8 - minItems: 1 - type: array - required: - - caSecret - - subjectName - type: object - x-kubernetes-validations: - - message: subjectNames[0] must equal subjectName if set - rule: 'has(self.subjectNames) ? self.subjectNames[0] == self.subjectName - : true' - required: - - services - type: object - status: - description: |- - ExtensionServiceStatus defines the observed state of an - ExtensionService resource. - properties: - conditions: - description: |- - Conditions contains the current status of the ExtensionService resource. - Contour will update a single condition, `Valid`, that is in normal-true polarity. - Contour will not modify any other Conditions set in this block, - in case some other controller wants to add a Condition. - items: - description: |- - DetailedCondition is an extension of the normal Kubernetes conditions, with two extra - fields to hold sub-conditions, which provide more detailed reasons for the state (True or False) - of the condition. - `errors` holds information about sub-conditions which are fatal to that condition and render its state False. - `warnings` holds information about sub-conditions which are not fatal to that condition and do not force the state to be False. - Remember that Conditions have a type, a status, and a reason. - The type is the type of the condition, the most important one in this CRD set is `Valid`. - `Valid` is a positive-polarity condition: when it is `status: true` there are no problems. - In more detail, `status: true` means that the object is has been ingested into Contour with no errors. - `warnings` may still be present, and will be indicated in the Reason field. There must be zero entries in the `errors` - slice in this case. - `Valid`, `status: false` means that the object has had one or more fatal errors during processing into Contour. - The details of the errors will be present under the `errors` field. There must be at least one error in the `errors` - slice if `status` is `false`. - For DetailedConditions of types other than `Valid`, the Condition must be in the negative polarity. - When they have `status` `true`, there is an error. There must be at least one entry in the `errors` Subcondition slice. - When they have `status` `false`, there are no serious errors, and there must be zero entries in the `errors` slice. - In either case, there may be entries in the `warnings` slice. - Regardless of the polarity, the `reason` and `message` fields must be updated with either the detail of the reason - (if there is one and only one entry in total across both the `errors` and `warnings` slices), or - `MultipleReasons` if there is more than one entry. - properties: - errors: - description: |- - Errors contains a slice of relevant error subconditions for this object. - Subconditions are expected to appear when relevant (when there is a error), and disappear when not relevant. - An empty slice here indicates no errors. - items: - description: |- - SubCondition is a Condition-like type intended for use as a subcondition inside a DetailedCondition. - It contains a subset of the Condition fields. - It is intended for warnings and errors, so `type` names should use abnormal-true polarity, - that is, they should be of the form "ErrorPresent: true". - The expected lifecycle for these errors is that they should only be present when the error or warning is, - and should be removed when they are not relevant. - properties: - message: - description: |- - Message is a human readable message indicating details about the transition. - This may be an empty string. - maxLength: 32768 - type: string - reason: - description: |- - Reason contains a programmatic identifier indicating the reason for the condition's last transition. - Producers of specific condition types may define expected values and meanings for this field, - and whether the values are considered a guaranteed API. - The value should be a CamelCase string. - This field may not be empty. - maxLength: 1024 - minLength: 1 - pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ - type: string - status: - description: Status of the condition, one of True, False, - Unknown. - enum: - - "True" - - "False" - - Unknown - type: string - type: - description: |- - Type of condition in `CamelCase` or in `foo.example.com/CamelCase`. - This must be in abnormal-true polarity, that is, `ErrorFound` or `controller.io/ErrorFound`. - The regex it matches is (dns1123SubdomainFmt/)?(qualifiedNameFmt) - maxLength: 316 - pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ - type: string - required: - - message - - reason - - status - - type - type: object - type: array - lastTransitionTime: - description: |- - lastTransitionTime is the last time the condition transitioned from one status to another. - This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable. - format: date-time - type: string - message: - description: |- - message is a human readable message indicating details about the transition. - This may be an empty string. - maxLength: 32768 - type: string - observedGeneration: - description: |- - observedGeneration represents the .metadata.generation that the condition was set based upon. - For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date - with respect to the current state of the instance. - format: int64 - minimum: 0 - type: integer - reason: - description: |- - reason contains a programmatic identifier indicating the reason for the condition's last transition. - Producers of specific condition types may define expected values and meanings for this field, - and whether the values are considered a guaranteed API. - The value should be a CamelCase string. - This field may not be empty. - maxLength: 1024 - minLength: 1 - pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ - type: string - status: - description: status of the condition, one of True, False, Unknown. - enum: - - "True" - - "False" - - Unknown - type: string - type: - description: |- - type of condition in CamelCase or in foo.example.com/CamelCase. - --- - Many .condition.type values are consistent across resources like Available, but because arbitrary conditions can be - useful (see .node.status.conditions), the ability to deconflict is important. - The regex it matches is (dns1123SubdomainFmt/)?(qualifiedNameFmt) - maxLength: 316 - pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ - type: string - warnings: - description: |- - Warnings contains a slice of relevant warning subconditions for this object. - Subconditions are expected to appear when relevant (when there is a warning), and disappear when not relevant. - An empty slice here indicates no warnings. - items: - description: |- - SubCondition is a Condition-like type intended for use as a subcondition inside a DetailedCondition. - It contains a subset of the Condition fields. - It is intended for warnings and errors, so `type` names should use abnormal-true polarity, - that is, they should be of the form "ErrorPresent: true". - The expected lifecycle for these errors is that they should only be present when the error or warning is, - and should be removed when they are not relevant. - properties: - message: - description: |- - Message is a human readable message indicating details about the transition. - This may be an empty string. - maxLength: 32768 - type: string - reason: - description: |- - Reason contains a programmatic identifier indicating the reason for the condition's last transition. - Producers of specific condition types may define expected values and meanings for this field, - and whether the values are considered a guaranteed API. - The value should be a CamelCase string. - This field may not be empty. - maxLength: 1024 - minLength: 1 - pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ - type: string - status: - description: Status of the condition, one of True, False, - Unknown. - enum: - - "True" - - "False" - - Unknown - type: string - type: - description: |- - Type of condition in `CamelCase` or in `foo.example.com/CamelCase`. - This must be in abnormal-true polarity, that is, `ErrorFound` or `controller.io/ErrorFound`. - The regex it matches is (dns1123SubdomainFmt/)?(qualifiedNameFmt) - maxLength: 316 - pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ - type: string - required: - - message - - reason - - status - - type - type: object - type: array - required: - - lastTransitionTime - - message - - reason - - status - - type - type: object - type: array - x-kubernetes-list-map-keys: - - type - x-kubernetes-list-type: map - type: object - type: object - served: true - storage: true - subresources: - status: {} ---- -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.15.0 - name: httpproxies.projectcontour.io -spec: - preserveUnknownFields: false - group: projectcontour.io - names: - kind: HTTPProxy - listKind: HTTPProxyList - plural: httpproxies - shortNames: - - proxy - - proxies - singular: httpproxy - scope: Namespaced - versions: - - additionalPrinterColumns: - - description: Fully qualified domain name - jsonPath: .spec.virtualhost.fqdn - name: FQDN - type: string - - description: Secret with TLS credentials - jsonPath: .spec.virtualhost.tls.secretName - name: TLS Secret - type: string - - description: The current status of the HTTPProxy - jsonPath: .status.currentStatus - name: Status - type: string - - description: Description of the current status - jsonPath: .status.description - name: Status Description - type: string - name: v1 - schema: - openAPIV3Schema: - description: HTTPProxy is an Ingress CRD specification. - properties: - apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - type: string - kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - metadata: - type: object - spec: - description: HTTPProxySpec defines the spec of the CRD. - properties: - includes: - description: |- - Includes allow for specific routing configuration to be included from another HTTPProxy, - possibly in another namespace. - items: - description: Include describes a set of policies that can be applied - to an HTTPProxy in a namespace. - properties: - conditions: - description: |- - Conditions are a set of rules that are applied to included HTTPProxies. - In effect, they are added onto the Conditions of included HTTPProxy Route - structs. - When applied, they are merged using AND, with one exception: - There can be only one Prefix MatchCondition per Conditions slice. - More than one Prefix, or contradictory Conditions, will make the - include invalid. Exact and Regex match conditions are not allowed - on includes. - items: - description: |- - MatchCondition are a general holder for matching rules for HTTPProxies. - One of Prefix, Exact, Regex, Header or QueryParameter must be provided. - properties: - exact: - description: |- - Exact defines a exact match for a request. - This field is not allowed in include match conditions. - type: string - header: - description: Header specifies the header condition to - match. - properties: - contains: - description: |- - Contains specifies a substring that must be present in - the header value. - type: string - exact: - description: Exact specifies a string that the header - value must be equal to. - type: string - ignoreCase: - description: |- - IgnoreCase specifies that string matching should be case insensitive. - Note that this has no effect on the Regex parameter. - type: boolean - name: - description: |- - Name is the name of the header to match against. Name is required. - Header names are case insensitive. - type: string - notcontains: - description: |- - NotContains specifies a substring that must not be present - in the header value. - type: string - notexact: - description: |- - NoExact specifies a string that the header value must not be - equal to. The condition is true if the header has any other value. - type: string - notpresent: - description: |- - NotPresent specifies that condition is true when the named header - is not present. Note that setting NotPresent to false does not - make the condition true if the named header is present. - type: boolean - present: - description: |- - Present specifies that condition is true when the named header - is present, regardless of its value. Note that setting Present - to false does not make the condition true if the named header - is absent. - type: boolean - regex: - description: |- - Regex specifies a regular expression pattern that must match the header - value. - type: string - treatMissingAsEmpty: - description: |- - TreatMissingAsEmpty specifies if the header match rule specified header - does not exist, this header value will be treated as empty. Defaults to false. - Unlike the underlying Envoy implementation this is **only** supported for - negative matches (e.g. NotContains, NotExact). - type: boolean - required: - - name - type: object - prefix: - description: Prefix defines a prefix match for a request. - type: string - queryParameter: - description: QueryParameter specifies the query parameter - condition to match. - properties: - contains: - description: |- - Contains specifies a substring that must be present in - the query parameter value. - type: string - exact: - description: Exact specifies a string that the query - parameter value must be equal to. - type: string - ignoreCase: - description: |- - IgnoreCase specifies that string matching should be case insensitive. - Note that this has no effect on the Regex parameter. - type: boolean - name: - description: |- - Name is the name of the query parameter to match against. Name is required. - Query parameter names are case insensitive. - type: string - prefix: - description: Prefix defines a prefix match for the - query parameter value. - type: string - present: - description: |- - Present specifies that condition is true when the named query parameter - is present, regardless of its value. Note that setting Present - to false does not make the condition true if the named query parameter - is absent. - type: boolean - regex: - description: |- - Regex specifies a regular expression pattern that must match the query - parameter value. - type: string - suffix: - description: Suffix defines a suffix match for a query - parameter value. - type: string - required: - - name - type: object - regex: - description: |- - Regex defines a regex match for a request. - This field is not allowed in include match conditions. - type: string - type: object - type: array - name: - description: Name of the HTTPProxy - type: string - namespace: - description: Namespace of the HTTPProxy to include. Defaults - to the current namespace if not supplied. - type: string - required: - - name - type: object - type: array - ingressClassName: - description: |- - IngressClassName optionally specifies the ingress class to use for this - HTTPProxy. This replaces the deprecated `kubernetes.io/ingress.class` - annotation. For backwards compatibility, when that annotation is set, it - is given precedence over this field. - type: string - routes: - description: Routes are the ingress routes. If TCPProxy is present, - Routes is ignored. - items: - description: Route contains the set of routes for a virtual host. - properties: - authPolicy: - description: |- - AuthPolicy updates the authorization policy that was set - on the root HTTPProxy object for client requests that - match this route. - properties: - context: - additionalProperties: - type: string - description: |- - Context is a set of key/value pairs that are sent to the - authentication server in the check request. If a context - is provided at an enclosing scope, the entries are merged - such that the inner scope overrides matching keys from the - outer scope. - type: object - disabled: - description: |- - When true, this field disables client request authentication - for the scope of the policy. - type: boolean - type: object - conditions: - description: |- - Conditions are a set of rules that are applied to a Route. - When applied, they are merged using AND, with one exception: - There can be only one Prefix, Exact or Regex MatchCondition - per Conditions slice. More than one of these condition types, - or contradictory Conditions, will make the route invalid. - items: - description: |- - MatchCondition are a general holder for matching rules for HTTPProxies. - One of Prefix, Exact, Regex, Header or QueryParameter must be provided. - properties: - exact: - description: |- - Exact defines a exact match for a request. - This field is not allowed in include match conditions. - type: string - header: - description: Header specifies the header condition to - match. - properties: - contains: - description: |- - Contains specifies a substring that must be present in - the header value. - type: string - exact: - description: Exact specifies a string that the header - value must be equal to. - type: string - ignoreCase: - description: |- - IgnoreCase specifies that string matching should be case insensitive. - Note that this has no effect on the Regex parameter. - type: boolean - name: - description: |- - Name is the name of the header to match against. Name is required. - Header names are case insensitive. - type: string - notcontains: - description: |- - NotContains specifies a substring that must not be present - in the header value. - type: string - notexact: - description: |- - NoExact specifies a string that the header value must not be - equal to. The condition is true if the header has any other value. - type: string - notpresent: - description: |- - NotPresent specifies that condition is true when the named header - is not present. Note that setting NotPresent to false does not - make the condition true if the named header is present. - type: boolean - present: - description: |- - Present specifies that condition is true when the named header - is present, regardless of its value. Note that setting Present - to false does not make the condition true if the named header - is absent. - type: boolean - regex: - description: |- - Regex specifies a regular expression pattern that must match the header - value. - type: string - treatMissingAsEmpty: - description: |- - TreatMissingAsEmpty specifies if the header match rule specified header - does not exist, this header value will be treated as empty. Defaults to false. - Unlike the underlying Envoy implementation this is **only** supported for - negative matches (e.g. NotContains, NotExact). - type: boolean - required: - - name - type: object - prefix: - description: Prefix defines a prefix match for a request. - type: string - queryParameter: - description: QueryParameter specifies the query parameter - condition to match. - properties: - contains: - description: |- - Contains specifies a substring that must be present in - the query parameter value. - type: string - exact: - description: Exact specifies a string that the query - parameter value must be equal to. - type: string - ignoreCase: - description: |- - IgnoreCase specifies that string matching should be case insensitive. - Note that this has no effect on the Regex parameter. - type: boolean - name: - description: |- - Name is the name of the query parameter to match against. Name is required. - Query parameter names are case insensitive. - type: string - prefix: - description: Prefix defines a prefix match for the - query parameter value. - type: string - present: - description: |- - Present specifies that condition is true when the named query parameter - is present, regardless of its value. Note that setting Present - to false does not make the condition true if the named query parameter - is absent. - type: boolean - regex: - description: |- - Regex specifies a regular expression pattern that must match the query - parameter value. - type: string - suffix: - description: Suffix defines a suffix match for a query - parameter value. - type: string - required: - - name - type: object - regex: - description: |- - Regex defines a regex match for a request. - This field is not allowed in include match conditions. - type: string - type: object - type: array - cookieRewritePolicies: - description: |- - The policies for rewriting Set-Cookie header attributes. Note that - rewritten cookie names must be unique in this list. Order rewrite - policies are specified in does not matter. - items: - properties: - domainRewrite: - description: |- - DomainRewrite enables rewriting the Set-Cookie Domain element. - If not set, Domain will not be rewritten. - properties: - value: - description: |- - Value is the value to rewrite the Domain attribute to. - For now this is required. - maxLength: 4096 - minLength: 1 - pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ - type: string - required: - - value - type: object - name: - description: Name is the name of the cookie for which - attributes will be rewritten. - maxLength: 4096 - minLength: 1 - pattern: ^[^()<>@,;:\\"\/[\]?={} \t\x7f\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f]+$ - type: string - pathRewrite: - description: |- - PathRewrite enables rewriting the Set-Cookie Path element. - If not set, Path will not be rewritten. - properties: - value: - description: |- - Value is the value to rewrite the Path attribute to. - For now this is required. - maxLength: 4096 - minLength: 1 - pattern: ^[^;\x7f\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f]+$ - type: string - required: - - value - type: object - sameSite: - description: |- - SameSite enables rewriting the Set-Cookie SameSite element. - If not set, SameSite attribute will not be rewritten. - enum: - - Strict - - Lax - - None - type: string - secure: - description: |- - Secure enables rewriting the Set-Cookie Secure element. - If not set, Secure attribute will not be rewritten. - type: boolean - required: - - name - type: object - type: array - directResponsePolicy: - description: DirectResponsePolicy returns an arbitrary HTTP - response directly. - properties: - body: - description: |- - Body is the content of the response body. - If this setting is omitted, no body is included in the generated response. - Note: Body is not recommended to set too long - otherwise it can have significant resource usage impacts. - type: string - statusCode: - description: StatusCode is the HTTP response status to be - returned. - maximum: 599 - minimum: 200 - type: integer - required: - - statusCode - type: object - enableWebsockets: - description: Enables websocket support for the route. - type: boolean - healthCheckPolicy: - description: The health check policy for this route. - properties: - expectedStatuses: - description: |- - The ranges of HTTP response statuses considered healthy. Follow half-open - semantics, i.e. for each range the start is inclusive and the end is exclusive. - Must be within the range [100,600). If not specified, only a 200 response status - is considered healthy. - items: - properties: - end: - description: The end (exclusive) of a range of HTTP - status codes. - format: int64 - maximum: 600 - minimum: 101 - type: integer - start: - description: The start (inclusive) of a range of HTTP - status codes. - format: int64 - maximum: 599 - minimum: 100 - type: integer - required: - - end - - start - type: object - type: array - healthyThresholdCount: - description: The number of healthy health checks required - before a host is marked healthy - format: int64 - minimum: 0 - type: integer - host: - description: |- - The value of the host header in the HTTP health check request. - If left empty (default value), the name "contour-envoy-healthcheck" - will be used. - type: string - intervalSeconds: - description: The interval (seconds) between health checks - format: int64 - type: integer - path: - description: HTTP endpoint used to perform health checks - on upstream service - type: string - timeoutSeconds: - description: The time to wait (seconds) for a health check - response - format: int64 - type: integer - unhealthyThresholdCount: - description: The number of unhealthy health checks required - before a host is marked unhealthy - format: int64 - minimum: 0 - type: integer - required: - - path - type: object - internalRedirectPolicy: - description: The policy to define when to handle redirects responses - internally. - properties: - allowCrossSchemeRedirect: - default: Never - description: |- - AllowCrossSchemeRedirect Allow internal redirect to follow a target URI with a different scheme - than the value of x-forwarded-proto. - SafeOnly allows same scheme redirect and safe cross scheme redirect, which means if the downstream - scheme is HTTPS, both HTTPS and HTTP redirect targets are allowed, but if the downstream scheme - is HTTP, only HTTP redirect targets are allowed. - enum: - - Always - - Never - - SafeOnly - type: string - denyRepeatedRouteRedirect: - description: |- - If DenyRepeatedRouteRedirect is true, rejects redirect targets that are pointing to a route that has - been followed by a previous redirect from the current route. - type: boolean - maxInternalRedirects: - description: |- - MaxInternalRedirects An internal redirect is not handled, unless the number of previous internal - redirects that a downstream request has encountered is lower than this value. - format: int32 - type: integer - redirectResponseCodes: - description: |- - RedirectResponseCodes If unspecified, only 302 will be treated as internal redirect. - Only 301, 302, 303, 307 and 308 are valid values. - items: - description: RedirectResponseCode is a uint32 type alias - with validation to ensure that the value is valid. - enum: - - 301 - - 302 - - 303 - - 307 - - 308 - format: int32 - type: integer - type: array - type: object - ipAllowPolicy: - description: |- - IPAllowFilterPolicy is a list of ipv4/6 filter rules for which matching - requests should be allowed. All other requests will be denied. - Only one of IPAllowFilterPolicy and IPDenyFilterPolicy can be defined. - The rules defined here override any rules set on the root HTTPProxy. - items: - properties: - cidr: - description: |- - CIDR is a CIDR block of ipv4 or ipv6 addresses to filter on. This can also be - a bare IP address (without a mask) to filter on exactly one address. - type: string - source: - description: |- - Source indicates how to determine the ip address to filter on, and can be - one of two values: - - `Remote` filters on the ip address of the client, accounting for PROXY and - X-Forwarded-For as needed. - - `Peer` filters on the ip of the network request, ignoring PROXY and - X-Forwarded-For. - enum: - - Peer - - Remote - type: string - required: - - cidr - - source - type: object - type: array - ipDenyPolicy: - description: |- - IPDenyFilterPolicy is a list of ipv4/6 filter rules for which matching - requests should be denied. All other requests will be allowed. - Only one of IPAllowFilterPolicy and IPDenyFilterPolicy can be defined. - The rules defined here override any rules set on the root HTTPProxy. - items: - properties: - cidr: - description: |- - CIDR is a CIDR block of ipv4 or ipv6 addresses to filter on. This can also be - a bare IP address (without a mask) to filter on exactly one address. - type: string - source: - description: |- - Source indicates how to determine the ip address to filter on, and can be - one of two values: - - `Remote` filters on the ip address of the client, accounting for PROXY and - X-Forwarded-For as needed. - - `Peer` filters on the ip of the network request, ignoring PROXY and - X-Forwarded-For. - enum: - - Peer - - Remote - type: string - required: - - cidr - - source - type: object - type: array - jwtVerificationPolicy: - description: The policy for verifying JWTs for requests to this - route. - properties: - disabled: - description: |- - Disabled defines whether to disable all JWT verification for this - route. This can be used to opt specific routes out of the default - JWT provider for the HTTPProxy. At most one of this field or the - "require" field can be specified. - type: boolean - require: - description: |- - Require names a specific JWT provider (defined in the virtual host) - to require for the route. If specified, this field overrides the - default provider if one exists. If this field is not specified, - the default provider will be required if one exists. At most one of - this field or the "disabled" field can be specified. - type: string - type: object - loadBalancerPolicy: - description: The load balancing policy for this route. - properties: - requestHashPolicies: - description: |- - RequestHashPolicies contains a list of hash policies to apply when the - `RequestHash` load balancing strategy is chosen. If an element of the - supplied list of hash policies is invalid, it will be ignored. If the - list of hash policies is empty after validation, the load balancing - strategy will fall back to the default `RoundRobin`. - items: - description: |- - RequestHashPolicy contains configuration for an individual hash policy - on a request attribute. - properties: - hashSourceIP: - description: |- - HashSourceIP should be set to true when request source IP hash based - load balancing is desired. It must be the only hash option field set, - otherwise this request hash policy object will be ignored. - type: boolean - headerHashOptions: - description: |- - HeaderHashOptions should be set when request header hash based load - balancing is desired. It must be the only hash option field set, - otherwise this request hash policy object will be ignored. - properties: - headerName: - description: |- - HeaderName is the name of the HTTP request header that will be used to - calculate the hash key. If the header specified is not present on a - request, no hash will be produced. - minLength: 1 - type: string - type: object - queryParameterHashOptions: - description: |- - QueryParameterHashOptions should be set when request query parameter hash based load - balancing is desired. It must be the only hash option field set, - otherwise this request hash policy object will be ignored. - properties: - parameterName: - description: |- - ParameterName is the name of the HTTP request query parameter that will be used to - calculate the hash key. If the query parameter specified is not present on a - request, no hash will be produced. - minLength: 1 - type: string - type: object - terminal: - description: |- - Terminal is a flag that allows for short-circuiting computing of a hash - for a given request. If set to true, and the request attribute specified - in the attribute hash options is present, no further hash policies will - be used to calculate a hash for the request. - type: boolean - type: object - type: array - strategy: - description: |- - Strategy specifies the policy used to balance requests - across the pool of backend pods. Valid policy names are - `Random`, `RoundRobin`, `WeightedLeastRequest`, `Cookie`, - and `RequestHash`. If an unknown strategy name is specified - or no policy is supplied, the default `RoundRobin` policy - is used. - type: string - type: object - pathRewritePolicy: - description: |- - The policy for rewriting the path of the request URL - after the request has been routed to a Service. - properties: - replacePrefix: - description: ReplacePrefix describes how the path prefix - should be replaced. - items: - description: ReplacePrefix describes a path prefix replacement. - properties: - prefix: - description: |- - Prefix specifies the URL path prefix to be replaced. - If Prefix is specified, it must exactly match the MatchCondition - prefix that is rendered by the chain of including HTTPProxies - and only that path prefix will be replaced by Replacement. - This allows HTTPProxies that are included through multiple - roots to only replace specific path prefixes, leaving others - unmodified. - If Prefix is not specified, all routing prefixes rendered - by the include chain will be replaced. - minLength: 1 - type: string - replacement: - description: |- - Replacement is the string that the routing path prefix - will be replaced with. This must not be empty. - minLength: 1 - type: string - required: - - replacement - type: object - type: array - type: object - permitInsecure: - description: |- - Allow this path to respond to insecure requests over HTTP which are normally - not permitted when a `virtualhost.tls` block is present. - type: boolean - rateLimitPolicy: - description: The policy for rate limiting on the route. - properties: - global: - description: |- - Global defines global rate limiting parameters, i.e. parameters - defining descriptors that are sent to an external rate limit - service (RLS) for a rate limit decision on each request. - properties: - descriptors: - description: |- - Descriptors defines the list of descriptors that will - be generated and sent to the rate limit service. Each - descriptor contains 1+ key-value pair entries. - items: - description: RateLimitDescriptor defines a list of - key-value pair generators. - properties: - entries: - description: Entries is the list of key-value - pair generators. - items: - description: |- - RateLimitDescriptorEntry is a key-value pair generator. Exactly - one field on this struct must be non-nil. - properties: - genericKey: - description: GenericKey defines a descriptor - entry with a static key and value. - properties: - key: - description: |- - Key defines the key of the descriptor entry. If not set, the - key is set to "generic_key". - type: string - value: - description: Value defines the value - of the descriptor entry. - minLength: 1 - type: string - type: object - remoteAddress: - description: |- - RemoteAddress defines a descriptor entry with a key of "remote_address" - and a value equal to the client's IP address (from x-forwarded-for). - type: object - requestHeader: - description: |- - RequestHeader defines a descriptor entry that's populated only if - a given header is present on the request. The descriptor key is static, - and the descriptor value is equal to the value of the header. - properties: - descriptorKey: - description: DescriptorKey defines the - key to use on the descriptor entry. - minLength: 1 - type: string - headerName: - description: HeaderName defines the - name of the header to look for on - the request. - minLength: 1 - type: string - type: object - requestHeaderValueMatch: - description: |- - RequestHeaderValueMatch defines a descriptor entry that's populated - if the request's headers match a set of 1+ match criteria. The - descriptor key is "header_match", and the descriptor value is static. - properties: - expectMatch: - default: true - description: |- - ExpectMatch defines whether the request must positively match the match - criteria in order to generate a descriptor entry (i.e. true), or not - match the match criteria in order to generate a descriptor entry (i.e. false). - The default is true. - type: boolean - headers: - description: |- - Headers is a list of 1+ match criteria to apply against the request - to determine whether to populate the descriptor entry or not. - items: - description: |- - HeaderMatchCondition specifies how to conditionally match against HTTP - headers. The Name field is required, only one of Present, NotPresent, - Contains, NotContains, Exact, NotExact and Regex can be set. - For negative matching rules only (e.g. NotContains or NotExact) you can set - TreatMissingAsEmpty. - IgnoreCase has no effect for Regex. - properties: - contains: - description: |- - Contains specifies a substring that must be present in - the header value. - type: string - exact: - description: Exact specifies a - string that the header value - must be equal to. - type: string - ignoreCase: - description: |- - IgnoreCase specifies that string matching should be case insensitive. - Note that this has no effect on the Regex parameter. - type: boolean - name: - description: |- - Name is the name of the header to match against. Name is required. - Header names are case insensitive. - type: string - notcontains: - description: |- - NotContains specifies a substring that must not be present - in the header value. - type: string - notexact: - description: |- - NoExact specifies a string that the header value must not be - equal to. The condition is true if the header has any other value. - type: string - notpresent: - description: |- - NotPresent specifies that condition is true when the named header - is not present. Note that setting NotPresent to false does not - make the condition true if the named header is present. - type: boolean - present: - description: |- - Present specifies that condition is true when the named header - is present, regardless of its value. Note that setting Present - to false does not make the condition true if the named header - is absent. - type: boolean - regex: - description: |- - Regex specifies a regular expression pattern that must match the header - value. - type: string - treatMissingAsEmpty: - description: |- - TreatMissingAsEmpty specifies if the header match rule specified header - does not exist, this header value will be treated as empty. Defaults to false. - Unlike the underlying Envoy implementation this is **only** supported for - negative matches (e.g. NotContains, NotExact). - type: boolean - required: - - name - type: object - minItems: 1 - type: array - value: - description: Value defines the value - of the descriptor entry. - minLength: 1 - type: string - type: object - type: object - minItems: 1 - type: array - type: object - minItems: 1 - type: array - disabled: - description: |- - Disabled configures the HTTPProxy to not use - the default global rate limit policy defined by the Contour configuration. - type: boolean - type: object - local: - description: |- - Local defines local rate limiting parameters, i.e. parameters - for rate limiting that occurs within each Envoy pod as requests - are handled. - properties: - burst: - description: |- - Burst defines the number of requests above the requests per - unit that should be allowed within a short period of time. - format: int32 - type: integer - requests: - description: |- - Requests defines how many requests per unit of time should - be allowed before rate limiting occurs. - format: int32 - minimum: 1 - type: integer - responseHeadersToAdd: - description: |- - ResponseHeadersToAdd is an optional list of response headers to - set when a request is rate-limited. - items: - description: HeaderValue represents a header name/value - pair - properties: - name: - description: Name represents a key of a header - minLength: 1 - type: string - value: - description: Value represents the value of a header - specified by a key - minLength: 1 - type: string - required: - - name - - value - type: object - type: array - responseStatusCode: - description: |- - ResponseStatusCode is the HTTP status code to use for responses - to rate-limited requests. Codes must be in the 400-599 range - (inclusive). If not specified, the Envoy default of 429 (Too - Many Requests) is used. - format: int32 - maximum: 599 - minimum: 400 - type: integer - unit: - description: |- - Unit defines the period of time within which requests - over the limit will be rate limited. Valid values are - "second", "minute" and "hour". - enum: - - second - - minute - - hour - type: string - required: - - requests - - unit - type: object - type: object - requestHeadersPolicy: - description: |- - The policy for managing request headers during proxying. - You may dynamically rewrite the Host header to be forwarded - upstream to the content of a request header using - the below format "%REQ(X-Header-Name)%". If the value of the header - is empty, it is ignored. - *NOTE: Pay attention to the potential security implications of using this option. - Provided header must come from trusted source. - **NOTE: The header rewrite is only done while forwarding and has no bearing - on the routing decision. - properties: - remove: - description: Remove specifies a list of HTTP header names - to remove. - items: - type: string - type: array - set: - description: |- - Set specifies a list of HTTP header values that will be set in the HTTP header. - If the header does not exist it will be added, otherwise it will be overwritten with the new value. - items: - description: HeaderValue represents a header name/value - pair - properties: - name: - description: Name represents a key of a header - minLength: 1 - type: string - value: - description: Value represents the value of a header - specified by a key - minLength: 1 - type: string - required: - - name - - value - type: object - type: array - type: object - requestRedirectPolicy: - description: RequestRedirectPolicy defines an HTTP redirection. - properties: - hostname: - description: |- - Hostname is the precise hostname to be used in the value of the `Location` - header in the response. - When empty, the hostname of the request is used. - No wildcards are allowed. - maxLength: 253 - minLength: 1 - pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ - type: string - path: - description: |- - Path allows for redirection to a different path from the - original on the request. The path must start with a - leading slash. - Note: Only one of Path or Prefix can be defined. - pattern: ^\/.*$ - type: string - port: - description: |- - Port is the port to be used in the value of the `Location` - header in the response. - When empty, port (if specified) of the request is used. - format: int32 - maximum: 65535 - minimum: 1 - type: integer - prefix: - description: |- - Prefix defines the value to swap the matched prefix or path with. - The prefix must start with a leading slash. - Note: Only one of Path or Prefix can be defined. - pattern: ^\/.*$ - type: string - scheme: - description: |- - Scheme is the scheme to be used in the value of the `Location` - header in the response. - When empty, the scheme of the request is used. - enum: - - http - - https - type: string - statusCode: - default: 302 - description: StatusCode is the HTTP status code to be used - in response. - enum: - - 301 - - 302 - type: integer - type: object - responseHeadersPolicy: - description: |- - The policy for managing response headers during proxying. - Rewriting the 'Host' header is not supported. - properties: - remove: - description: Remove specifies a list of HTTP header names - to remove. - items: - type: string - type: array - set: - description: |- - Set specifies a list of HTTP header values that will be set in the HTTP header. - If the header does not exist it will be added, otherwise it will be overwritten with the new value. - items: - description: HeaderValue represents a header name/value - pair - properties: - name: - description: Name represents a key of a header - minLength: 1 - type: string - value: - description: Value represents the value of a header - specified by a key - minLength: 1 - type: string - required: - - name - - value - type: object - type: array - type: object - retryPolicy: - description: The retry policy for this route. - properties: - count: - default: 1 - description: |- - NumRetries is maximum allowed number of retries. - If set to -1, then retries are disabled. - If set to 0 or not supplied, the value is set - to the Envoy default of 1. - format: int64 - minimum: -1 - type: integer - perTryTimeout: - description: |- - PerTryTimeout specifies the timeout per retry attempt. - Ignored if NumRetries is not supplied. - pattern: ^(((\d*(\.\d*)?h)|(\d*(\.\d*)?m)|(\d*(\.\d*)?s)|(\d*(\.\d*)?ms)|(\d*(\.\d*)?us)|(\d*(\.\d*)?µs)|(\d*(\.\d*)?ns))+|infinity|infinite)$ - type: string - retriableStatusCodes: - description: |- - RetriableStatusCodes specifies the HTTP status codes that should be retried. - This field is only respected when you include `retriable-status-codes` in the `RetryOn` field. - items: - format: int32 - type: integer - type: array - retryOn: - description: |- - RetryOn specifies the conditions on which to retry a request. - Supported [HTTP conditions](https://www.envoyproxy.io/docs/envoy/latest/configuration/http/http_filters/router_filter#x-envoy-retry-on): - - `5xx` - - `gateway-error` - - `reset` - - `connect-failure` - - `retriable-4xx` - - `refused-stream` - - `retriable-status-codes` - - `retriable-headers` - Supported [gRPC conditions](https://www.envoyproxy.io/docs/envoy/latest/configuration/http/http_filters/router_filter#x-envoy-retry-grpc-on): - - `cancelled` - - `deadline-exceeded` - - `internal` - - `resource-exhausted` - - `unavailable` - items: - description: RetryOn is a string type alias with validation - to ensure that the value is valid. - enum: - - 5xx - - gateway-error - - reset - - connect-failure - - retriable-4xx - - refused-stream - - retriable-status-codes - - retriable-headers - - cancelled - - deadline-exceeded - - internal - - resource-exhausted - - unavailable - type: string - type: array - type: object - services: - description: Services are the services to proxy traffic. - items: - description: Service defines an Kubernetes Service to proxy - traffic. - properties: - cookieRewritePolicies: - description: The policies for rewriting Set-Cookie header - attributes. - items: - properties: - domainRewrite: - description: |- - DomainRewrite enables rewriting the Set-Cookie Domain element. - If not set, Domain will not be rewritten. - properties: - value: - description: |- - Value is the value to rewrite the Domain attribute to. - For now this is required. - maxLength: 4096 - minLength: 1 - pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ - type: string - required: - - value - type: object - name: - description: Name is the name of the cookie for - which attributes will be rewritten. - maxLength: 4096 - minLength: 1 - pattern: ^[^()<>@,;:\\"\/[\]?={} \t\x7f\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f]+$ - type: string - pathRewrite: - description: |- - PathRewrite enables rewriting the Set-Cookie Path element. - If not set, Path will not be rewritten. - properties: - value: - description: |- - Value is the value to rewrite the Path attribute to. - For now this is required. - maxLength: 4096 - minLength: 1 - pattern: ^[^;\x7f\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f]+$ - type: string - required: - - value - type: object - sameSite: - description: |- - SameSite enables rewriting the Set-Cookie SameSite element. - If not set, SameSite attribute will not be rewritten. - enum: - - Strict - - Lax - - None - type: string - secure: - description: |- - Secure enables rewriting the Set-Cookie Secure element. - If not set, Secure attribute will not be rewritten. - type: boolean - required: - - name - type: object - type: array - healthPort: - description: |- - HealthPort is the port for this service healthcheck. - If not specified, Port is used for service healthchecks. - maximum: 65535 - minimum: 1 - type: integer - mirror: - description: |- - If Mirror is true the Service will receive a read only mirror of the traffic for this route. - If Mirror is true, then fractional mirroring can be enabled by optionally setting the Weight - field. Legal values for Weight are 1-100. Omitting the Weight field will result in 100% mirroring. - NOTE: Setting Weight explicitly to 0 will unexpectedly result in 100% traffic mirroring. This - occurs since we cannot distinguish omitted fields from those explicitly set to their default - values - type: boolean - name: - description: |- - Name is the name of Kubernetes service to proxy traffic. - Names defined here will be used to look up corresponding endpoints which contain the ips to route. - type: string - port: - description: Port (defined as Integer) to proxy traffic - to since a service can have multiple defined. - exclusiveMaximum: true - maximum: 65536 - minimum: 1 - type: integer - protocol: - description: |- - Protocol may be used to specify (or override) the protocol used to reach this Service. - Values may be tls, h2, h2c. If omitted, protocol-selection falls back on Service annotations. - enum: - - h2 - - h2c - - tls - type: string - requestHeadersPolicy: - description: The policy for managing request headers during - proxying. - properties: - remove: - description: Remove specifies a list of HTTP header - names to remove. - items: - type: string - type: array - set: - description: |- - Set specifies a list of HTTP header values that will be set in the HTTP header. - If the header does not exist it will be added, otherwise it will be overwritten with the new value. - items: - description: HeaderValue represents a header name/value - pair - properties: - name: - description: Name represents a key of a header - minLength: 1 - type: string - value: - description: Value represents the value of a - header specified by a key - minLength: 1 - type: string - required: - - name - - value - type: object - type: array - type: object - responseHeadersPolicy: - description: |- - The policy for managing response headers during proxying. - Rewriting the 'Host' header is not supported. - properties: - remove: - description: Remove specifies a list of HTTP header - names to remove. - items: - type: string - type: array - set: - description: |- - Set specifies a list of HTTP header values that will be set in the HTTP header. - If the header does not exist it will be added, otherwise it will be overwritten with the new value. - items: - description: HeaderValue represents a header name/value - pair - properties: - name: - description: Name represents a key of a header - minLength: 1 - type: string - value: - description: Value represents the value of a - header specified by a key - minLength: 1 - type: string - required: - - name - - value - type: object - type: array - type: object - slowStartPolicy: - description: Slow start will gradually increase amount - of traffic to a newly added endpoint. - properties: - aggression: - default: "1.0" - description: |- - The speed of traffic increase over the slow start window. - Defaults to 1.0, so that endpoint would get linearly increasing amount of traffic. - When increasing the value for this parameter, the speed of traffic ramp-up increases non-linearly. - The value of aggression parameter should be greater than 0.0. - More info: https://www.envoyproxy.io/docs/envoy/latest/intro/arch_overview/upstream/load_balancing/slow_start - pattern: ^([0-9]+([.][0-9]+)?|[.][0-9]+)$ - type: string - minWeightPercent: - default: 10 - description: |- - The minimum or starting percentage of traffic to send to new endpoints. - A non-zero value helps avoid a too small initial weight, which may cause endpoints in slow start mode to receive no traffic in the beginning of the slow start window. - If not specified, the default is 10%. - format: int32 - maximum: 100 - minimum: 0 - type: integer - window: - description: |- - The duration of slow start window. - Duration is expressed in the Go [Duration format](https://godoc.org/time#ParseDuration). - Valid time units are "ns", "us" (or "µs"), "ms", "s", "m", "h". - pattern: ^(((\d*(\.\d*)?h)|(\d*(\.\d*)?m)|(\d*(\.\d*)?s)|(\d*(\.\d*)?ms)|(\d*(\.\d*)?us)|(\d*(\.\d*)?µs)|(\d*(\.\d*)?ns))+)$ - type: string - required: - - window - type: object - validation: - description: UpstreamValidation defines how to verify - the backend service's certificate - properties: - caSecret: - description: |- - Name or namespaced name of the Kubernetes secret used to validate the certificate presented by the backend. - The secret must contain key named ca.crt. - The name can be optionally prefixed with namespace "namespace/name". - When cross-namespace reference is used, TLSCertificateDelegation resource must exist in the namespace to grant access to the secret. - Max length should be the actual max possible length of a namespaced name (63 + 253 + 1 = 317) - maxLength: 317 - minLength: 1 - type: string - subjectName: - description: |- - Key which is expected to be present in the 'subjectAltName' of the presented certificate. - Deprecated: migrate to using the plural field subjectNames. - maxLength: 250 - minLength: 1 - type: string - subjectNames: - description: |- - List of keys, of which at least one is expected to be present in the 'subjectAltName of the - presented certificate. - items: - type: string - maxItems: 8 - minItems: 1 - type: array - required: - - caSecret - - subjectName - type: object - x-kubernetes-validations: - - message: subjectNames[0] must equal subjectName if set - rule: 'has(self.subjectNames) ? self.subjectNames[0] - == self.subjectName : true' - weight: - description: Weight defines percentage of traffic to balance - traffic - format: int64 - minimum: 0 - type: integer - required: - - name - - port - type: object - type: array - timeoutPolicy: - description: The timeout policy for this route. - properties: - idle: - description: |- - Timeout for how long the proxy should wait while there is no activity during single request/response (for HTTP/1.1) or stream (for HTTP/2). - Timeout will not trigger while HTTP/1.1 connection is idle between two consecutive requests. - If not specified, there is no per-route idle timeout, though a connection manager-wide - stream_idle_timeout default of 5m still applies. - pattern: ^(((\d*(\.\d*)?h)|(\d*(\.\d*)?m)|(\d*(\.\d*)?s)|(\d*(\.\d*)?ms)|(\d*(\.\d*)?us)|(\d*(\.\d*)?µs)|(\d*(\.\d*)?ns))+|infinity|infinite)$ - type: string - idleConnection: - description: |- - Timeout for how long connection from the proxy to the upstream service is kept when there are no active requests. - If not supplied, Envoy's default value of 1h applies. - pattern: ^(((\d*(\.\d*)?h)|(\d*(\.\d*)?m)|(\d*(\.\d*)?s)|(\d*(\.\d*)?ms)|(\d*(\.\d*)?us)|(\d*(\.\d*)?µs)|(\d*(\.\d*)?ns))+|infinity|infinite)$ - type: string - response: - description: |- - Timeout for receiving a response from the server after processing a request from client. - If not supplied, Envoy's default value of 15s applies. - pattern: ^(((\d*(\.\d*)?h)|(\d*(\.\d*)?m)|(\d*(\.\d*)?s)|(\d*(\.\d*)?ms)|(\d*(\.\d*)?us)|(\d*(\.\d*)?µs)|(\d*(\.\d*)?ns))+|infinity|infinite)$ - type: string - type: object - type: object - type: array - tcpproxy: - description: TCPProxy holds TCP proxy information. - properties: - healthCheckPolicy: - description: The health check policy for this tcp proxy - properties: - healthyThresholdCount: - description: The number of healthy health checks required - before a host is marked healthy - format: int32 - type: integer - intervalSeconds: - description: The interval (seconds) between health checks - format: int64 - type: integer - timeoutSeconds: - description: The time to wait (seconds) for a health check - response - format: int64 - type: integer - unhealthyThresholdCount: - description: The number of unhealthy health checks required - before a host is marked unhealthy - format: int32 - type: integer - type: object - include: - description: Include specifies that this tcpproxy should be delegated - to another HTTPProxy. - properties: - name: - description: Name of the child HTTPProxy - type: string - namespace: - description: Namespace of the HTTPProxy to include. Defaults - to the current namespace if not supplied. - type: string - required: - - name - type: object - includes: - description: |- - IncludesDeprecated allow for specific routing configuration to be appended to another HTTPProxy in another namespace. - Exists due to a mistake when developing HTTPProxy and the field was marked plural - when it should have been singular. This field should stay to not break backwards compatibility to v1 users. - properties: - name: - description: Name of the child HTTPProxy - type: string - namespace: - description: Namespace of the HTTPProxy to include. Defaults - to the current namespace if not supplied. - type: string - required: - - name - type: object - loadBalancerPolicy: - description: |- - The load balancing policy for the backend services. Note that the - `Cookie` and `RequestHash` load balancing strategies cannot be used - here. - properties: - requestHashPolicies: - description: |- - RequestHashPolicies contains a list of hash policies to apply when the - `RequestHash` load balancing strategy is chosen. If an element of the - supplied list of hash policies is invalid, it will be ignored. If the - list of hash policies is empty after validation, the load balancing - strategy will fall back to the default `RoundRobin`. - items: - description: |- - RequestHashPolicy contains configuration for an individual hash policy - on a request attribute. - properties: - hashSourceIP: - description: |- - HashSourceIP should be set to true when request source IP hash based - load balancing is desired. It must be the only hash option field set, - otherwise this request hash policy object will be ignored. - type: boolean - headerHashOptions: - description: |- - HeaderHashOptions should be set when request header hash based load - balancing is desired. It must be the only hash option field set, - otherwise this request hash policy object will be ignored. - properties: - headerName: - description: |- - HeaderName is the name of the HTTP request header that will be used to - calculate the hash key. If the header specified is not present on a - request, no hash will be produced. - minLength: 1 - type: string - type: object - queryParameterHashOptions: - description: |- - QueryParameterHashOptions should be set when request query parameter hash based load - balancing is desired. It must be the only hash option field set, - otherwise this request hash policy object will be ignored. - properties: - parameterName: - description: |- - ParameterName is the name of the HTTP request query parameter that will be used to - calculate the hash key. If the query parameter specified is not present on a - request, no hash will be produced. - minLength: 1 - type: string - type: object - terminal: - description: |- - Terminal is a flag that allows for short-circuiting computing of a hash - for a given request. If set to true, and the request attribute specified - in the attribute hash options is present, no further hash policies will - be used to calculate a hash for the request. - type: boolean - type: object - type: array - strategy: - description: |- - Strategy specifies the policy used to balance requests - across the pool of backend pods. Valid policy names are - `Random`, `RoundRobin`, `WeightedLeastRequest`, `Cookie`, - and `RequestHash`. If an unknown strategy name is specified - or no policy is supplied, the default `RoundRobin` policy - is used. - type: string - type: object - services: - description: Services are the services to proxy traffic - items: - description: Service defines an Kubernetes Service to proxy - traffic. - properties: - cookieRewritePolicies: - description: The policies for rewriting Set-Cookie header - attributes. - items: - properties: - domainRewrite: - description: |- - DomainRewrite enables rewriting the Set-Cookie Domain element. - If not set, Domain will not be rewritten. - properties: - value: - description: |- - Value is the value to rewrite the Domain attribute to. - For now this is required. - maxLength: 4096 - minLength: 1 - pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ - type: string - required: - - value - type: object - name: - description: Name is the name of the cookie for which - attributes will be rewritten. - maxLength: 4096 - minLength: 1 - pattern: ^[^()<>@,;:\\"\/[\]?={} \t\x7f\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f]+$ - type: string - pathRewrite: - description: |- - PathRewrite enables rewriting the Set-Cookie Path element. - If not set, Path will not be rewritten. - properties: - value: - description: |- - Value is the value to rewrite the Path attribute to. - For now this is required. - maxLength: 4096 - minLength: 1 - pattern: ^[^;\x7f\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f]+$ - type: string - required: - - value - type: object - sameSite: - description: |- - SameSite enables rewriting the Set-Cookie SameSite element. - If not set, SameSite attribute will not be rewritten. - enum: - - Strict - - Lax - - None - type: string - secure: - description: |- - Secure enables rewriting the Set-Cookie Secure element. - If not set, Secure attribute will not be rewritten. - type: boolean - required: - - name - type: object - type: array - healthPort: - description: |- - HealthPort is the port for this service healthcheck. - If not specified, Port is used for service healthchecks. - maximum: 65535 - minimum: 1 - type: integer - mirror: - description: |- - If Mirror is true the Service will receive a read only mirror of the traffic for this route. - If Mirror is true, then fractional mirroring can be enabled by optionally setting the Weight - field. Legal values for Weight are 1-100. Omitting the Weight field will result in 100% mirroring. - NOTE: Setting Weight explicitly to 0 will unexpectedly result in 100% traffic mirroring. This - occurs since we cannot distinguish omitted fields from those explicitly set to their default - values - type: boolean - name: - description: |- - Name is the name of Kubernetes service to proxy traffic. - Names defined here will be used to look up corresponding endpoints which contain the ips to route. - type: string - port: - description: Port (defined as Integer) to proxy traffic - to since a service can have multiple defined. - exclusiveMaximum: true - maximum: 65536 - minimum: 1 - type: integer - protocol: - description: |- - Protocol may be used to specify (or override) the protocol used to reach this Service. - Values may be tls, h2, h2c. If omitted, protocol-selection falls back on Service annotations. - enum: - - h2 - - h2c - - tls - type: string - requestHeadersPolicy: - description: The policy for managing request headers during - proxying. - properties: - remove: - description: Remove specifies a list of HTTP header - names to remove. - items: - type: string - type: array - set: - description: |- - Set specifies a list of HTTP header values that will be set in the HTTP header. - If the header does not exist it will be added, otherwise it will be overwritten with the new value. - items: - description: HeaderValue represents a header name/value - pair - properties: - name: - description: Name represents a key of a header - minLength: 1 - type: string - value: - description: Value represents the value of a header - specified by a key - minLength: 1 - type: string - required: - - name - - value - type: object - type: array - type: object - responseHeadersPolicy: - description: |- - The policy for managing response headers during proxying. - Rewriting the 'Host' header is not supported. - properties: - remove: - description: Remove specifies a list of HTTP header - names to remove. - items: - type: string - type: array - set: - description: |- - Set specifies a list of HTTP header values that will be set in the HTTP header. - If the header does not exist it will be added, otherwise it will be overwritten with the new value. - items: - description: HeaderValue represents a header name/value - pair - properties: - name: - description: Name represents a key of a header - minLength: 1 - type: string - value: - description: Value represents the value of a header - specified by a key - minLength: 1 - type: string - required: - - name - - value - type: object - type: array - type: object - slowStartPolicy: - description: Slow start will gradually increase amount of - traffic to a newly added endpoint. - properties: - aggression: - default: "1.0" - description: |- - The speed of traffic increase over the slow start window. - Defaults to 1.0, so that endpoint would get linearly increasing amount of traffic. - When increasing the value for this parameter, the speed of traffic ramp-up increases non-linearly. - The value of aggression parameter should be greater than 0.0. - More info: https://www.envoyproxy.io/docs/envoy/latest/intro/arch_overview/upstream/load_balancing/slow_start - pattern: ^([0-9]+([.][0-9]+)?|[.][0-9]+)$ - type: string - minWeightPercent: - default: 10 - description: |- - The minimum or starting percentage of traffic to send to new endpoints. - A non-zero value helps avoid a too small initial weight, which may cause endpoints in slow start mode to receive no traffic in the beginning of the slow start window. - If not specified, the default is 10%. - format: int32 - maximum: 100 - minimum: 0 - type: integer - window: - description: |- - The duration of slow start window. - Duration is expressed in the Go [Duration format](https://godoc.org/time#ParseDuration). - Valid time units are "ns", "us" (or "µs"), "ms", "s", "m", "h". - pattern: ^(((\d*(\.\d*)?h)|(\d*(\.\d*)?m)|(\d*(\.\d*)?s)|(\d*(\.\d*)?ms)|(\d*(\.\d*)?us)|(\d*(\.\d*)?µs)|(\d*(\.\d*)?ns))+)$ - type: string - required: - - window - type: object - validation: - description: UpstreamValidation defines how to verify the - backend service's certificate - properties: - caSecret: - description: |- - Name or namespaced name of the Kubernetes secret used to validate the certificate presented by the backend. - The secret must contain key named ca.crt. - The name can be optionally prefixed with namespace "namespace/name". - When cross-namespace reference is used, TLSCertificateDelegation resource must exist in the namespace to grant access to the secret. - Max length should be the actual max possible length of a namespaced name (63 + 253 + 1 = 317) - maxLength: 317 - minLength: 1 - type: string - subjectName: - description: |- - Key which is expected to be present in the 'subjectAltName' of the presented certificate. - Deprecated: migrate to using the plural field subjectNames. - maxLength: 250 - minLength: 1 - type: string - subjectNames: - description: |- - List of keys, of which at least one is expected to be present in the 'subjectAltName of the - presented certificate. - items: - type: string - maxItems: 8 - minItems: 1 - type: array - required: - - caSecret - - subjectName - type: object - x-kubernetes-validations: - - message: subjectNames[0] must equal subjectName if set - rule: 'has(self.subjectNames) ? self.subjectNames[0] == - self.subjectName : true' - weight: - description: Weight defines percentage of traffic to balance - traffic - format: int64 - minimum: 0 - type: integer - required: - - name - - port - type: object - type: array - type: object - virtualhost: - description: |- - Virtualhost appears at most once. If it is present, the object is considered - to be a "root" HTTPProxy. - properties: - authorization: - description: |- - This field configures an extension service to perform - authorization for this virtual host. Authorization can - only be configured on virtual hosts that have TLS enabled. - If the TLS configuration requires client certificate - validation, the client certificate is always included in the - authentication check request. - properties: - authPolicy: - description: |- - AuthPolicy sets a default authorization policy for client requests. - This policy will be used unless overridden by individual routes. - properties: - context: - additionalProperties: - type: string - description: |- - Context is a set of key/value pairs that are sent to the - authentication server in the check request. If a context - is provided at an enclosing scope, the entries are merged - such that the inner scope overrides matching keys from the - outer scope. - type: object - disabled: - description: |- - When true, this field disables client request authentication - for the scope of the policy. - type: boolean - type: object - extensionRef: - description: ExtensionServiceRef specifies the extension resource - that will authorize client requests. - properties: - apiVersion: - description: |- - API version of the referent. - If this field is not specified, the default "projectcontour.io/v1alpha1" will be used - minLength: 1 - type: string - name: - description: |- - Name of the referent. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - minLength: 1 - type: string - namespace: - description: |- - Namespace of the referent. - If this field is not specifies, the namespace of the resource that targets the referent will be used. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/ - minLength: 1 - type: string - type: object - failOpen: - description: |- - If FailOpen is true, the client request is forwarded to the upstream service - even if the authorization server fails to respond. This field should not be - set in most cases. It is intended for use only while migrating applications - from internal authorization to Contour external authorization. - type: boolean - responseTimeout: - description: |- - ResponseTimeout configures maximum time to wait for a check response from the authorization server. - Timeout durations are expressed in the Go [Duration format](https://godoc.org/time#ParseDuration). - Valid time units are "ns", "us" (or "µs"), "ms", "s", "m", "h". - The string "infinity" is also a valid input and specifies no timeout. - pattern: ^(((\d*(\.\d*)?h)|(\d*(\.\d*)?m)|(\d*(\.\d*)?s)|(\d*(\.\d*)?ms)|(\d*(\.\d*)?us)|(\d*(\.\d*)?µs)|(\d*(\.\d*)?ns))+|infinity|infinite)$ - type: string - withRequestBody: - description: WithRequestBody specifies configuration for sending - the client request's body to authorization server. - properties: - allowPartialMessage: - description: If AllowPartialMessage is true, then Envoy - will buffer the body until MaxRequestBytes are reached. - type: boolean - maxRequestBytes: - default: 1024 - description: MaxRequestBytes sets the maximum size of - message body ExtAuthz filter will hold in-memory. - format: int32 - minimum: 1 - type: integer - packAsBytes: - description: If PackAsBytes is true, the body sent to - Authorization Server is in raw bytes. - type: boolean - type: object - type: object - corsPolicy: - description: Specifies the cross-origin policy to apply to the - VirtualHost. - properties: - allowCredentials: - description: Specifies whether the resource allows credentials. - type: boolean - allowHeaders: - description: AllowHeaders specifies the content for the *access-control-allow-headers* - header. - items: - description: CORSHeaderValue specifies the value of the - string headers returned by a cross-domain request. - pattern: ^[a-zA-Z0-9!#$%&'*+.^_`|~-]+$ - type: string - minItems: 1 - type: array - allowMethods: - description: AllowMethods specifies the content for the *access-control-allow-methods* - header. - items: - description: CORSHeaderValue specifies the value of the - string headers returned by a cross-domain request. - pattern: ^[a-zA-Z0-9!#$%&'*+.^_`|~-]+$ - type: string - minItems: 1 - type: array - allowOrigin: - description: |- - AllowOrigin specifies the origins that will be allowed to do CORS requests. - Allowed values include "*" which signifies any origin is allowed, an exact - origin of the form "scheme://host[:port]" (where port is optional), or a valid - regex pattern. - Note that regex patterns are validated and a simple "glob" pattern (e.g. *.foo.com) - will be rejected or produce unexpected matches when applied as a regex. - items: - type: string - minItems: 1 - type: array - allowPrivateNetwork: - description: |- - AllowPrivateNetwork specifies whether to allow private network requests. - See https://developer.chrome.com/blog/private-network-access-preflight. - type: boolean - exposeHeaders: - description: ExposeHeaders Specifies the content for the *access-control-expose-headers* - header. - items: - description: CORSHeaderValue specifies the value of the - string headers returned by a cross-domain request. - pattern: ^[a-zA-Z0-9!#$%&'*+.^_`|~-]+$ - type: string - minItems: 1 - type: array - maxAge: - description: |- - MaxAge indicates for how long the results of a preflight request can be cached. - MaxAge durations are expressed in the Go [Duration format](https://godoc.org/time#ParseDuration). - Valid time units are "ns", "us" (or "µs"), "ms", "s", "m", "h". - Only positive values are allowed while 0 disables the cache requiring a preflight OPTIONS - check for all cross-origin requests. - pattern: ^(((\d*(\.\d*)?h)|(\d*(\.\d*)?m)|(\d*(\.\d*)?s)|(\d*(\.\d*)?ms)|(\d*(\.\d*)?us)|(\d*(\.\d*)?µs)|(\d*(\.\d*)?ns))+|0)$ - type: string - required: - - allowMethods - - allowOrigin - type: object - fqdn: - description: |- - The fully qualified domain name of the root of the ingress tree - all leaves of the DAG rooted at this object relate to the fqdn. - pattern: ^(\*\.)?[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ - type: string - ipAllowPolicy: - description: |- - IPAllowFilterPolicy is a list of ipv4/6 filter rules for which matching - requests should be allowed. All other requests will be denied. - Only one of IPAllowFilterPolicy and IPDenyFilterPolicy can be defined. - The rules defined here may be overridden in a Route. - items: - properties: - cidr: - description: |- - CIDR is a CIDR block of ipv4 or ipv6 addresses to filter on. This can also be - a bare IP address (without a mask) to filter on exactly one address. - type: string - source: - description: |- - Source indicates how to determine the ip address to filter on, and can be - one of two values: - - `Remote` filters on the ip address of the client, accounting for PROXY and - X-Forwarded-For as needed. - - `Peer` filters on the ip of the network request, ignoring PROXY and - X-Forwarded-For. - enum: - - Peer - - Remote - type: string - required: - - cidr - - source - type: object - type: array - ipDenyPolicy: - description: |- - IPDenyFilterPolicy is a list of ipv4/6 filter rules for which matching - requests should be denied. All other requests will be allowed. - Only one of IPAllowFilterPolicy and IPDenyFilterPolicy can be defined. - The rules defined here may be overridden in a Route. - items: - properties: - cidr: - description: |- - CIDR is a CIDR block of ipv4 or ipv6 addresses to filter on. This can also be - a bare IP address (without a mask) to filter on exactly one address. - type: string - source: - description: |- - Source indicates how to determine the ip address to filter on, and can be - one of two values: - - `Remote` filters on the ip address of the client, accounting for PROXY and - X-Forwarded-For as needed. - - `Peer` filters on the ip of the network request, ignoring PROXY and - X-Forwarded-For. - enum: - - Peer - - Remote - type: string - required: - - cidr - - source - type: object - type: array - jwtProviders: - description: Providers to use for verifying JSON Web Tokens (JWTs) - on the virtual host. - items: - description: JWTProvider defines how to verify JWTs on requests. - properties: - audiences: - description: |- - Audiences that JWTs are allowed to have in the "aud" field. - If not provided, JWT audiences are not checked. - items: - type: string - type: array - default: - description: |- - Whether the provider should apply to all - routes in the HTTPProxy/its includes by - default. At most one provider can be marked - as the default. If no provider is marked - as the default, individual routes must explicitly - identify the provider they require. - type: boolean - forwardJWT: - description: |- - Whether the JWT should be forwarded to the backend - service after successful verification. By default, - the JWT is not forwarded. - type: boolean - issuer: - description: |- - Issuer that JWTs are required to have in the "iss" field. - If not provided, JWT issuers are not checked. - type: string - name: - description: Unique name for the provider. - minLength: 1 - type: string - remoteJWKS: - description: Remote JWKS to use for verifying JWT signatures. - properties: - cacheDuration: - description: |- - How long to cache the JWKS locally. If not specified, - Envoy's default of 5m applies. - pattern: ^(((\d*(\.\d*)?h)|(\d*(\.\d*)?m)|(\d*(\.\d*)?s)|(\d*(\.\d*)?ms)|(\d*(\.\d*)?us)|(\d*(\.\d*)?µs)|(\d*(\.\d*)?ns))+)$ - type: string - dnsLookupFamily: - description: |- - The DNS IP address resolution policy for the JWKS URI. - When configured as "v4", the DNS resolver will only perform a lookup - for addresses in the IPv4 family. If "v6" is configured, the DNS resolver - will only perform a lookup for addresses in the IPv6 family. - If "all" is configured, the DNS resolver - will perform a lookup for addresses in both the IPv4 and IPv6 family. - If "auto" is configured, the DNS resolver will first perform a lookup - for addresses in the IPv6 family and fallback to a lookup for addresses - in the IPv4 family. If not specified, the Contour-wide setting defined - in the config file or ContourConfiguration applies (defaults to "auto"). - See https://www.envoyproxy.io/docs/envoy/latest/api-v3/config/cluster/v3/cluster.proto.html#envoy-v3-api-enum-config-cluster-v3-cluster-dnslookupfamily - for more information. - enum: - - auto - - v4 - - v6 - type: string - timeout: - description: |- - How long to wait for a response from the URI. - If not specified, a default of 1s applies. - pattern: ^(((\d*(\.\d*)?h)|(\d*(\.\d*)?m)|(\d*(\.\d*)?s)|(\d*(\.\d*)?ms)|(\d*(\.\d*)?us)|(\d*(\.\d*)?µs)|(\d*(\.\d*)?ns))+)$ - type: string - uri: - description: The URI for the JWKS. - minLength: 1 - type: string - validation: - description: UpstreamValidation defines how to verify - the JWKS's TLS certificate. - properties: - caSecret: - description: |- - Name or namespaced name of the Kubernetes secret used to validate the certificate presented by the backend. - The secret must contain key named ca.crt. - The name can be optionally prefixed with namespace "namespace/name". - When cross-namespace reference is used, TLSCertificateDelegation resource must exist in the namespace to grant access to the secret. - Max length should be the actual max possible length of a namespaced name (63 + 253 + 1 = 317) - maxLength: 317 - minLength: 1 - type: string - subjectName: - description: |- - Key which is expected to be present in the 'subjectAltName' of the presented certificate. - Deprecated: migrate to using the plural field subjectNames. - maxLength: 250 - minLength: 1 - type: string - subjectNames: - description: |- - List of keys, of which at least one is expected to be present in the 'subjectAltName of the - presented certificate. - items: - type: string - maxItems: 8 - minItems: 1 - type: array - required: - - caSecret - - subjectName - type: object - x-kubernetes-validations: - - message: subjectNames[0] must equal subjectName if - set - rule: 'has(self.subjectNames) ? self.subjectNames[0] - == self.subjectName : true' - required: - - uri - type: object - required: - - name - - remoteJWKS - type: object - type: array - rateLimitPolicy: - description: The policy for rate limiting on the virtual host. - properties: - global: - description: |- - Global defines global rate limiting parameters, i.e. parameters - defining descriptors that are sent to an external rate limit - service (RLS) for a rate limit decision on each request. - properties: - descriptors: - description: |- - Descriptors defines the list of descriptors that will - be generated and sent to the rate limit service. Each - descriptor contains 1+ key-value pair entries. - items: - description: RateLimitDescriptor defines a list of key-value - pair generators. - properties: - entries: - description: Entries is the list of key-value pair - generators. - items: - description: |- - RateLimitDescriptorEntry is a key-value pair generator. Exactly - one field on this struct must be non-nil. - properties: - genericKey: - description: GenericKey defines a descriptor - entry with a static key and value. - properties: - key: - description: |- - Key defines the key of the descriptor entry. If not set, the - key is set to "generic_key". - type: string - value: - description: Value defines the value of - the descriptor entry. - minLength: 1 - type: string - type: object - remoteAddress: - description: |- - RemoteAddress defines a descriptor entry with a key of "remote_address" - and a value equal to the client's IP address (from x-forwarded-for). - type: object - requestHeader: - description: |- - RequestHeader defines a descriptor entry that's populated only if - a given header is present on the request. The descriptor key is static, - and the descriptor value is equal to the value of the header. - properties: - descriptorKey: - description: DescriptorKey defines the - key to use on the descriptor entry. - minLength: 1 - type: string - headerName: - description: HeaderName defines the name - of the header to look for on the request. - minLength: 1 - type: string - type: object - requestHeaderValueMatch: - description: |- - RequestHeaderValueMatch defines a descriptor entry that's populated - if the request's headers match a set of 1+ match criteria. The - descriptor key is "header_match", and the descriptor value is static. - properties: - expectMatch: - default: true - description: |- - ExpectMatch defines whether the request must positively match the match - criteria in order to generate a descriptor entry (i.e. true), or not - match the match criteria in order to generate a descriptor entry (i.e. false). - The default is true. - type: boolean - headers: - description: |- - Headers is a list of 1+ match criteria to apply against the request - to determine whether to populate the descriptor entry or not. - items: - description: |- - HeaderMatchCondition specifies how to conditionally match against HTTP - headers. The Name field is required, only one of Present, NotPresent, - Contains, NotContains, Exact, NotExact and Regex can be set. - For negative matching rules only (e.g. NotContains or NotExact) you can set - TreatMissingAsEmpty. - IgnoreCase has no effect for Regex. - properties: - contains: - description: |- - Contains specifies a substring that must be present in - the header value. - type: string - exact: - description: Exact specifies a string - that the header value must be - equal to. - type: string - ignoreCase: - description: |- - IgnoreCase specifies that string matching should be case insensitive. - Note that this has no effect on the Regex parameter. - type: boolean - name: - description: |- - Name is the name of the header to match against. Name is required. - Header names are case insensitive. - type: string - notcontains: - description: |- - NotContains specifies a substring that must not be present - in the header value. - type: string - notexact: - description: |- - NoExact specifies a string that the header value must not be - equal to. The condition is true if the header has any other value. - type: string - notpresent: - description: |- - NotPresent specifies that condition is true when the named header - is not present. Note that setting NotPresent to false does not - make the condition true if the named header is present. - type: boolean - present: - description: |- - Present specifies that condition is true when the named header - is present, regardless of its value. Note that setting Present - to false does not make the condition true if the named header - is absent. - type: boolean - regex: - description: |- - Regex specifies a regular expression pattern that must match the header - value. - type: string - treatMissingAsEmpty: - description: |- - TreatMissingAsEmpty specifies if the header match rule specified header - does not exist, this header value will be treated as empty. Defaults to false. - Unlike the underlying Envoy implementation this is **only** supported for - negative matches (e.g. NotContains, NotExact). - type: boolean - required: - - name - type: object - minItems: 1 - type: array - value: - description: Value defines the value of - the descriptor entry. - minLength: 1 - type: string - type: object - type: object - minItems: 1 - type: array - type: object - minItems: 1 - type: array - disabled: - description: |- - Disabled configures the HTTPProxy to not use - the default global rate limit policy defined by the Contour configuration. - type: boolean - type: object - local: - description: |- - Local defines local rate limiting parameters, i.e. parameters - for rate limiting that occurs within each Envoy pod as requests - are handled. - properties: - burst: - description: |- - Burst defines the number of requests above the requests per - unit that should be allowed within a short period of time. - format: int32 - type: integer - requests: - description: |- - Requests defines how many requests per unit of time should - be allowed before rate limiting occurs. - format: int32 - minimum: 1 - type: integer - responseHeadersToAdd: - description: |- - ResponseHeadersToAdd is an optional list of response headers to - set when a request is rate-limited. - items: - description: HeaderValue represents a header name/value - pair - properties: - name: - description: Name represents a key of a header - minLength: 1 - type: string - value: - description: Value represents the value of a header - specified by a key - minLength: 1 - type: string - required: - - name - - value - type: object - type: array - responseStatusCode: - description: |- - ResponseStatusCode is the HTTP status code to use for responses - to rate-limited requests. Codes must be in the 400-599 range - (inclusive). If not specified, the Envoy default of 429 (Too - Many Requests) is used. - format: int32 - maximum: 599 - minimum: 400 - type: integer - unit: - description: |- - Unit defines the period of time within which requests - over the limit will be rate limited. Valid values are - "second", "minute" and "hour". - enum: - - second - - minute - - hour - type: string - required: - - requests - - unit - type: object - type: object - tls: - description: |- - If present the fields describes TLS properties of the virtual - host. The SNI names that will be matched on are described in fqdn, - the tls.secretName secret must contain a certificate that itself - contains a name that matches the FQDN. - properties: - clientValidation: - description: |- - ClientValidation defines how to verify the client certificate - when an external client establishes a TLS connection to Envoy. - This setting: - 1. Enables TLS client certificate validation. - 2. Specifies how the client certificate will be validated (i.e. - validation required or skipped). - Note: Setting client certificate validation to be skipped should - be only used in conjunction with an external authorization server that - performs client validation as Contour will ensure client certificates - are passed along. - properties: - caSecret: - description: |- - Name of a Kubernetes secret that contains a CA certificate bundle. - The secret must contain key named ca.crt. - The client certificate must validate against the certificates in the bundle. - If specified and SkipClientCertValidation is true, client certificates will - be required on requests. - The name can be optionally prefixed with namespace "namespace/name". - When cross-namespace reference is used, TLSCertificateDelegation resource must exist in the namespace to grant access to the secret. - minLength: 1 - type: string - crlOnlyVerifyLeafCert: - description: |- - If this option is set to true, only the certificate at the end of the - certificate chain will be subject to validation by CRL. - type: boolean - crlSecret: - description: |- - Name of a Kubernetes opaque secret that contains a concatenated list of PEM encoded CRLs. - The secret must contain key named crl.pem. - This field will be used to verify that a client certificate has not been revoked. - CRLs must be available from all CAs, unless crlOnlyVerifyLeafCert is true. - Large CRL lists are not supported since individual secrets are limited to 1MiB in size. - The name can be optionally prefixed with namespace "namespace/name". - When cross-namespace reference is used, TLSCertificateDelegation resource must exist in the namespace to grant access to the secret. - minLength: 1 - type: string - forwardClientCertificate: - description: |- - ForwardClientCertificate adds the selected data from the passed client TLS certificate - to the x-forwarded-client-cert header. - properties: - cert: - description: Client cert in URL encoded PEM format. - type: boolean - chain: - description: Client cert chain (including the leaf - cert) in URL encoded PEM format. - type: boolean - dns: - description: DNS type Subject Alternative Names of - the client cert. - type: boolean - subject: - description: Subject of the client cert. - type: boolean - uri: - description: URI type Subject Alternative Name of - the client cert. - type: boolean - type: object - optionalClientCertificate: - description: |- - OptionalClientCertificate when set to true will request a client certificate - but allow the connection to continue if the client does not provide one. - If a client certificate is sent, it will be verified according to the - other properties, which includes disabling validation if - SkipClientCertValidation is set. Defaults to false. - type: boolean - skipClientCertValidation: - description: |- - SkipClientCertValidation disables downstream client certificate - validation. Defaults to false. This field is intended to be used in - conjunction with external authorization in order to enable the external - authorization server to validate client certificates. When this field - is set to true, client certificates are requested but not verified by - Envoy. If CACertificate is specified, client certificates are required on - requests, but not verified. If external authorization is in use, they are - presented to the external authorization server. - type: boolean - type: object - enableFallbackCertificate: - description: |- - EnableFallbackCertificate defines if the vhost should allow a default certificate to - be applied which handles all requests which don't match the SNI defined in this vhost. - type: boolean - maximumProtocolVersion: - description: |- - MaximumProtocolVersion is the maximum TLS version this vhost should - negotiate. Valid options are `1.2` and `1.3` (default). Any other value - defaults to TLS 1.3. - type: string - minimumProtocolVersion: - description: |- - MinimumProtocolVersion is the minimum TLS version this vhost should - negotiate. Valid options are `1.2` (default) and `1.3`. Any other value - defaults to TLS 1.2. - type: string - passthrough: - description: |- - Passthrough defines whether the encrypted TLS handshake will be - passed through to the backing cluster. Either Passthrough or - SecretName must be specified, but not both. - type: boolean - secretName: - description: |- - SecretName is the name of a TLS secret. - Either SecretName or Passthrough must be specified, but not both. - If specified, the named secret must contain a matching certificate - for the virtual host's FQDN. - The name can be optionally prefixed with namespace "namespace/name". - When cross-namespace reference is used, TLSCertificateDelegation resource must exist in the namespace to grant access to the secret. - type: string - type: object - required: - - fqdn - type: object - type: object - status: - default: - currentStatus: NotReconciled - description: Waiting for controller - description: Status is a container for computed information about the - HTTPProxy. - properties: - conditions: - description: |- - Conditions contains information about the current status of the HTTPProxy, - in an upstream-friendly container. - Contour will update a single condition, `Valid`, that is in normal-true polarity. - That is, when `currentStatus` is `valid`, the `Valid` condition will be `status: true`, - and vice versa. - Contour will leave untouched any other Conditions set in this block, - in case some other controller wants to add a Condition. - If you are another controller owner and wish to add a condition, you *should* - namespace your condition with a label, like `controller.domain.com/ConditionName`. - items: - description: |- - DetailedCondition is an extension of the normal Kubernetes conditions, with two extra - fields to hold sub-conditions, which provide more detailed reasons for the state (True or False) - of the condition. - `errors` holds information about sub-conditions which are fatal to that condition and render its state False. - `warnings` holds information about sub-conditions which are not fatal to that condition and do not force the state to be False. - Remember that Conditions have a type, a status, and a reason. - The type is the type of the condition, the most important one in this CRD set is `Valid`. - `Valid` is a positive-polarity condition: when it is `status: true` there are no problems. - In more detail, `status: true` means that the object is has been ingested into Contour with no errors. - `warnings` may still be present, and will be indicated in the Reason field. There must be zero entries in the `errors` - slice in this case. - `Valid`, `status: false` means that the object has had one or more fatal errors during processing into Contour. - The details of the errors will be present under the `errors` field. There must be at least one error in the `errors` - slice if `status` is `false`. - For DetailedConditions of types other than `Valid`, the Condition must be in the negative polarity. - When they have `status` `true`, there is an error. There must be at least one entry in the `errors` Subcondition slice. - When they have `status` `false`, there are no serious errors, and there must be zero entries in the `errors` slice. - In either case, there may be entries in the `warnings` slice. - Regardless of the polarity, the `reason` and `message` fields must be updated with either the detail of the reason - (if there is one and only one entry in total across both the `errors` and `warnings` slices), or - `MultipleReasons` if there is more than one entry. - properties: - errors: - description: |- - Errors contains a slice of relevant error subconditions for this object. - Subconditions are expected to appear when relevant (when there is a error), and disappear when not relevant. - An empty slice here indicates no errors. - items: - description: |- - SubCondition is a Condition-like type intended for use as a subcondition inside a DetailedCondition. - It contains a subset of the Condition fields. - It is intended for warnings and errors, so `type` names should use abnormal-true polarity, - that is, they should be of the form "ErrorPresent: true". - The expected lifecycle for these errors is that they should only be present when the error or warning is, - and should be removed when they are not relevant. - properties: - message: - description: |- - Message is a human readable message indicating details about the transition. - This may be an empty string. - maxLength: 32768 - type: string - reason: - description: |- - Reason contains a programmatic identifier indicating the reason for the condition's last transition. - Producers of specific condition types may define expected values and meanings for this field, - and whether the values are considered a guaranteed API. - The value should be a CamelCase string. - This field may not be empty. - maxLength: 1024 - minLength: 1 - pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ - type: string - status: - description: Status of the condition, one of True, False, - Unknown. - enum: - - "True" - - "False" - - Unknown - type: string - type: - description: |- - Type of condition in `CamelCase` or in `foo.example.com/CamelCase`. - This must be in abnormal-true polarity, that is, `ErrorFound` or `controller.io/ErrorFound`. - The regex it matches is (dns1123SubdomainFmt/)?(qualifiedNameFmt) - maxLength: 316 - pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ - type: string - required: - - message - - reason - - status - - type - type: object - type: array - lastTransitionTime: - description: |- - lastTransitionTime is the last time the condition transitioned from one status to another. - This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable. - format: date-time - type: string - message: - description: |- - message is a human readable message indicating details about the transition. - This may be an empty string. - maxLength: 32768 - type: string - observedGeneration: - description: |- - observedGeneration represents the .metadata.generation that the condition was set based upon. - For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date - with respect to the current state of the instance. - format: int64 - minimum: 0 - type: integer - reason: - description: |- - reason contains a programmatic identifier indicating the reason for the condition's last transition. - Producers of specific condition types may define expected values and meanings for this field, - and whether the values are considered a guaranteed API. - The value should be a CamelCase string. - This field may not be empty. - maxLength: 1024 - minLength: 1 - pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ - type: string - status: - description: status of the condition, one of True, False, Unknown. - enum: - - "True" - - "False" - - Unknown - type: string - type: - description: |- - type of condition in CamelCase or in foo.example.com/CamelCase. - --- - Many .condition.type values are consistent across resources like Available, but because arbitrary conditions can be - useful (see .node.status.conditions), the ability to deconflict is important. - The regex it matches is (dns1123SubdomainFmt/)?(qualifiedNameFmt) - maxLength: 316 - pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ - type: string - warnings: - description: |- - Warnings contains a slice of relevant warning subconditions for this object. - Subconditions are expected to appear when relevant (when there is a warning), and disappear when not relevant. - An empty slice here indicates no warnings. - items: - description: |- - SubCondition is a Condition-like type intended for use as a subcondition inside a DetailedCondition. - It contains a subset of the Condition fields. - It is intended for warnings and errors, so `type` names should use abnormal-true polarity, - that is, they should be of the form "ErrorPresent: true". - The expected lifecycle for these errors is that they should only be present when the error or warning is, - and should be removed when they are not relevant. - properties: - message: - description: |- - Message is a human readable message indicating details about the transition. - This may be an empty string. - maxLength: 32768 - type: string - reason: - description: |- - Reason contains a programmatic identifier indicating the reason for the condition's last transition. - Producers of specific condition types may define expected values and meanings for this field, - and whether the values are considered a guaranteed API. - The value should be a CamelCase string. - This field may not be empty. - maxLength: 1024 - minLength: 1 - pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ - type: string - status: - description: Status of the condition, one of True, False, - Unknown. - enum: - - "True" - - "False" - - Unknown - type: string - type: - description: |- - Type of condition in `CamelCase` or in `foo.example.com/CamelCase`. - This must be in abnormal-true polarity, that is, `ErrorFound` or `controller.io/ErrorFound`. - The regex it matches is (dns1123SubdomainFmt/)?(qualifiedNameFmt) - maxLength: 316 - pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ - type: string - required: - - message - - reason - - status - - type - type: object - type: array - required: - - lastTransitionTime - - message - - reason - - status - - type - type: object - type: array - x-kubernetes-list-map-keys: - - type - x-kubernetes-list-type: map - currentStatus: - type: string - description: - type: string - loadBalancer: - description: LoadBalancer contains the current status of the load - balancer. - properties: - ingress: - description: |- - Ingress is a list containing ingress points for the load-balancer. - Traffic intended for the service should be sent to these ingress points. - items: - description: |- - LoadBalancerIngress represents the status of a load-balancer ingress point: - traffic intended for the service should be sent to an ingress point. - properties: - hostname: - description: |- - Hostname is set for load-balancer ingress points that are DNS based - (typically AWS load-balancers) - type: string - ip: - description: |- - IP is set for load-balancer ingress points that are IP based - (typically GCE or OpenStack load-balancers) - type: string - ipMode: - description: |- - IPMode specifies how the load-balancer IP behaves, and may only be specified when the ip field is specified. - Setting this to "VIP" indicates that traffic is delivered to the node with - the destination set to the load-balancer's IP and port. - Setting this to "Proxy" indicates that traffic is delivered to the node or pod with - the destination set to the node's IP and node port or the pod's IP and port. - Service implementations may use this information to adjust traffic routing. - type: string - ports: - description: |- - Ports is a list of records of service ports - If used, every port defined in the service should have an entry in it - items: - properties: - error: - description: |- - Error is to record the problem with the service port - The format of the error shall comply with the following rules: - - built-in error values shall be specified in this file and those shall use - CamelCase names - - cloud provider specific error values must have names that comply with the - format foo.example.com/CamelCase. - --- - The regex it matches is (dns1123SubdomainFmt/)?(qualifiedNameFmt) - maxLength: 316 - pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ - type: string - port: - description: Port is the port number of the service - port of which status is recorded here - format: int32 - type: integer - protocol: - default: TCP - description: |- - Protocol is the protocol of the service port of which status is recorded here - The supported values are: "TCP", "UDP", "SCTP" - type: string - required: - - port - - protocol - type: object - type: array - x-kubernetes-list-type: atomic - type: object - type: array - x-kubernetes-list-type: atomic - type: object - type: object - required: - - metadata - - spec - type: object - served: true - storage: true - subresources: - status: {} ---- -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.15.0 - name: tlscertificatedelegations.projectcontour.io -spec: - preserveUnknownFields: false - group: projectcontour.io - names: - kind: TLSCertificateDelegation - listKind: TLSCertificateDelegationList - plural: tlscertificatedelegations - shortNames: - - tlscerts - singular: tlscertificatedelegation - scope: Namespaced - versions: - - name: v1 - schema: - openAPIV3Schema: - description: |- - TLSCertificateDelegation is an TLS Certificate Delegation CRD specification. - See design/tls-certificate-delegation.md for details. - properties: - apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - type: string - kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - metadata: - type: object - spec: - description: TLSCertificateDelegationSpec defines the spec of the CRD - properties: - delegations: - items: - description: |- - CertificateDelegation maps the authority to reference a secret - in the current namespace to a set of namespaces. - properties: - secretName: - description: required, the name of a secret in the current namespace. - type: string - targetNamespaces: - description: |- - required, the namespaces the authority to reference the - secret will be delegated to. - If TargetNamespaces is nil or empty, the CertificateDelegation' - is ignored. If the TargetNamespace list contains the character, "*" - the secret will be delegated to all namespaces. - items: - type: string - type: array - required: - - secretName - - targetNamespaces - type: object - type: array - required: - - delegations - type: object - status: - description: |- - TLSCertificateDelegationStatus allows for the status of the delegation - to be presented to the user. - properties: - conditions: - description: |- - Conditions contains information about the current status of the HTTPProxy, - in an upstream-friendly container. - Contour will update a single condition, `Valid`, that is in normal-true polarity. - That is, when `currentStatus` is `valid`, the `Valid` condition will be `status: true`, - and vice versa. - Contour will leave untouched any other Conditions set in this block, - in case some other controller wants to add a Condition. - If you are another controller owner and wish to add a condition, you *should* - namespace your condition with a label, like `controller.domain.com\ConditionName`. - items: - description: |- - DetailedCondition is an extension of the normal Kubernetes conditions, with two extra - fields to hold sub-conditions, which provide more detailed reasons for the state (True or False) - of the condition. - `errors` holds information about sub-conditions which are fatal to that condition and render its state False. - `warnings` holds information about sub-conditions which are not fatal to that condition and do not force the state to be False. - Remember that Conditions have a type, a status, and a reason. - The type is the type of the condition, the most important one in this CRD set is `Valid`. - `Valid` is a positive-polarity condition: when it is `status: true` there are no problems. - In more detail, `status: true` means that the object is has been ingested into Contour with no errors. - `warnings` may still be present, and will be indicated in the Reason field. There must be zero entries in the `errors` - slice in this case. - `Valid`, `status: false` means that the object has had one or more fatal errors during processing into Contour. - The details of the errors will be present under the `errors` field. There must be at least one error in the `errors` - slice if `status` is `false`. - For DetailedConditions of types other than `Valid`, the Condition must be in the negative polarity. - When they have `status` `true`, there is an error. There must be at least one entry in the `errors` Subcondition slice. - When they have `status` `false`, there are no serious errors, and there must be zero entries in the `errors` slice. - In either case, there may be entries in the `warnings` slice. - Regardless of the polarity, the `reason` and `message` fields must be updated with either the detail of the reason - (if there is one and only one entry in total across both the `errors` and `warnings` slices), or - `MultipleReasons` if there is more than one entry. - properties: - errors: - description: |- - Errors contains a slice of relevant error subconditions for this object. - Subconditions are expected to appear when relevant (when there is a error), and disappear when not relevant. - An empty slice here indicates no errors. - items: - description: |- - SubCondition is a Condition-like type intended for use as a subcondition inside a DetailedCondition. - It contains a subset of the Condition fields. - It is intended for warnings and errors, so `type` names should use abnormal-true polarity, - that is, they should be of the form "ErrorPresent: true". - The expected lifecycle for these errors is that they should only be present when the error or warning is, - and should be removed when they are not relevant. - properties: - message: - description: |- - Message is a human readable message indicating details about the transition. - This may be an empty string. - maxLength: 32768 - type: string - reason: - description: |- - Reason contains a programmatic identifier indicating the reason for the condition's last transition. - Producers of specific condition types may define expected values and meanings for this field, - and whether the values are considered a guaranteed API. - The value should be a CamelCase string. - This field may not be empty. - maxLength: 1024 - minLength: 1 - pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ - type: string - status: - description: Status of the condition, one of True, False, - Unknown. - enum: - - "True" - - "False" - - Unknown - type: string - type: - description: |- - Type of condition in `CamelCase` or in `foo.example.com/CamelCase`. - This must be in abnormal-true polarity, that is, `ErrorFound` or `controller.io/ErrorFound`. - The regex it matches is (dns1123SubdomainFmt/)?(qualifiedNameFmt) - maxLength: 316 - pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ - type: string - required: - - message - - reason - - status - - type - type: object - type: array - lastTransitionTime: - description: |- - lastTransitionTime is the last time the condition transitioned from one status to another. - This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable. - format: date-time - type: string - message: - description: |- - message is a human readable message indicating details about the transition. - This may be an empty string. - maxLength: 32768 - type: string - observedGeneration: - description: |- - observedGeneration represents the .metadata.generation that the condition was set based upon. - For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date - with respect to the current state of the instance. - format: int64 - minimum: 0 - type: integer - reason: - description: |- - reason contains a programmatic identifier indicating the reason for the condition's last transition. - Producers of specific condition types may define expected values and meanings for this field, - and whether the values are considered a guaranteed API. - The value should be a CamelCase string. - This field may not be empty. - maxLength: 1024 - minLength: 1 - pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ - type: string - status: - description: status of the condition, one of True, False, Unknown. - enum: - - "True" - - "False" - - Unknown - type: string - type: - description: |- - type of condition in CamelCase or in foo.example.com/CamelCase. - --- - Many .condition.type values are consistent across resources like Available, but because arbitrary conditions can be - useful (see .node.status.conditions), the ability to deconflict is important. - The regex it matches is (dns1123SubdomainFmt/)?(qualifiedNameFmt) - maxLength: 316 - pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ - type: string - warnings: - description: |- - Warnings contains a slice of relevant warning subconditions for this object. - Subconditions are expected to appear when relevant (when there is a warning), and disappear when not relevant. - An empty slice here indicates no warnings. - items: - description: |- - SubCondition is a Condition-like type intended for use as a subcondition inside a DetailedCondition. - It contains a subset of the Condition fields. - It is intended for warnings and errors, so `type` names should use abnormal-true polarity, - that is, they should be of the form "ErrorPresent: true". - The expected lifecycle for these errors is that they should only be present when the error or warning is, - and should be removed when they are not relevant. - properties: - message: - description: |- - Message is a human readable message indicating details about the transition. - This may be an empty string. - maxLength: 32768 - type: string - reason: - description: |- - Reason contains a programmatic identifier indicating the reason for the condition's last transition. - Producers of specific condition types may define expected values and meanings for this field, - and whether the values are considered a guaranteed API. - The value should be a CamelCase string. - This field may not be empty. - maxLength: 1024 - minLength: 1 - pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ - type: string - status: - description: Status of the condition, one of True, False, - Unknown. - enum: - - "True" - - "False" - - Unknown - type: string - type: - description: |- - Type of condition in `CamelCase` or in `foo.example.com/CamelCase`. - This must be in abnormal-true polarity, that is, `ErrorFound` or `controller.io/ErrorFound`. - The regex it matches is (dns1123SubdomainFmt/)?(qualifiedNameFmt) - maxLength: 316 - pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ - type: string - required: - - message - - reason - - status - - type - type: object - type: array - required: - - lastTransitionTime - - message - - reason - - status - - type - type: object - type: array - x-kubernetes-list-map-keys: - - type - x-kubernetes-list-type: map - type: object - required: - - metadata - - spec - type: object - served: true - storage: true - subresources: - status: {} diff --git a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/contour/upstream/02-job-certgen.yaml b/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/contour/upstream/02-job-certgen.yaml deleted file mode 100644 index c8e75c58d..000000000 --- a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/contour/upstream/02-job-certgen.yaml +++ /dev/null @@ -1,72 +0,0 @@ ---- -apiVersion: v1 -kind: ServiceAccount -metadata: - name: contour-certgen - namespace: projectcontour ---- -apiVersion: rbac.authorization.k8s.io/v1 -kind: RoleBinding -metadata: - name: contour - namespace: projectcontour -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: Role - name: contour-certgen -subjects: -- kind: ServiceAccount - name: contour-certgen - namespace: projectcontour ---- -apiVersion: rbac.authorization.k8s.io/v1 -kind: Role -metadata: - name: contour-certgen - namespace: projectcontour -rules: -- apiGroups: - - "" - resources: - - secrets - verbs: - - create - - update ---- -apiVersion: batch/v1 -kind: Job -metadata: - name: contour-certgen-v1-30-2 - namespace: projectcontour -spec: - template: - metadata: - labels: - app: "contour-certgen" - spec: - containers: - - name: contour - image: ghcr.io/projectcontour/contour:v1.30.2 - imagePullPolicy: IfNotPresent - command: - - contour - - certgen - - --kube - - --incluster - - --overwrite - - --secrets-format=compact - - --namespace=$(CONTOUR_NAMESPACE) - env: - - name: CONTOUR_NAMESPACE - valueFrom: - fieldRef: - fieldPath: metadata.namespace - restartPolicy: Never - serviceAccountName: contour-certgen - securityContext: - runAsNonRoot: true - runAsUser: 65534 - runAsGroup: 65534 - parallelism: 1 - completions: 1 - backoffLimit: 1 diff --git a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/contour/upstream/02-rbac.yaml b/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/contour/upstream/02-rbac.yaml deleted file mode 100644 index 9766df6a9..000000000 --- a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/contour/upstream/02-rbac.yaml +++ /dev/null @@ -1,27 +0,0 @@ ---- -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRoleBinding -metadata: - name: contour -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: ClusterRole - name: contour -subjects: -- kind: ServiceAccount - name: contour - namespace: projectcontour ---- -apiVersion: rbac.authorization.k8s.io/v1 -kind: RoleBinding -metadata: - name: contour-rolebinding - namespace: projectcontour -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: Role - name: contour -subjects: -- kind: ServiceAccount - name: contour - namespace: projectcontour diff --git a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/contour/upstream/02-role-contour.yaml b/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/contour/upstream/02-role-contour.yaml deleted file mode 100644 index 21bf57381..000000000 --- a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/contour/upstream/02-role-contour.yaml +++ /dev/null @@ -1,116 +0,0 @@ -# The following ClusterRole and Role are generated from kubebuilder RBAC tags by -# generate-rbac.sh. Do not edit this file directly but instead edit the source -# files and re-render. ---- -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - name: contour -rules: -- apiGroups: - - "" - resources: - - configmaps - - endpoints - - namespaces - - secrets - - services - verbs: - - get - - list - - watch -- apiGroups: - - discovery.k8s.io - resources: - - endpointslices - verbs: - - get - - list - - watch -- apiGroups: - - gateway.networking.k8s.io - resources: - - backendtlspolicies - - gatewayclasses - - gateways - - grpcroutes - - httproutes - - referencegrants - - tcproutes - - tlsroutes - verbs: - - get - - list - - watch -- apiGroups: - - gateway.networking.k8s.io - resources: - - backendtlspolicies/status - - gatewayclasses/status - - gateways/status - - grpcroutes/status - - httproutes/status - - tcproutes/status - - tlsroutes/status - verbs: - - update -- apiGroups: - - networking.k8s.io - resources: - - ingresses - verbs: - - get - - list - - watch -- apiGroups: - - networking.k8s.io - resources: - - ingresses/status - verbs: - - create - - get - - update -- apiGroups: - - projectcontour.io - resources: - - contourconfigurations - - extensionservices - - httpproxies - - tlscertificatedelegations - verbs: - - get - - list - - watch -- apiGroups: - - projectcontour.io - resources: - - contourconfigurations/status - - extensionservices/status - - httpproxies/status - verbs: - - create - - get - - update ---- -apiVersion: rbac.authorization.k8s.io/v1 -kind: Role -metadata: - name: contour - namespace: projectcontour -rules: -- apiGroups: - - "" - resources: - - events - verbs: - - create - - get - - update -- apiGroups: - - coordination.k8s.io - resources: - - leases - verbs: - - create - - get - - update diff --git a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/contour/upstream/02-service-contour.yaml b/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/contour/upstream/02-service-contour.yaml deleted file mode 100644 index 8be5bc9a7..000000000 --- a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/contour/upstream/02-service-contour.yaml +++ /dev/null @@ -1,15 +0,0 @@ ---- -apiVersion: v1 -kind: Service -metadata: - name: contour - namespace: projectcontour -spec: - ports: - - port: 8001 - name: xds - protocol: TCP - targetPort: 8001 - selector: - app: contour - type: ClusterIP diff --git a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/contour/upstream/02-service-envoy.yaml b/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/contour/upstream/02-service-envoy.yaml deleted file mode 100644 index 1da8fc0a6..000000000 --- a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/contour/upstream/02-service-envoy.yaml +++ /dev/null @@ -1,28 +0,0 @@ ---- -apiVersion: v1 -kind: Service -metadata: - name: envoy - namespace: projectcontour - annotations: - # This annotation puts the AWS ELB into "TCP" mode so that it does not - # do HTTP negotiation for HTTPS connections at the ELB edge. - # The downside of this is the remote IP address of all connections will - # appear to be the internal address of the ELB. See docs/proxy-proto.md - # for information about enabling the PROXY protocol on the ELB to recover - # the original remote IP address. - service.beta.kubernetes.io/aws-load-balancer-backend-protocol: tcp -spec: - externalTrafficPolicy: Local - ports: - - port: 80 - name: http - protocol: TCP - targetPort: 8080 - - port: 443 - name: https - protocol: TCP - targetPort: 8443 - selector: - app: envoy - type: LoadBalancer diff --git a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/contour/upstream/03-contour.yaml b/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/contour/upstream/03-contour.yaml deleted file mode 100644 index 807305518..000000000 --- a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/contour/upstream/03-contour.yaml +++ /dev/null @@ -1,100 +0,0 @@ ---- -apiVersion: apps/v1 -kind: Deployment -metadata: - labels: - app: contour - name: contour - namespace: projectcontour -spec: - replicas: 2 - strategy: - type: RollingUpdate - rollingUpdate: - # This value of maxSurge means that during a rolling update - # the new ReplicaSet will be created first. - maxSurge: 50% - selector: - matchLabels: - app: contour - template: - metadata: - labels: - app: contour - spec: - affinity: - podAntiAffinity: - preferredDuringSchedulingIgnoredDuringExecution: - - podAffinityTerm: - labelSelector: - matchLabels: - app: contour - topologyKey: kubernetes.io/hostname - weight: 100 - containers: - - args: - - serve - - --incluster - - --xds-address=0.0.0.0 - - --xds-port=8001 - - --contour-cafile=/certs/ca.crt - - --contour-cert-file=/certs/tls.crt - - --contour-key-file=/certs/tls.key - - --config-path=/config/contour.yaml - command: ["contour"] - image: ghcr.io/projectcontour/contour:v1.30.2 - imagePullPolicy: IfNotPresent - name: contour - ports: - - containerPort: 8001 - name: xds - protocol: TCP - - containerPort: 8000 - name: metrics - protocol: TCP - - containerPort: 6060 - name: debug - protocol: TCP - livenessProbe: - httpGet: - path: /healthz - port: 8000 - readinessProbe: - tcpSocket: - port: 8001 - periodSeconds: 10 - volumeMounts: - - name: contourcert - mountPath: /certs - readOnly: true - - name: contour-config - mountPath: /config - readOnly: true - env: - - name: CONTOUR_NAMESPACE - valueFrom: - fieldRef: - apiVersion: v1 - fieldPath: metadata.namespace - - name: POD_NAME - valueFrom: - fieldRef: - apiVersion: v1 - fieldPath: metadata.name - dnsPolicy: ClusterFirst - serviceAccountName: contour - securityContext: - runAsNonRoot: true - runAsUser: 65534 - runAsGroup: 65534 - volumes: - - name: contourcert - secret: - secretName: contourcert - - name: contour-config - configMap: - name: contour - defaultMode: 0644 - items: - - key: contour.yaml - path: contour.yaml diff --git a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/contour/upstream/03-envoy.yaml b/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/contour/upstream/03-envoy.yaml deleted file mode 100644 index b28516dd9..000000000 --- a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/contour/upstream/03-envoy.yaml +++ /dev/null @@ -1,139 +0,0 @@ ---- -apiVersion: apps/v1 -kind: DaemonSet -metadata: - labels: - app: envoy - name: envoy - namespace: projectcontour -spec: - updateStrategy: - type: RollingUpdate - rollingUpdate: - maxUnavailable: 10% - selector: - matchLabels: - app: envoy - template: - metadata: - labels: - app: envoy - spec: - containers: - - command: - - /bin/contour - args: - - envoy - - shutdown-manager - image: ghcr.io/projectcontour/contour:v1.30.2 - imagePullPolicy: IfNotPresent - lifecycle: - preStop: - exec: - command: - - /bin/contour - - envoy - - shutdown - name: shutdown-manager - volumeMounts: - - name: envoy-admin - mountPath: /admin - - args: - - -c - - /config/envoy.json - - --service-cluster $(CONTOUR_NAMESPACE) - - --service-node $(ENVOY_POD_NAME) - - --log-level info - command: - - envoy - image: docker.io/envoyproxy/envoy:v1.31.5 - imagePullPolicy: IfNotPresent - name: envoy - env: - - name: CONTOUR_NAMESPACE - valueFrom: - fieldRef: - apiVersion: v1 - fieldPath: metadata.namespace - - name: ENVOY_POD_NAME - valueFrom: - fieldRef: - apiVersion: v1 - fieldPath: metadata.name - ports: - - containerPort: 8080 - hostPort: 80 - name: http - protocol: TCP - - containerPort: 8443 - hostPort: 443 - name: https - protocol: TCP - - containerPort: 8002 - hostPort: 8002 - name: metrics - protocol: TCP - readinessProbe: - httpGet: - path: /ready - port: 8002 - initialDelaySeconds: 3 - periodSeconds: 4 - volumeMounts: - - name: envoy-config - mountPath: /config - readOnly: true - - name: envoycert - mountPath: /certs - readOnly: true - - name: envoy-admin - mountPath: /admin - lifecycle: - preStop: - httpGet: - path: /shutdown - port: 8090 - scheme: HTTP - initContainers: - - args: - - bootstrap - - /config/envoy.json - - --xds-address=contour - - --xds-port=8001 - - --xds-resource-version=v3 - - --resources-dir=/config/resources - - --envoy-cafile=/certs/ca.crt - - --envoy-cert-file=/certs/tls.crt - - --envoy-key-file=/certs/tls.key - command: - - contour - image: ghcr.io/projectcontour/contour:v1.30.2 - imagePullPolicy: IfNotPresent - name: envoy-initconfig - volumeMounts: - - name: envoy-config - mountPath: /config - - name: envoycert - mountPath: /certs - readOnly: true - env: - - name: CONTOUR_NAMESPACE - valueFrom: - fieldRef: - fieldPath: metadata.namespace - automountServiceAccountToken: false - serviceAccountName: envoy - terminationGracePeriodSeconds: 300 - volumes: - - name: envoy-admin - emptyDir: {} - - name: envoy-config - emptyDir: {} - - name: envoycert - secret: - secretName: envoycert - restartPolicy: Always - securityContext: - runAsNonRoot: true - runAsUser: 65534 - runAsGroup: 65534 diff --git a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/contour/upstream/README.md b/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/contour/upstream/README.md deleted file mode 100644 index 5edf32fc8..000000000 --- a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/contour/upstream/README.md +++ /dev/null @@ -1,84 +0,0 @@ -# Contour Installation - -This is an installation guide to configure Contour in a Deployment separate from Envoy which allows for easier scaling of each component. - -This configuration has several advantages: - -1. Envoy runs as a daemonset which allows for distributed scaling across workers in the cluster -2. Communication between Contour and Envoy is secured by mutually-checked self-signed certificates. - -## Moving parts - -- Contour is run as Deployment and Envoy as a Daemonset -- Envoy runs on host networking -- Envoy runs on ports 80 & 443 - -The TLS secrets used to secure the gRPC session between Contour and Envoy are generated using a Job that runs `contour certgen`. -For detailed instructions on how to configure the required secrets manually, see the [step-by-step TLS HOWTO](https://projectcontour.io/docs/main/grpc-tls-howto). - -## Deploy Contour - -Either: - -1. Run `kubectl apply -f https://projectcontour.io/quickstart/contour.yaml` - -or: -Clone or fork the repository, then run: - -```bash -kubectl apply -f examples/contour -``` - -This will: - -- set up RBAC and Contour's CRDs (CRDs include HTTPProxy, TLSCertificateDelegation) -- run a Kubernetes Job that will generate one-year validity certs and put them into `projectcontour` -- Install Contour and Envoy in a Deployment and Daemonset respectively. - -**NOTE**: The current configuration exposes the `/stats` path from the Envoy Admin UI so that Prometheus can scrape for metrics. - -## Test - -1. Install a workload (see the kuard example in the [main deployment guide](https://projectcontour.io/docs/main/deploy-options/#test-with-httpproxy)). - -## Deploying with Host Networking enabled for Envoy - -In order to deploy the Envoy Daemonset with host networking enabled, you need to make two changes. - -In the Envoy daemonset definition, at the Pod spec level, change: - -```yaml -dnsPolicy: ClusterFirst -``` - -to - -```yaml -dnsPolicy: ClusterFirstWithHostNet -``` - -and add - -```yaml -hostNetwork: true -``` - -Then, in the Envoy Service definition, change the annotation from: - -```yaml - # This annotation puts the AWS ELB into "TCP" mode so that it does not - # do HTTP negotiation for HTTPS connections at the ELB edge. - # The downside of this is the remote IP address of all connections will - # appear to be the internal address of the ELB. See docs/proxy-proto.md - # for information about enabling the PROXY protocol on the ELB to recover - # the original remote IP address. - service.beta.kubernetes.io/aws-load-balancer-backend-protocol: tcp -``` - -to - -```yaml - service.beta.kubernetes.io/aws-load-balancer-type: nlb -``` - -Then, apply the example as normal. This will still deploy a LoadBalancer Service, but it will be an NLB instead of an ELB. diff --git a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/contour/values-schema.yaml b/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/contour/values-schema.yaml deleted file mode 100644 index a3d9c9551..000000000 --- a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/contour/values-schema.yaml +++ /dev/null @@ -1,35 +0,0 @@ -#@ load("rules.star", "check_all") - -#@data/values-schema -#@schema/validation ("check compliance of values", check_all) ---- -#@schema/desc "Underlying infrastructure provider." -#@schema/validation one_of=["aws", "gcp", "azure", "kind", "minikube", "custom"] -infraProvider: "custom" - -#@schema/desc "Name of the namespace to use" -namespace: projectcontour -#@schema/desc "Should the namespace be created" -createNamespace: true - -#@schema/desc "Contour dpeloyment configuration" -#@schema/nullable -contour: - replicas: 1 - -#@schema/desc "Envoy service configuration" -service: - #@schema/validation one_of=["ClusterIP", "LoadBalancer"] - type: LoadBalancer - useHostPorts: true - -#@schema/desc "Configuration for externaldns" -#@schema/nullable -externaldns: - domains: - - "" - -#@schema/desc "Configuration for the Contour ingress controller" -configFileContents: - defaultHttpVersions: - - "" diff --git a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/educates/00-assert.yaml b/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/educates/00-assert.yaml deleted file mode 100644 index 6108ccdaa..000000000 --- a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/educates/00-assert.yaml +++ /dev/null @@ -1,8 +0,0 @@ -#@ load("@ytt:data", "data") -#@ load("@ytt:assert", "assert") - -#@ if data.values.clusterSecurity.policyEngine == "pod-security-policies": -#@ if data.values.clusterStorage.user: -#@ assert.fail("Cluster storage user cannot be set when pod security policies enabled.") -#@ end -#@ end \ No newline at end of file diff --git a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/educates/00-package.star b/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/educates/00-package.star deleted file mode 100644 index a449d45d8..000000000 --- a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/educates/00-package.star +++ /dev/null @@ -1,55 +0,0 @@ -load("@ytt:data", "data") -load("@ytt:base64", "base64") -load("@ytt:json", "json") - -def xgetattr(object, path, default=None): - def _lookup(object, key, default=None): - keys = key.split(".") - value = default - for key in keys: - value = getattr(object, key, None) - if value == None: - return default - end - object = value - end - return value - end - - return _lookup(object, path, default) -end - -def image_reference(name): - registry = xgetattr(data.values, "imageRegistry.host", "registry.default.svc.cluster.local") - if xgetattr(data.values, "imageRegistry.namespace", "") != "": - registry = "{}/{}".format(registry, data.values.imageRegistry.namespace) - end - image = "{}/educates-{}:{}".format(registry, name, data.values.version) - for item in data.values.imageVersions: - if item.name == name: - image = item.image - break - end - end - return image -end - -def image_pull_policy(image): - tag = image.split(":") - always = len(tag) <= 1 or tag[-1] in ["latest", "main", "master", "develop"] - return always and "Always" or "IfNotPresent" -end - -def image_pull_secrets(): - return [item["name"] for item in data.values.clusterSecrets.pullSecretRefs] -end - -def docker_config_json(host, username, password): - return json.encode({ - "auths": { - host: { - "auth": base64.encode("{}:{}".format(username, password)) - } - } - }) -end diff --git a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/educates/00-schema.yaml b/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/educates/00-schema.yaml deleted file mode 100644 index 98863ba43..000000000 --- a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/educates/00-schema.yaml +++ /dev/null @@ -1,278 +0,0 @@ -#@data/values-schema ---- -#! The version of Educates to be used. This is used internally for development -#! and experimentation and should not be overridden through a values file in -#! normal use. - -version: "latest" - -#! Settings for customizing namespace, API group and resource naming conventions -#! for the operator. This is used internally for development and experimentation -#! and should not be overridden through a values file in normal use. - -operator: - namespace: "educates" - -#! Settings for customizing session manager permissions. By default, the session -#! manager is granted cluster-admin to allow workshops to make use of any -#! resource types. If cluster-admin is disabled, only the minimum permissions -#! required for the session manager to function will be granted. This restricts -#! workshops to deploying workloads into the session namespace only. To grant -#! additional permissions without cluster-admin, use cluster role aggregation to -#! add permissions to the default cluster role granted to the session manager. - -sessionManager: - #! Whether the session manager should be granted cluster-admin permissions. - clusterAdmin: true - -#! Image registry where Educates container images and workshop content is -#! stored. This is used internally for development, experimentation and when -#! working on workshop content in a local Educates environment, and should not -#! be overridden through a values file in normal use. If images are hosted at -#! the root of the image registry, the namespace setting can be left empty. -#! If this is set, it will disable the deployment of an in cluster image -#! registry as part of the Educates deployment which is done when secure -#! connections are available. - -#@schema/nullable -imageRegistry: - #@schema/nullable - #@schema/validation min_len=1 - host: "" - namespace: "" - -#! Container image versions for various components of Educates. This is used -#! internally by packaging and should not be overridden through a values file -#! in normal use. - -imageVersions: - - name: "" - image: "" - -#! Settings for customizing container runtime used for Educates deployments. - -clusterRuntime: - #! Runtime class applied to deployments. Can be set where pods should be run - #! using a container runtime other than the default. For example one could - #! select Kata containers as runtime so workshop containers are isolated in an - #! additional lightweight VM. Only workshop containers currently have this - #! runtime class applied. - class: "" - -#! Settings for customizing ingress details by which Educates will be accessed. - -clusterIngress: - #! Ingress domain. DNS parent subdomain used for training portal and workshop - #! ingresses. - domain: "educates-local-dev.test" - - #! Ingress class. Required when multiple ingress controllers exist and it is - #! necessary to use one which is not marked as the default. Note that any - #! workshop content which has users create ingresses will need to separately - #! handle that a non default ingress class needs to be used. - class: "" - - #! Ingress protocol. Should only be set where an ingress secret has not been - #! supplied but an external router is terminating secure connections and then - #! proxying through to the Kubernetes cluster hosting Educates. In this case - #! would be necessary to override it with the value "https". Otherwise leave - #! as empty and the value will be calculated automatically based on whether an - #! ingress secret was supplied. - protocol: "" - - #! TLS certificate for secure ingress. Must be a wildcard certificate for - #! children of the DNS parent ingress subdomain. Full certificate chain and - #! private key need to be defined in the values. Will be ignored if the - #! "tlsCertificateRef" setting is defined. - tlsCertificate: - tls.crt: "" - tls.key: "" - - #! Reference to TLS certificate for secure ingress. Must be a wildcard - #! certificate for children of the DNS parent ingress subdomain. Takes - #! precedence over "tlsCertificate" setting. If namespace is not specified the - #! secret must reside in the Educates namespace. - - tlsCertificateRef: - namespace: "" - name: "" - - #! CA certificate for verifying wildcard TLS certificate. Will be ignored if - #! the "caCertificateRef" setting is defined. - - caCertificate: - ca.crt: "" - - #! Reference to CA certificate for verifying wildcard TLS certificate. Takes - #! precedence over "caCertificate" setting. If namespace is not specified the - #! secret must reside in the Educates namespace. - - caCertificateRef: - namespace: "" - name: "" - - #! When a CA certificate is provided it can optionally be injected into the - #! cluster nodes. - - caNodeInjector: - enabled: false - -#! Settings for overriding options for portal and workshop session cookies. - -sessionCookies: - #! Session cookie domain. DNS parent domain used for training portal and - #! workshop session cookies. May need to be set to a parent domain of the - #! ingress domain if cross domain cookie sharing is necessary due to - #! embedding. - domain: "" - -#! Configuration for persistent volumes. The default storage class specified -#! by the cluster will be used if not defined. Storage group may need to be -#! set where a cluster has pod security policies enabled, usually setting it -#! to group ID 1. Storage user in combination with storage group can be set in -#! exceptional case where storage class used maps to NFS storage and storage -#! server requires specific user and group always be used. This latter combo -#! cannot be used in a Kubernetes cluster which enforces pod security policies. - -clusterStorage: - class: "" - #@schema/nullable - user: 0 - group: 1 - -#! References to image pull secrets for additional image registries hosting -#! Educates container images, or custom workshop images. If the namespace for -#! a secret is not defined, it is the users responsibility to ensure it is -#! copied into the Educates namespace. If the namespace is defined a secret -#! copier will be automatically defined which will result in the secret being -#! copied into the Educates namespace. - -clusterSecrets: - pullSecretRefs: - - namespace: "" - name: "" - -#! Policy engine used to enforce security. Options are "pod-security-policies", -#! "pod-security-standards", "security-context-constraints", "kyverno" and -#! "none". - -clusterSecurity: - policyEngine: "none" - -#! Rules engine used to enforce additional restrictions on what workshop users -#! can do beyond what RBAC limits. Options are "kyverno" and "none". - -workshopSecurity: - rulesEngine: "kyverno" - -#! User credentials for accessing training portal instances. If not specified -#! then random passwords are generated which can be obtained from the custom -#! resource for the training portal. The admin user can access the admin pages -#! for the training portal where as the robot user cannot and only exists for -#! REST API access. Client credentials are access credentials which do not -#! require a user to login through the web based login mechanism of the training -#! portal. They are only usable with the training portal REST API. - -trainingPortal: - credentials: - admin: - username: "educates" - #@schema/nullable - password: "" - robot: - username: "robot@educates" - #@schema/nullable - password: "" - - clients: - robot: - #@schema/nullable - id: "" - #@schema/nullable - secret: "" - -#! Docker daemon settings when building docker images in a workshop is -#! enabled. Proxy cache provides a way of partially getting around image -#! pull limits for Docker Hub image registry, if the remote URL being -#! set to "https://registry-1.docker.io". - -dockerDaemon: - networkMTU: 1400 - - proxyCache: - remoteURL: "" - username: "" - password: "" - -#! Cluster network settings for blocking access to specific IP address blocks. -#! By default will block AWS EC2 metadata access point. - -clusterNetwork: - #@schema/default ["169.254.169.254/32", "fd00:ec2::254/128"] - blockCIDRs: - - "" - -#! Analytics allows for tracking for workshop sessions. Note that Google -#! analytics is not a reliable method due to being browser based and many users -#! blocking such tracking IDs. Webhooks is completely server side and gives -#! more detailed analytics. - -workshopAnalytics: - google: - trackingId: "" - - clarity: - trackingId: "" - - amplitude: - trackingId: "" - - webhook: - url: "" - -#! Overrides for styling of training portal and workshop dashboard interface. - -websiteStyling: - workshopDashboard: - html: "" - script: "" - style: "" - - workshopInstructions: - html: "" - script: "" - style: "" - - workshopStarted: - html: "" - - workshopFinished: - html: "" - - trainingPortal: - html: "" - script: "" - style: "" - - defaultTheme: "" - - themeDataRefs: - - name: "" - namespace: "" - - frameAncestors: - - "" - -#! Pre-pull selected workshop images to nodes in the cluster. Should be empty -#! list if no images should be prepulled. This is done to reduce start up times -#! for workhop sessions the first time on each node in the cluster. - -imagePuller: - enabled: true - #@schema/default ["base-environment"] - prePullImages: - - "" - -lookupService: - enabled: false - ingressPrefix: "educates-api" diff --git a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/educates/00-values.yaml b/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/educates/00-values.yaml deleted file mode 100644 index a4c8a92c7..000000000 --- a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/educates/00-values.yaml +++ /dev/null @@ -1,18 +0,0 @@ -#@data/values - ---- -imageVersions: -- name: debian-base-image - image: "debian:sid-20230502-slim" -- name: docker-in-docker - image: "docker:27.5.1-dind" -- name: loftsh-kubernetes-v1.31 - image: "ghcr.io/loft-sh/kubernetes:v1.31.1" -- name: loftsh-kubernetes-v1.32 - image: "ghcr.io/loft-sh/kubernetes:v1.32.1" -- name: loftsh-kubernetes-v1.33 - image: "ghcr.io/loft-sh/kubernetes:v1.33.4" -- name: loftsh-kubernetes-v1.34 - image: "ghcr.io/loft-sh/kubernetes:v1.34.0" -- name: loftsh-vcluster - image: "ghcr.io/loft-sh/vcluster-oss:0.30.2" diff --git a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/educates/01-clusterpolicies.yaml b/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/educates/01-clusterpolicies.yaml deleted file mode 100644 index a14f4c517..000000000 --- a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/educates/01-clusterpolicies.yaml +++ /dev/null @@ -1,8 +0,0 @@ -#@ load("@ytt:data", "data") -#@ load("@ytt:library", "library") -#@ load("@ytt:template", "template") - -#@ if data.values.clusterSecurity.policyEngine == "kyverno": ---- #@ template.replace(library.get("kyverno-baseline").with_data_values(data.values, plain=True).eval()) ---- #@ template.replace(library.get("kyverno-restricted").with_data_values(data.values, plain=True).eval()) -#@ end diff --git a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/educates/01-clusterroles.yaml b/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/educates/01-clusterroles.yaml deleted file mode 100644 index 899ef1d0e..000000000 --- a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/educates/01-clusterroles.yaml +++ /dev/null @@ -1,95 +0,0 @@ -#@ load("@ytt:data", "data") - -#@ if data.values.clusterSecurity.policyEngine == "pod-security-policies": ---- -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - name: educates-privileged-psp -rules: - - apiGroups: - - policy - resources: - - podsecuritypolicies - verbs: - - use - resourceNames: - - aaa-educates-privileged - ---- -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - name: educates-baseline-psp -rules: - - apiGroups: - - policy - resources: - - podsecuritypolicies - verbs: - - use - resourceNames: - - aaa-educates-baseline - ---- -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - name: educates-restricted-psp -rules: - - apiGroups: - - policy - resources: - - podsecuritypolicies - verbs: - - use - resourceNames: - - aaa-educates-restricted -#@ end - -#@ if data.values.clusterSecurity.policyEngine == "security-context-constraints": ---- -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - name: educates-privileged-scc -rules: - - apiGroups: - - security.openshift.io - resources: - - securitycontextconstraints - verbs: - - use - resourceNames: - - educates-privileged - ---- -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - name: educates-baseline-scc -rules: - - apiGroups: - - security.openshift.io - resources: - - securitycontextconstraints - verbs: - - use - resourceNames: - - educates-baseline - ---- -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - name: educates-restricted-scc -rules: - - apiGroups: - - security.openshift.io - resources: - - securitycontextconstraints - verbs: - - use - resourceNames: - - educates-restricted -#@ end diff --git a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/educates/01-podsecuritypolicies.yaml b/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/educates/01-podsecuritypolicies.yaml deleted file mode 100644 index 3a48aae37..000000000 --- a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/educates/01-podsecuritypolicies.yaml +++ /dev/null @@ -1,174 +0,0 @@ -#@ load("@ytt:data", "data") - -#! These are standard pod security policies from Kubernetes, but we use our -#! own with name that is better guaranteed to override any defaults. - -#@ if data.values.clusterSecurity.policyEngine == "pod-security-policies": ---- -apiVersion: policy/v1beta1 -kind: PodSecurityPolicy -metadata: - name: aaa-educates-privileged - annotations: - seccomp.security.alpha.kubernetes.io/allowedProfileNames: "*" -spec: - privileged: true - allowPrivilegeEscalation: true - allowedCapabilities: - - "*" - volumes: - - "*" - hostNetwork: true - hostPorts: - - min: 0 - max: 65535 - hostIPC: true - hostPID: true - runAsUser: - rule: "RunAsAny" - seLinux: - rule: "RunAsAny" - supplementalGroups: - rule: "RunAsAny" - fsGroup: - rule: "RunAsAny" - ---- -apiVersion: policy/v1beta1 -kind: PodSecurityPolicy -metadata: - name: aaa-educates-baseline - annotations: - #! Optional: Allow the default AppArmor profile, requires setting the default. - #! apparmor.security.beta.kubernetes.io/allowedProfileNames: 'runtime/default' - #! apparmor.security.beta.kubernetes.io/defaultProfileName: 'runtime/default' - seccomp.security.alpha.kubernetes.io/allowedProfileNames: '*' -spec: - privileged: false - allowPrivilegeEscalation: true - #! The moby default capability set, minus NET_RAW - allowedCapabilities: - - 'CHOWN' - - 'DAC_OVERRIDE' - - 'FSETID' - - 'FOWNER' - - 'MKNOD' - - 'SETGID' - - 'SETUID' - - 'SETFCAP' - - 'SETPCAP' - - 'NET_BIND_SERVICE' - - 'SYS_CHROOT' - - 'KILL' - - 'AUDIT_WRITE' - #! Allow all volume types except hostpath - volumes: - #! 'core' volume types - - 'configMap' - - 'emptyDir' - - 'projected' - - 'secret' - - 'downwardAPI' - #! Assume that ephemeral CSI drivers & persistentVolumes set up by the cluster admin are safe to use. - - 'csi' - - 'persistentVolumeClaim' - - 'ephemeral' - #! Allow all other non-hostpath volume types. - - 'awsElasticBlockStore' - - 'azureDisk' - - 'azureFile' - - 'cephFS' - - 'cinder' - - 'fc' - - 'flexVolume' - - 'flocker' - - 'gcePersistentDisk' - - 'gitRepo' - - 'glusterfs' - - 'iscsi' - - 'nfs' - - 'photonPersistentDisk' - - 'portworxVolume' - - 'quobyte' - - 'rbd' - - 'scaleIO' - - 'storageos' - - 'vsphereVolume' - hostNetwork: false - hostIPC: false - hostPID: false - readOnlyRootFilesystem: false - runAsUser: - rule: 'RunAsAny' - seLinux: - #! This policy assumes the nodes are using AppArmor rather than SELinux. - #! The PSP SELinux API cannot express the SELinux Pod Security Standards, - #! so if using SELinux, you must choose a more restrictive default. - rule: 'RunAsAny' - supplementalGroups: - #! XXX Standard policy usually has RunAsAny, but we set a range so that - #! it will add a supplementalGroup if none set. - rule: 'MustRunAs' - ranges: - - min: 0 - max: 65535 - fsGroup: - #! XXX Standard policy usually has RunAsAny, but we set a range so that - #! it will add a supplementalGroup if none set. - rule: 'MustRunAs' - ranges: - - min: 0 - max: 65535 - ---- -apiVersion: policy/v1beta1 -kind: PodSecurityPolicy -metadata: - name: aaa-educates-restricted - annotations: - #! apparmor.security.beta.kubernetes.io/allowedProfileNames: 'runtime/default' - #! apparmor.security.beta.kubernetes.io/defaultProfileName: 'runtime/default' - #! seccomp.security.alpha.kubernetes.io/allowedProfileNames: 'docker/default,runtime/default' - #! Need to allow anything because if none are defined pod security policies - #! doesn't seem to be very tolerant of setting this as runtime/default. - seccomp.security.alpha.kubernetes.io/allowedProfileNames: '*' -spec: - privileged: false - #! Required to prevent escalations to root. - allowPrivilegeEscalation: false - requiredDropCapabilities: - - ALL - #! Allow core volume types. - volumes: - - 'configMap' - - 'emptyDir' - - 'projected' - - 'secret' - - 'downwardAPI' - #! Assume that ephemeral CSI drivers & persistentVolumes set up by the cluster admin are safe to use. - - 'csi' - - 'persistentVolumeClaim' - - 'ephemeral' - hostNetwork: false - hostIPC: false - hostPID: false - runAsUser: - #! Require the container to run without root privileges. - rule: 'MustRunAsNonRoot' - seLinux: - #! This policy assumes the nodes are using AppArmor rather than SELinux. - rule: 'RunAsAny' - supplementalGroups: - rule: 'MustRunAs' - ranges: - #! XXX Allow group ID of 0. This deviates from standard policies. - - min: 0 - max: 65535 - fsGroup: - rule: 'MustRunAs' - ranges: - #! XXX Allow group ID of 0. This deviates from standard policies. - - min: 0 - max: 65535 - readOnlyRootFilesystem: false -#@ end diff --git a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/educates/01-securitycontextconstraints.yaml b/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/educates/01-securitycontextconstraints.yaml deleted file mode 100644 index 5f9fd7070..000000000 --- a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/educates/01-securitycontextconstraints.yaml +++ /dev/null @@ -1,118 +0,0 @@ -#@ load("@ytt:data", "data") - -#@ if data.values.clusterSecurity.policyEngine == "security-context-constraints": ---- -apiVersion: security.openshift.io/v1 -kind: SecurityContextConstraints -metadata: - name: educates-privileged -allowHostDirVolumePlugin: true -allowHostIPC: true -allowHostNetwork: true -allowHostPID: true -allowHostPorts: true -allowPrivilegeEscalation: true -allowPrivilegedContainer: true -allowedCapabilities: -- '*' -allowedUnsafeSysctls: -- '*' -defaultAddCapabilities: null -fsGroup: - type: RunAsAny -groups: [] -priority: 100 -readOnlyRootFilesystem: false -requiredDropCapabilities: null -runAsUser: - type: RunAsAny -seLinuxContext: - type: RunAsAny -seccompProfiles: -- '*' -supplementalGroups: - type: RunAsAny -users: [] -volumes: -- '*' - ---- -apiVersion: security.openshift.io/v1 -kind: SecurityContextConstraints -metadata: - name: educates-baseline -allowHostDirVolumePlugin: false -allowHostIPC: false -allowHostNetwork: false -allowHostPID: false -allowHostPorts: false -allowPrivilegeEscalation: true -allowPrivilegedContainer: false -allowedCapabilities: null -defaultAddCapabilities: null -fsGroup: - type: RunAsAny -groups: [] -priority: 100 -readOnlyRootFilesystem: false -requiredDropCapabilities: -- MKNOD -runAsUser: - type: RunAsAny -seccompProfiles: -- runtime/default -seLinuxContext: - type: MustRunAs -supplementalGroups: - type: RunAsAny -users: [] -volumes: -- configMap -- downwardAPI -- emptyDir -- persistentVolumeClaim -- projected -- secret - ---- -apiVersion: security.openshift.io/v1 -kind: SecurityContextConstraints -metadata: - name: educates-restricted -allowHostDirVolumePlugin: false -allowHostIPC: false -allowHostNetwork: false -allowHostPID: false -allowHostPorts: false -allowPrivilegeEscalation: false -allowPrivilegedContainer: false -allowedCapabilities: null -defaultAddCapabilities: null -fsGroup: - type: RunAsAny -groups: [] -priority: 100 -readOnlyRootFilesystem: false -requiredDropCapabilities: -- KILL -- MKNOD -- SETUID -- SETGID -runAsUser: - type: MustRunAsNonRoot -seccompProfiles: -- runtime/default -seLinuxContext: - type: MustRunAs -supplementalGroups: - type: RunAsAny -users: [] -volumes: -- configMap -- downwardAPI -- emptyDir -- persistentVolumeClaim -- projected -- secret - -#@ end diff --git a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/educates/02-namespaces.yaml b/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/educates/02-namespaces.yaml deleted file mode 100644 index ed56c7e1d..000000000 --- a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/educates/02-namespaces.yaml +++ /dev/null @@ -1,11 +0,0 @@ -#@ load("@ytt:data", "data") - ---- -apiVersion: v1 -kind: Namespace -metadata: - name: #@ data.values.operator.namespace - #@ if data.values.clusterSecurity.policyEngine == "pod-security-standards": - labels: - pod-security.kubernetes.io/enforce: baseline - #@ end diff --git a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/educates/06-secrets.yaml b/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/educates/06-secrets.yaml deleted file mode 100644 index 433d8ce6a..000000000 --- a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/educates/06-secrets.yaml +++ /dev/null @@ -1,73 +0,0 @@ -#@ load("@ytt:data", "data") -#@ load("@ytt:yaml", "yaml") -#@ load("@ytt:base64", "base64") -#@ load("@ytt:library", "library") -#@ load("/00-package.star", "xgetattr") - -#@ kyverno_policies = library.get("kyverno-policies").eval() - ---- -apiVersion: v1 -kind: Secret -metadata: - name: educates-config - namespace: #@ data.values.operator.namespace - annotations: - kapp.k14s.io/versioned: "" - kapp.k14s.io/num-versions: "5" - kapp.k14s.io/disable-original: "" -stringData: - educates-operator-config.yaml: #@ yaml.encode(data.values) - kyverno-policies.yaml: #@ yaml.encode(kyverno_policies) - -#@ ingress_certificate = getattr(data.values.clusterIngress.tlsCertificate, "tls.crt") -#@ ingress_private_key = getattr(data.values.clusterIngress.tlsCertificate, "tls.key") -#@ ingress_secret_ref_name = data.values.clusterIngress.tlsCertificateRef.name - -#@ if not ingress_secret_ref_name and ingress_certificate and ingress_private_key: ---- -apiVersion: v1 -kind: Secret -metadata: - name: #@ "{}-tls".format(data.values.clusterIngress.domain) - namespace: #@ data.values.operator.namespace -type: kubernetes.io/tls -data: - tls.crt: #@ base64.encode(ingress_certificate) - tls.key: #@ base64.encode(ingress_private_key) -#@ end - -#@ ingress_ca_certificate = getattr(data.values.clusterIngress.caCertificate, "ca.crt") -#@ ingress_ca_secret_ref_name = data.values.clusterIngress.caCertificateRef.name - -#@ if not ingress_ca_secret_ref_name and ingress_ca_certificate: ---- -apiVersion: v1 -kind: Secret -metadata: - name: #@ "{}-ca".format(data.values.clusterIngress.domain) - namespace: #@ data.values.operator.namespace -data: - ca.crt: #@ base64.encode(ingress_ca_certificate) -#@ end - -#@ default_theme = data.values.websiteStyling - ---- -apiVersion: v1 -kind: Secret -metadata: - name: default-website-theme - namespace: #@ data.values.operator.namespace -data: - workshop-dashboard.html: #@ base64.encode(xgetattr(default_theme, "workshopDashboard.html", "")) - workshop-dashboard.js: #@ base64.encode(xgetattr(default_theme, "workshopDashboard.script", "")) - workshop-dashboard.css: #@ base64.encode(xgetattr(default_theme, "workshopDashboard.style", "")) - workshop-instructions.html: #@ base64.encode(xgetattr(default_theme, "workshopInstructions.html", "")) - workshop-instructions.js: #@ base64.encode(xgetattr(default_theme, "workshopInstructions.script", "")) - workshop-instructions.css: #@ base64.encode(xgetattr(default_theme, "workshopInstructions.style", "")) - workshop-started.html: #@ base64.encode(xgetattr(default_theme, "workshopStarted.html", "")) - workshop-finished.html: #@ base64.encode(xgetattr(default_theme, "workshopFinished.html", "")) - training-portal.html: #@ base64.encode(xgetattr(default_theme, "trainingPortal.html", "")) - training-portal.js: #@ base64.encode(xgetattr(default_theme, "trainingPortal.script", "")) - training-portal.css: #@ base64.encode(xgetattr(default_theme, "trainingPortal.style", "")) diff --git a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/educates/07-node-ca-injector.yaml b/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/educates/07-node-ca-injector.yaml deleted file mode 100644 index 84b1c1098..000000000 --- a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/educates/07-node-ca-injector.yaml +++ /dev/null @@ -1,148 +0,0 @@ -#@ load("@ytt:data", "data") -#@ load("/00-package.star", "image_reference", "image_pull_policy") - -#@ ingress_ca_secret = data.values.clusterIngress.caCertificateRef.name -#@ if not ingress_ca_secret and getattr(data.values.clusterIngress.caCertificate, "ca.crt"): -#@ ingress_ca_secret = "{}-ca".format(data.values.clusterIngress.domain) -#@ end - -#@ if ingress_ca_secret and data.values.clusterIngress.caNodeInjector.enabled: ---- -apiVersion: v1 -kind: ServiceAccount -metadata: - name: node-ca-injector - namespace: #@ data.values.operator.namespace ---- -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - name: educates-node-ca-injector -rules: -- apiGroups: ["networking.k8s.io"] - resources: ["ingresses"] - verbs: ["get", "list", "watch"] ---- -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRoleBinding -metadata: - name: educates-node-ca-injector -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: ClusterRole - name: educates-node-ca-injector -subjects: -- kind: ServiceAccount - name: node-ca-injector - namespace: #@ data.values.operator.namespace ---- -apiVersion: rbac.authorization.k8s.io/v1 -kind: Role -metadata: - name: node-ca-injector - namespace: #@ data.values.operator.namespace -rules: -- apiGroups: [""] - resources: ["configmaps"] - verbs: ["get", "list", "watch", "create", "update", "delete", "patch"] ---- -apiVersion: rbac.authorization.k8s.io/v1 -kind: RoleBinding -metadata: - name: node-ca-injector - namespace: #@ data.values.operator.namespace -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: Role - name: node-ca-injector -subjects: -- kind: ServiceAccount - name: node-ca-injector - namespace: #@ data.values.operator.namespace ---- -apiVersion: apps/v1 -kind: Deployment -metadata: - name: node-ca-injector-controller - namespace: #@ data.values.operator.namespace -spec: - replicas: 1 - selector: - matchLabels: - app: node-ca-injector-controller - template: - metadata: - labels: - app: node-ca-injector-controller - spec: - serviceAccountName: node-ca-injector - containers: - - name: controller - #@ image = image_reference("node-ca-injector") - image: #@ image - imagePullPolicy: #@ image_pull_policy(image) - args: ["controller"] - env: - - name: OPERATOR_NAMESPACE - valueFrom: - fieldRef: - fieldPath: metadata.namespace - resources: - requests: - memory: "64Mi" - cpu: "50m" - limits: - memory: "128Mi" ---- -apiVersion: apps/v1 -kind: DaemonSet -metadata: - name: node-ca-injector - namespace: #@ data.values.operator.namespace -spec: - selector: - matchLabels: - app: node-ca-injector - template: - metadata: - labels: - app: node-ca-injector - spec: - tolerations: - - operator: Exists - containers: - - name: sync - #@ image = image_reference("node-ca-injector") - image: #@ image - imagePullPolicy: #@ image_pull_policy(image) - args: ["sync"] - securityContext: - privileged: true - volumeMounts: - - name: hosts-config - mountPath: /config/hosts - readOnly: true - - name: ca-secret - mountPath: /config/ca - readOnly: true - - name: containerd-certs-d - mountPath: /host/etc/containerd/certs.d - resources: - requests: - memory: "32Mi" - cpu: "10m" - limits: - memory: "64Mi" - volumes: - - name: hosts-config - configMap: - name: educates-registry-hosts - optional: true - - name: ca-secret - secret: - secretName: #@ ingress_ca_secret - - name: containerd-certs-d - hostPath: - path: /etc/containerd/certs.d - type: DirectoryOrCreate -#@ end diff --git a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/educates/08-lookup.yaml b/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/educates/08-lookup.yaml deleted file mode 100644 index c7e1ec501..000000000 --- a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/educates/08-lookup.yaml +++ /dev/null @@ -1,36 +0,0 @@ -#@ load("@ytt:data", "data") -#@ load("@ytt:library", "library") -#@ load("@ytt:template", "template") -#@ load("/00-package.star", "image_reference", "image_pull_policy") - -#@ ingress_certificate = getattr(data.values.clusterIngress.tlsCertificate, "tls.crt") -#@ ingress_private_key = getattr(data.values.clusterIngress.tlsCertificate, "tls.key") -#@ image = image_reference("lookup-service") - -#@ if data.values.clusterIngress.tlsCertificateRef.name != None: -#@ ingress_secret = data.values.clusterIngress.tlsCertificateRef.name -#@ elif (ingress_certificate and ingress_private_key): -#@ ingress_secret = "{}-tls".format(data.values.clusterIngress.domain) -#@ end - -#@ ingress_ca_secret = data.values.clusterIngress.caCertificateRef.name - -#@ workshop_base_image = image_reference("base-environment") -#@ workshop_base_image_pull_policy = image_pull_policy(workshop_base_image) - -#@ def lookup_service_values(): -tld: #@ "{}.{}".format(data.values.lookupService.ingressPrefix, data.values.clusterIngress.domain) -certName: #@ ingress_secret -caName: #@ ingress_ca_secret -ingressClass: #@ getattr(data.values.clusterIngress, "class", "") -image: #@ image -imagePullPolicy: #@ image_pull_policy(image) -workshopBaseImage: #@ workshop_base_image -workshopBaseImagePullPolicy: #@ workshop_base_image_pull_policy -#@ end - -#@ if data.values.lookupService.enabled: ---- #@ template.replace(library.get("lookup-service").with_data_values(lookup_service_values(), plain=True).eval()) -#@ end - ---- #@ template.replace(library.get("lookup-service-token").with_data_values({}, plain=True).eval()) diff --git a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/educates/10-secrets-manager/01-clusterroles.yaml b/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/educates/10-secrets-manager/01-clusterroles.yaml deleted file mode 100644 index eb181d120..000000000 --- a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/educates/10-secrets-manager/01-clusterroles.yaml +++ /dev/null @@ -1,63 +0,0 @@ ---- -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - name: educates-secrets-manager -rules: -- apiGroups: - - "" - resources: - - events - verbs: - - create -- apiGroups: - - "" - resources: - - secrets - verbs: - - get - - list - - watch - - create - - delete - - deletecollection - - patch - - update -- apiGroups: - - "" - resources: - - namespaces - verbs: - - get - - list - - watch -- apiGroups: - - "" - resources: - - serviceaccounts - verbs: - - get - - list - - watch - - patch - - update -- apiGroups: - - secrets.educates.dev - resources: - - secretcopiers - - secretexporters - - secretimporters - - secretinjectors - verbs: - - get - - list - - watch - - patch - - update -- apiGroups: - - secrets.educates.dev - resources: - - secretcopiers/finalizers - - secretimporters/finalizers - verbs: - - update diff --git a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/educates/10-secrets-manager/04-serviceaccounts.yaml b/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/educates/10-secrets-manager/04-serviceaccounts.yaml deleted file mode 100644 index bf65ffbdc..000000000 --- a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/educates/10-secrets-manager/04-serviceaccounts.yaml +++ /dev/null @@ -1,14 +0,0 @@ -#@ load("@ytt:data", "data") - ---- -apiVersion: v1 -kind: ServiceAccount -metadata: - name: secrets-manager - namespace: #@ data.values.operator.namespace - annotations: - kapp.k14s.io/change-group: secrets.educates.dev/service-accounts - #! Following currently needed for kapp on OpenShift. - #! TODO: Bring kapp rebaseRules for Openshift service accounts -#! kapp.k14s.io/create-strategy: fallback-on-update -#! kapp.k14s.io/update-strategy: skip diff --git a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/educates/10-secrets-manager/05-clusterrolebindings.yaml b/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/educates/10-secrets-manager/05-clusterrolebindings.yaml deleted file mode 100644 index 47e30f0ad..000000000 --- a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/educates/10-secrets-manager/05-clusterrolebindings.yaml +++ /dev/null @@ -1,47 +0,0 @@ -#@ load("@ytt:data", "data") - ---- -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRoleBinding -metadata: - name: educates-secrets-manager -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: ClusterRole - name: educates-secrets-manager -subjects: -- kind: ServiceAccount - name: secrets-manager - namespace: #@ data.values.operator.namespace - -#@ if data.values.clusterSecurity.policyEngine == "pod-security-policies": ---- -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRoleBinding -metadata: - name: educates-secrets-manager-psp -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: ClusterRole - name: educates-baseline-psp -subjects: -- kind: ServiceAccount - name: secrets-manager - namespace: #@ data.values.operator.namespace -#@ end - -#@ if data.values.clusterSecurity.policyEngine == "security-context-constraints": ---- -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRoleBinding -metadata: - name: educates-secrets-manager-scc -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: ClusterRole - name: educates-baseline-scc -subjects: -- kind: ServiceAccount - name: secrets-manager - namespace: #@ data.values.operator.namespace -#@ end diff --git a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/educates/10-secrets-manager/06-secrets.yaml b/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/educates/10-secrets-manager/06-secrets.yaml deleted file mode 100644 index 6b760dad1..000000000 --- a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/educates/10-secrets-manager/06-secrets.yaml +++ /dev/null @@ -1,13 +0,0 @@ -#@ load("@ytt:data", "data") - ---- -apiVersion: v1 -kind: Secret -metadata: - name: secrets-manager-token - namespace: #@ data.values.operator.namespace - annotations: - kubernetes.io/service-account.name: "secrets-manager" - kapp.k14s.io/change-rule: upsert after upserting secrets.educates.dev/service-accounts -#! kapp.k14s.io/update-strategy: skip -type: kubernetes.io/service-account-token diff --git a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/educates/10-secrets-manager/07-deployments.yaml b/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/educates/10-secrets-manager/07-deployments.yaml deleted file mode 100644 index 51b1267ca..000000000 --- a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/educates/10-secrets-manager/07-deployments.yaml +++ /dev/null @@ -1,70 +0,0 @@ -#@ load("@ytt:data", "data") -#@ load("@ytt:json", "json") -#@ load("@ytt:md5", "md5") -#@ load("/00-package.star", "image_reference", "image_pull_policy") - ---- -apiVersion: apps/v1 -kind: Deployment -metadata: - name: secrets-manager - namespace: #@ data.values.operator.namespace -spec: - replicas: 1 - selector: - matchLabels: - deployment: secrets-manager - strategy: - type: Recreate - template: - metadata: - labels: - deployment: secrets-manager - spec: - serviceAccountName: secrets-manager - automountServiceAccountToken: false - securityContext: - runAsNonRoot: true - runAsUser: 1001 - #! seccompProfile: - #! type: RuntimeDefault - containers: - - name: operator - #@ image = image_reference("secrets-manager") - image: #@ image - imagePullPolicy: #@ image_pull_policy(image) - securityContext: - allowPrivilegeEscalation: false - capabilities: - drop: ["ALL"] - startupProbe: - initialDelaySeconds: 15 - periodSeconds: 10 - timeoutSeconds: 5 - successThreshold: 1 - failureThreshold: 4 - httpGet: - path: /healthz?probe=startup - port: 8080 - livenessProbe: - initialDelaySeconds: 15 - periodSeconds: 30 - timeoutSeconds: 5 - successThreshold: 1 - failureThreshold: 3 - httpGet: - path: /healthz?probe=liveness - port: 8080 - volumeMounts: - - name: config - mountPath: /opt/app-root/config/ - - name: token - mountPath: /var/run/secrets/kubernetes.io/serviceaccount - readOnly: true - volumes: - - name: config - secret: - secretName: educates-config - - name: token - secret: - secretName: secrets-manager-token diff --git a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/educates/11-session-manager/01-clusterroles.yaml b/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/educates/11-session-manager/01-clusterroles.yaml deleted file mode 100644 index c263611c1..000000000 --- a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/educates/11-session-manager/01-clusterroles.yaml +++ /dev/null @@ -1,809 +0,0 @@ ---- -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - name: educates-session-manager -aggregationRule: - clusterRoleSelectors: - - matchLabels: - rbac.educates.dev/extends-workshop-permissions: "true" -rules: [] - ---- -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - name: educates-session-manager:core - labels: - rbac.educates.dev/extends-workshop-permissions: "true" -rules: -- apiGroups: - - "" - resources: - - namespaces - verbs: - - "*" -- apiGroups: - - "" - resources: - - limitranges - - resourcequotas - verbs: - - "*" -- apiGroups: - - rbac.authorization.k8s.io - resources: - - clusterroles - - clusterrolebindings - verbs: - - "*" -- apiGroups: - - training.educates.dev - resources: - - workshops - - workshopsessions - - trainingportals - - workshopenvironments - - workshopallocations - - workshoprequests - verbs: - - "*" -- apiGroups: - - secrets.educates.dev - resources: - - secretcopiers - verbs: - - "*" - ---- -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - name: educates-view-session-role -rules: - - apiGroups: - - "" - resources: - - configmaps - - endpoints - - persistentvolumeclaims - - persistentvolumeclaims/status - - pods - - replicationcontrollers - - replicationcontrollers/scale - - serviceaccounts - - services - - services/status - verbs: - - get - - list - - watch - - apiGroups: - - "" - resources: - - bindings - - events - - limitranges - - namespaces/status - - pods/log - - pods/status - - replicationcontrollers/status - - resourcequotas - - resourcequotas/status - verbs: - - get - - list - - watch - - apiGroups: - - "" - resources: - - namespaces - verbs: - - get - - list - - watch - - apiGroups: - - apps - resources: - - controllerrevisions - - daemonsets - - daemonsets/status - - deployments - - deployments/scale - - deployments/status - - replicasets - - replicasets/scale - - replicasets/status - - statefulsets - - statefulsets/scale - - statefulsets/status - verbs: - - get - - list - - watch - - apiGroups: - - autoscaling - resources: - - horizontalpodautoscalers - - horizontalpodautoscalers/status - verbs: - - get - - list - - watch - - apiGroups: - - batch - resources: - - cronjobs - - cronjobs/status - - jobs - - jobs/status - verbs: - - get - - list - - watch - - apiGroups: - - extensions - resources: - - daemonsets - - daemonsets/status - - deployments - - deployments/scale - - deployments/status - - ingresses - - ingresses/status - #! - networkpolicies - - replicasets - - replicasets/scale - - replicasets/status - - replicationcontrollers/scale - verbs: - - get - - list - - watch - - apiGroups: - - policy - resources: - - poddisruptionbudgets - - poddisruptionbudgets/status - verbs: - - get - - list - - watch - - apiGroups: - - networking.k8s.io - resources: - - ingresses - - ingresses/status - #! - networkpolicies - verbs: - - get - - list - - watch - ---- -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - name: educates-edit-session-role -rules: - - apiGroups: - - "" - resources: - - pods/attach - - pods/exec - - pods/portforward - - pods/proxy - - secrets - - services/proxy - verbs: - - get - - list - - watch - - apiGroups: - - "" - resources: - - serviceaccounts - verbs: - - impersonate - - apiGroups: - - "" - resources: - - pods - - pods/attach - - pods/exec - - pods/portforward - - pods/proxy - verbs: - - create - - delete - - deletecollection - - patch - - update - - apiGroups: - - "" - resources: - - configmaps - - endpoints - - persistentvolumeclaims - - replicationcontrollers - - replicationcontrollers/scale - - secrets - - serviceaccounts - - services - - services/proxy - verbs: - - create - - delete - - deletecollection - - patch - - update - - apiGroups: - - apps - resources: - - daemonsets - - deployments - - deployments/rollback - - deployments/scale - - replicasets - - replicasets/scale - - statefulsets - - statefulsets/scale - verbs: - - create - - delete - - deletecollection - - patch - - update - - apiGroups: - - autoscaling - resources: - - horizontalpodautoscalers - verbs: - - create - - delete - - deletecollection - - patch - - update - - apiGroups: - - batch - resources: - - cronjobs - - jobs - verbs: - - create - - delete - - deletecollection - - patch - - update - - apiGroups: - - extensions - resources: - - daemonsets - - deployments - - deployments/rollback - - deployments/scale - - ingresses - - replicasets - - replicasets/scale - - replicationcontrollers/scale - verbs: - - create - - delete - - deletecollection - - patch - - update - - apiGroups: - - policy - resources: - - poddisruptionbudgets - verbs: - - create - - delete - - deletecollection - - patch - - update - - apiGroups: - - networking.k8s.io - resources: - - ingresses - verbs: - - create - - delete - - deletecollection - - patch - - update - - apiGroups: - - "" - resources: - - configmaps - - endpoints - - persistentvolumeclaims - - persistentvolumeclaims/status - - pods - - replicationcontrollers - - replicationcontrollers/scale - - serviceaccounts - - services - - services/status - verbs: - - get - - list - - watch - - apiGroups: - - "" - resources: - - bindings - - events - - limitranges - - namespaces/status - - pods/log - - pods/status - - replicationcontrollers/status - - resourcequotas - - resourcequotas/status - verbs: - - get - - list - - watch - - apiGroups: - - "" - resources: - - namespaces - verbs: - - get - - list - - watch - - apiGroups: - - apps - resources: - - controllerrevisions - - daemonsets - - daemonsets/status - - deployments - - deployments/scale - - deployments/status - - replicasets - - replicasets/scale - - replicasets/status - - statefulsets - - statefulsets/scale - - statefulsets/status - verbs: - - get - - list - - watch - - apiGroups: - - autoscaling - resources: - - horizontalpodautoscalers - - horizontalpodautoscalers/status - verbs: - - get - - list - - watch - - apiGroups: - - batch - resources: - - cronjobs - - cronjobs/status - - jobs - - jobs/status - verbs: - - get - - list - - watch - - apiGroups: - - extensions - resources: - - daemonsets - - daemonsets/status - - deployments - - deployments/scale - - deployments/status - - ingresses - - ingresses/status - #! - networkpolicies - - replicasets - - replicasets/scale - - replicasets/status - - replicationcontrollers/scale - verbs: - - get - - list - - watch - - apiGroups: - - policy - resources: - - poddisruptionbudgets - - poddisruptionbudgets/status - verbs: - - get - - list - - watch - - apiGroups: - - networking.k8s.io - resources: - - ingresses - - ingresses/status - #! - networkpolicies - verbs: - - get - - list - - watch - ---- -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - name: educates-admin-session-role -rules: - - apiGroups: - - "" - resources: - - pods/attach - - pods/exec - - pods/portforward - - pods/proxy - - secrets - - services/proxy - verbs: - - get - - list - - watch - - apiGroups: - - "" - resources: - - serviceaccounts - verbs: - - impersonate - - apiGroups: - - "" - resources: - - pods - - pods/attach - - pods/exec - - pods/portforward - - pods/proxy - verbs: - - create - - delete - - deletecollection - - patch - - update - - apiGroups: - - "" - resources: - - configmaps - - endpoints - - persistentvolumeclaims - - replicationcontrollers - - replicationcontrollers/scale - - secrets - - serviceaccounts - - services - - services/proxy - verbs: - - create - - delete - - deletecollection - - patch - - update - - apiGroups: - - apps - resources: - - daemonsets - - deployments - - deployments/rollback - - deployments/scale - - replicasets - - replicasets/scale - - statefulsets - - statefulsets/scale - verbs: - - create - - delete - - deletecollection - - patch - - update - - apiGroups: - - autoscaling - resources: - - horizontalpodautoscalers - verbs: - - create - - delete - - deletecollection - - patch - - update - - apiGroups: - - batch - resources: - - cronjobs - - jobs - verbs: - - create - - delete - - deletecollection - - patch - - update - - apiGroups: - - extensions - resources: - - daemonsets - - deployments - - deployments/rollback - - deployments/scale - - ingresses - - replicasets - - replicasets/scale - - replicationcontrollers/scale - verbs: - - create - - delete - - deletecollection - - patch - - update - - apiGroups: - - policy - resources: - - poddisruptionbudgets - verbs: - - create - - delete - - deletecollection - - patch - - update - - apiGroups: - - networking.k8s.io - resources: - - ingresses - verbs: - - create - - delete - - deletecollection - - patch - - update - - apiGroups: - - "" - resources: - - configmaps - - endpoints - - persistentvolumeclaims - - persistentvolumeclaims/status - - pods - - replicationcontrollers - - replicationcontrollers/scale - - serviceaccounts - - services - - services/status - verbs: - - get - - list - - watch - - apiGroups: - - "" - resources: - - bindings - - events - - limitranges - - namespaces/status - - pods/log - - pods/status - - replicationcontrollers/status - - resourcequotas - - resourcequotas/status - verbs: - - get - - list - - watch - - apiGroups: - - "" - resources: - - namespaces - verbs: - - get - - list - - watch - - apiGroups: - - apps - resources: - - controllerrevisions - - daemonsets - - daemonsets/status - - deployments - - deployments/scale - - deployments/status - - replicasets - - replicasets/scale - - replicasets/status - - statefulsets - - statefulsets/scale - - statefulsets/status - verbs: - - get - - list - - watch - - apiGroups: - - autoscaling - resources: - - horizontalpodautoscalers - - horizontalpodautoscalers/status - verbs: - - get - - list - - watch - - apiGroups: - - batch - resources: - - cronjobs - - cronjobs/status - - jobs - - jobs/status - verbs: - - get - - list - - watch - - apiGroups: - - extensions - resources: - - daemonsets - - daemonsets/status - - deployments - - deployments/scale - - deployments/status - - ingresses - - ingresses/status - #! - networkpolicies - - replicasets - - replicasets/scale - - replicasets/status - - replicationcontrollers/scale - verbs: - - get - - list - - watch - - apiGroups: - - policy - resources: - - poddisruptionbudgets - - poddisruptionbudgets/status - verbs: - - get - - list - - watch - - apiGroups: - - networking.k8s.io - resources: - - ingresses - - ingresses/status - #! - networkpolicies - verbs: - - get - - list - - watch - - apiGroups: - - authorization.k8s.io - resources: - - localsubjectaccessreviews - verbs: - - create - - apiGroups: - - rbac.authorization.k8s.io - resources: - - rolebindings - - roles - verbs: - - create - - delete - - deletecollection - - get - - list - - patch - - update - - watch - ---- -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - name: educates-training-portal -rules: - - apiGroups: - - "" - resources: - - namespaces - resourceNames: - - default - verbs: - - get - - apiGroups: - - "" - resources: - - secrets - verbs: - - get - - list - - watch - - create - - apiGroups: - - training.educates.dev - resources: - - workshops - - workshopenvironments - - workshopsessions - - workshopallocations - - trainingportals - verbs: - - get - - list - - watch - - apiGroups: - - training.educates.dev - resources: - - trainingportals/finalizers - - workshopenvironments/finalizers - - workshopsessions/finalizers - verbs: - - update - - apiGroups: - - training.educates.dev - resources: - - workshopenvironments - - workshopsessions - - workshopallocations - verbs: - - create - - patch - - delete - ---- -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - name: educates-tunnel-manager -rules: -- apiGroups: - - "" - resources: - - events - verbs: - - create -- apiGroups: - - "" - resources: - - secrets - verbs: - - get - - list - - watch - - create - - delete - - deletecollection - - patch - - update -- apiGroups: - - "" - resources: - - namespaces - verbs: - - get - - list - - watch -- apiGroups: - - "" - resources: - - serviceaccounts - verbs: - - get - - list - - watch - - patch - - update -- apiGroups: - - training.educates.dev - resources: - - workshopsessions - verbs: - - get - - list - - watch diff --git a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/educates/11-session-manager/04-serviceaccounts.yaml b/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/educates/11-session-manager/04-serviceaccounts.yaml deleted file mode 100644 index 5877b2af3..000000000 --- a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/educates/11-session-manager/04-serviceaccounts.yaml +++ /dev/null @@ -1,26 +0,0 @@ -#@ load("@ytt:data", "data") - ---- -apiVersion: v1 -kind: ServiceAccount -metadata: - name: session-manager - namespace: #@ data.values.operator.namespace - annotations: - kapp.k14s.io/change-group: training.educates.dev/service-accounts - #! Following currently needed for kapp on OpenShift. - #! TODO: Bring kapp rebaseRules for Openshift service accounts -#! kapp.k14s.io/create-strategy: fallback-on-update -#! kapp.k14s.io/update-strategy: skip - ---- -apiVersion: v1 -kind: ServiceAccount -metadata: - name: image-puller - namespace: #@ data.values.operator.namespace - annotations: - #! Following currently needed for kapp on OpenShift. - #! TODO: Bring kapp rebaseRules for Openshift service accounts -#! kapp.k14s.io/create-strategy: fallback-on-update -#! kapp.k14s.io/update-strategy: skip diff --git a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/educates/11-session-manager/05-clusterrolebindings.yaml b/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/educates/11-session-manager/05-clusterrolebindings.yaml deleted file mode 100644 index a2c122f99..000000000 --- a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/educates/11-session-manager/05-clusterrolebindings.yaml +++ /dev/null @@ -1,119 +0,0 @@ -#@ load("@ytt:data", "data") - ---- -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRoleBinding -metadata: - name: educates-session-manager -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: ClusterRole - name: educates-session-manager -subjects: -- kind: ServiceAccount - name: session-manager - namespace: #@ data.values.operator.namespace - ---- -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRoleBinding -metadata: - name: educates-session-manager:admin -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: ClusterRole - name: admin -subjects: -- kind: ServiceAccount - name: session-manager - namespace: #@ data.values.operator.namespace - ---- -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRoleBinding -metadata: - name: educates-session-manager:kyverno-policies -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: ClusterRole - name: kyverno:rbac:admin:policies -subjects: -- kind: ServiceAccount - name: session-manager - namespace: #@ data.values.operator.namespace - -#@ if data.values.sessionManager.clusterAdmin: ---- -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRoleBinding -metadata: - name: educates-session-manager:cluster-admin -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: ClusterRole - name: cluster-admin -subjects: -- kind: ServiceAccount - name: session-manager - namespace: #@ data.values.operator.namespace -#@ end - -#@ if data.values.clusterSecurity.policyEngine == "pod-security-policies": ---- -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRoleBinding -metadata: - name: educates-session-manager-psp -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: ClusterRole - name: educates-baseline-psp -subjects: -- kind: ServiceAccount - name: session-manager - namespace: #@ data.values.operator.namespace - ---- -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRoleBinding -metadata: - name: educates-image-puller-psp -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: ClusterRole - name: educates-baseline-psp -subjects: -- kind: ServiceAccount - name: image-puller - namespace: #@ data.values.operator.namespace -#@ end - -#@ if data.values.clusterSecurity.policyEngine == "security-context-constraints": ---- -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRoleBinding -metadata: - name: educates-session-manager-scc -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: ClusterRole - name: educates-baseline-scc -subjects: -- kind: ServiceAccount - name: session-manager - namespace: #@ data.values.operator.namespace - ---- -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRoleBinding -metadata: - name: educates-image-puller-scc -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: ClusterRole - name: educates-baseline-scc -subjects: -- kind: ServiceAccount - name: image-puller - namespace: #@ data.values.operator.namespace -#@ end diff --git a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/educates/11-session-manager/06-secrets.yaml b/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/educates/11-session-manager/06-secrets.yaml deleted file mode 100644 index a0ce2249e..000000000 --- a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/educates/11-session-manager/06-secrets.yaml +++ /dev/null @@ -1,13 +0,0 @@ -#@ load("@ytt:data", "data") - ---- -apiVersion: v1 -kind: Secret -metadata: - name: session-manager-token - namespace: #@ data.values.operator.namespace - annotations: - kubernetes.io/service-account.name: "session-manager" - kapp.k14s.io/change-rule: upsert after upserting training.educates.dev/service-accounts -#! kapp.k14s.io/update-strategy: skip -type: kubernetes.io/service-account-token diff --git a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/educates/11-session-manager/07-daemonsets.yaml b/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/educates/11-session-manager/07-daemonsets.yaml deleted file mode 100644 index a30ef263a..000000000 --- a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/educates/11-session-manager/07-daemonsets.yaml +++ /dev/null @@ -1,56 +0,0 @@ -#@ load("@ytt:data", "data") -#@ load("/00-package.star", "image_reference", "image_pull_secrets", "image_pull_policy") - -#@ prepull = [] -#@ prepull.append("training-portal") -#@ prepull.extend(data.values.imagePuller.prePullImages) - ---- -#@ if data.values.imagePuller.enabled: -apiVersion: apps/v1 -kind: DaemonSet -metadata: - name: image-puller - namespace: #@ data.values.operator.namespace -spec: - selector: - matchLabels: - app: image-puller - template: - metadata: - labels: - app: image-puller - spec: - serviceAccountName: image-puller - securityContext: - runAsNonRoot: true - runAsUser: 1001 - #! seccompProfile: - #! type: RuntimeDefault - initContainers: - #@ images = data.values.imageVersions - #@ for i in range(len(prepull)): - #@ image = image_reference(prepull[i]) - #@ if image: - - name: #@ prepull[i] - image: #@ image - imagePullPolicy: #@ image_pull_policy(image) - command: ["/bin/true"] - #@ end - #@ end - containers: - - name: pause - #@ image = image_reference("pause-container") - image: #@ image - imagePullPolicy: #@ image_pull_policy(image) - securityContext: - allowPrivilegeEscalation: false - capabilities: - drop: ["ALL"] - #@ pull_secrets = image_pull_secrets() - #@ if pull_secrets: - #@overlay/match missing_ok=True - imagePullSecrets: #@ [{"name": name} for name in pull_secrets] - #@ end - -#@ end diff --git a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/educates/11-session-manager/07-deployments.yaml b/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/educates/11-session-manager/07-deployments.yaml deleted file mode 100644 index 0586069ac..000000000 --- a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/educates/11-session-manager/07-deployments.yaml +++ /dev/null @@ -1,70 +0,0 @@ -#@ load("@ytt:data", "data") -#@ load("@ytt:json", "json") -#@ load("@ytt:md5", "md5") -#@ load("/00-package.star", "image_reference", "image_pull_policy") - ---- -apiVersion: apps/v1 -kind: Deployment -metadata: - name: session-manager - namespace: #@ data.values.operator.namespace -spec: - replicas: 1 - selector: - matchLabels: - deployment: session-manager - strategy: - type: Recreate - template: - metadata: - labels: - deployment: session-manager - spec: - serviceAccountName: session-manager - automountServiceAccountToken: false - securityContext: - runAsNonRoot: true - runAsUser: 1001 - #! seccompProfile: - #! type: RuntimeDefault - containers: - - name: operator - #@ image = image_reference("session-manager") - image: #@ image - imagePullPolicy: #@ image_pull_policy(image) - securityContext: - allowPrivilegeEscalation: false - capabilities: - drop: ["ALL"] - startupProbe: - initialDelaySeconds: 15 - periodSeconds: 10 - timeoutSeconds: 1 - successThreshold: 1 - failureThreshold: 4 - httpGet: - path: /healthz?probe=startup - port: 8080 - livenessProbe: - initialDelaySeconds: 15 - periodSeconds: 30 - timeoutSeconds: 1 - successThreshold: 1 - failureThreshold: 3 - httpGet: - path: /healthz?probe=liveness - port: 8080 - volumeMounts: - - name: config - mountPath: /opt/app-root/config/ - - name: token - mountPath: /var/run/secrets/kubernetes.io/serviceaccount - readOnly: true - volumes: - - name: config - secret: - secretName: educates-config - - name: token - secret: - secretName: session-manager-token diff --git a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/educates/11-session-manager/10-secretcopiers.yaml b/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/educates/11-session-manager/10-secretcopiers.yaml deleted file mode 100644 index 297fddf5b..000000000 --- a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/educates/11-session-manager/10-secretcopiers.yaml +++ /dev/null @@ -1,111 +0,0 @@ -#@ load("@ytt:data", "data") -#@ load("/00-package.star", "image_pull_secrets") - -#@ ingress_secret_ref_name = data.values.clusterIngress.tlsCertificateRef.name -#@ ingress_secret_ref_namespace = data.values.clusterIngress.tlsCertificateRef.namespace - -#@ ingress_ca_secret_ref_name = data.values.clusterIngress.caCertificateRef.name -#@ ingress_ca_secret_ref_namespace = data.values.clusterIngress.caCertificateRef.namespace - ---- -apiVersion: secrets.educates.dev/v1beta1 -kind: SecretCopier -metadata: - name: educates-ingress-secrets -spec: - rules: - #@ if ingress_secret_ref_name and ingress_secret_ref_namespace and ingress_secret_ref_namespace != data.values.operator.namespace: - - sourceSecret: - name: #@ ingress_secret_ref_name - namespace: #@ ingress_secret_ref_namespace - targetNamespaces: - nameSelector: - matchNames: - - #@ data.values.operator.namespace - #@ end - #@ if ingress_ca_secret_ref_name and ingress_ca_secret_ref_namespace and ingress_ca_secret_ref_namespace != data.values.operator.namespace: - - sourceSecret: - name: #@ ingress_ca_secret_ref_name - namespace: #@ ingress_ca_secret_ref_namespace - targetNamespaces: - nameSelector: - matchNames: - - #@ data.values.operator.namespace - #@ end - -#@ secrets = [] -#@ for secret in data.values.clusterSecrets.pullSecretRefs: -#@ if secret["namespace"] and secret["namespace"] != data.values.operator.namespace: -#@ secrets.append(secret) -#@ end -#@ end -#@ if secrets: ---- -apiVersion: secrets.educates.dev/v1beta1 -kind: SecretCopier -metadata: - name: educates-upstream-image-pull-secrets -spec: - rules: - #@ for secret in secrets: - - sourceSecret: - name: #@ secret["name"] - namespace: #@ secret["namespace"] - targetNamespaces: - nameSelector: - matchNames: - - #@ data.values.operator.namespace - #@ end -#@ end - -#@ pull_secrets = image_pull_secrets() -#@ if pull_secrets: ---- -apiVersion: secrets.educates.dev/v1beta1 -kind: SecretCopier -metadata: - name: educates-downstream-image-pull-secrets -spec: - rules: - #@ for name in pull_secrets: - - sourceSecret: - name: #@ name - namespace: #@ data.values.operator.namespace - targetNamespaces: - labelSelector: - matchLabels: - training.educates.dev/component: portal - - sourceSecret: - name: #@ name - namespace: #@ data.values.operator.namespace - targetNamespaces: - labelSelector: - matchLabels: - training.educates.dev/component: environment - #@ end -#@ end - -#@ secrets = [] -#@ for secret in data.values.websiteStyling.themeDataRefs: -#@ if secret["namespace"] and secret["namespace"] != data.values.operator.namespace: -#@ secrets.append(secret) -#@ end -#@ end -#@ if secrets: ---- -apiVersion: secrets.educates.dev/v1beta1 -kind: SecretCopier -metadata: - name: educates-upstream-website-themes -spec: - rules: - #@ for secret in secrets: - - sourceSecret: - name: #@ secret["name"] - namespace: #@ secret["namespace"] - targetNamespaces: - nameSelector: - matchNames: - - #@ data.values.operator.namespace - #@ end -#@ end diff --git a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/educates/11-session-manager/10-secretinjectors.yaml b/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/educates/11-session-manager/10-secretinjectors.yaml deleted file mode 100644 index a41076c8d..000000000 --- a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/educates/11-session-manager/10-secretinjectors.yaml +++ /dev/null @@ -1,66 +0,0 @@ -#@ load("@ytt:data", "data") -#@ load("/00-package.star", "image_pull_secrets") - -#@ pull_secrets = image_pull_secrets() -#@ if pull_secrets: ---- -apiVersion: secrets.educates.dev/v1beta1 -kind: SecretInjector -metadata: - name: educates-image-pull-secrets -spec: - rules: - - targetNamespaces: - labelSelector: - matchLabels: - training.educates.dev/component: portal - sourceSecrets: - nameSelector: - matchNames: #@ pull_secrets - serviceAccounts: - labelSelector: - matchLabels: - training.educates.dev/component: portal - - targetNamespaces: - labelSelector: - matchLabels: - training.educates.dev/component: environment - sourceSecrets: - nameSelector: - matchNames: #@ pull_secrets - serviceAccounts: - labelSelector: - matchLabels: - training.educates.dev/component: environment - - targetNamespaces: - labelSelector: - matchLabels: - training.educates.dev/component: environment - sourceSecrets: - nameSelector: - matchNames: #@ pull_secrets - serviceAccounts: - labelSelector: - matchLabels: - training.educates.dev/component: session -#@ end - ---- -apiVersion: secrets.educates.dev/v1beta1 -kind: SecretInjector -metadata: - name: educates-registry-credentials -spec: - rules: - - targetNamespaces: - labelSelector: - matchLabels: - training.educates.dev/component: session - sourceSecrets: - nameSelector: - matchNames: - - educates-registry-credentials - serviceAccounts: - nameSelector: - matchNames: - - default diff --git a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/educates/_ytt_lib/kyverno-baseline/overlays.yaml b/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/educates/_ytt_lib/kyverno-baseline/overlays.yaml deleted file mode 100644 index 90b0ec9e3..000000000 --- a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/educates/_ytt_lib/kyverno-baseline/overlays.yaml +++ /dev/null @@ -1,36 +0,0 @@ -#@ load("@ytt:data", "data") -#@ load("@ytt:overlay", "overlay") - -#@overlay/match by=overlay.subset({"kind":"ClusterPolicy"}),expects="1+" ---- -metadata: - #@overlay/replace via=lambda left, right: "educates-baseline-{}".format(left) - name: null - -#@overlay/match by=overlay.subset({"kind":"ClusterPolicy"}),expects="1+" ---- -spec: - rules: - #@overlay/match by=overlay.all,expects="0+" - - match: - any: - #@overlay/match by=overlay.all,expects="0+" - - resources: - #@overlay/match missing_ok=True - namespaceSelector: - #@overlay/match missing_ok=True - matchExpressions: - - key: training.educates.dev/policy.engine - operator: In - values: - - kyverno - - key: training.educates.dev/policy.name - operator: In - values: - - baseline - - restricted - -#@overlay/match by=overlay.subset({"kind":"ClusterPolicy"}),expects="1+" ---- -spec: - validationFailureAction: Enforce diff --git a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/educates/_ytt_lib/kyverno-baseline/upstream/LICENSE b/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/educates/_ytt_lib/kyverno-baseline/upstream/LICENSE deleted file mode 100644 index 261eeb9e9..000000000 --- a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/educates/_ytt_lib/kyverno-baseline/upstream/LICENSE +++ /dev/null @@ -1,201 +0,0 @@ - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright [yyyy] [name of copyright owner] - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. diff --git a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/educates/_ytt_lib/kyverno-baseline/upstream/pod-security-cel/baseline/disallow-capabilities/disallow-capabilities.yaml b/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/educates/_ytt_lib/kyverno-baseline/upstream/pod-security-cel/baseline/disallow-capabilities/disallow-capabilities.yaml deleted file mode 100644 index b423f426b..000000000 --- a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/educates/_ytt_lib/kyverno-baseline/upstream/pod-security-cel/baseline/disallow-capabilities/disallow-capabilities.yaml +++ /dev/null @@ -1,42 +0,0 @@ -apiVersion: kyverno.io/v1 -kind: ClusterPolicy -metadata: - name: disallow-capabilities - annotations: - policies.kyverno.io/title: Disallow Capabilities in CEL expressions - policies.kyverno.io/category: Pod Security Standards (Baseline) in CEL - policies.kyverno.io/severity: medium - policies.kyverno.io/minversion: 1.11.0 - kyverno.io/kubernetes-version: "1.26-1.27" - policies.kyverno.io/subject: Pod - policies.kyverno.io/description: >- - Adding capabilities beyond those listed in the policy must be disallowed. -spec: - validationFailureAction: Audit - background: true - rules: - - name: adding-capabilities - match: - any: - - resources: - kinds: - - Pod - operations: - - CREATE - - UPDATE - validate: - cel: - variables: - - name: allowedCapabilities - expression: "['AUDIT_WRITE','CHOWN','DAC_OVERRIDE','FOWNER','FSETID','KILL','MKNOD','NET_BIND_SERVICE','SETFCAP','SETGID','SETPCAP','SETUID','SYS_CHROOT']" - - name: allContainers - expression: "(object.spec.containers + (has(object.spec.initContainers) ? object.spec.initContainers : []) + (has(object.spec.ephemeralContainers) ? object.spec.ephemeralContainers : []))" - expressions: - - expression: >- - variables.allContainers.all(container, - container.?securityContext.?capabilities.?add.orValue([]).all(capability, capability == '' || - capability in variables.allowedCapabilities)) - message: >- - Any capabilities added beyond the allowed list (AUDIT_WRITE, CHOWN, DAC_OVERRIDE, FOWNER, - FSETID, KILL, MKNOD, NET_BIND_SERVICE, SETFCAP, SETGID, SETPCAP, SETUID, SYS_CHROOT) - are disallowed. diff --git a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/educates/_ytt_lib/kyverno-baseline/upstream/pod-security-cel/baseline/disallow-host-namespaces/disallow-host-namespaces.yaml b/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/educates/_ytt_lib/kyverno-baseline/upstream/pod-security-cel/baseline/disallow-host-namespaces/disallow-host-namespaces.yaml deleted file mode 100644 index 2fafe9e33..000000000 --- a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/educates/_ytt_lib/kyverno-baseline/upstream/pod-security-cel/baseline/disallow-host-namespaces/disallow-host-namespaces.yaml +++ /dev/null @@ -1,39 +0,0 @@ -apiVersion: kyverno.io/v1 -kind: ClusterPolicy -metadata: - name: disallow-host-namespaces - annotations: - policies.kyverno.io/title: Disallow Host Namespaces in CEL expressions - policies.kyverno.io/category: Pod Security Standards (Baseline) in CEL - policies.kyverno.io/severity: medium - policies.kyverno.io/minversion: 1.11.0 - kyverno.io/kubernetes-version: "1.26-1.27" - policies.kyverno.io/subject: Pod - policies.kyverno.io/description: >- - Host namespaces (Process ID namespace, Inter-Process Communication namespace, and - network namespace) allow access to shared information and can be used to elevate - privileges. Pods should not be allowed access to host namespaces. This policy ensures - fields which make use of these host namespaces are unset or set to `false`. -spec: - validationFailureAction: Audit - background: true - rules: - - name: host-namespaces - match: - any: - - resources: - kinds: - - Pod - operations: - - CREATE - - UPDATE - validate: - cel: - expressions: - - expression: >- - ( object.spec.?hostNetwork.orValue(false) == false) && - ( object.spec.?hostIPC.orValue(false) == false) && - ( object.spec.?hostPID.orValue(false) == false) - message: >- - Sharing the host namespaces is disallowed. The fields spec.hostNetwork, - spec.hostIPC, and spec.hostPID must be unset or set to `false`. diff --git a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/educates/_ytt_lib/kyverno-baseline/upstream/pod-security-cel/baseline/disallow-host-path/disallow-host-path.yaml b/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/educates/_ytt_lib/kyverno-baseline/upstream/pod-security-cel/baseline/disallow-host-path/disallow-host-path.yaml deleted file mode 100644 index faa358038..000000000 --- a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/educates/_ytt_lib/kyverno-baseline/upstream/pod-security-cel/baseline/disallow-host-path/disallow-host-path.yaml +++ /dev/null @@ -1,33 +0,0 @@ -apiVersion: kyverno.io/v1 -kind: ClusterPolicy -metadata: - name: disallow-host-path - annotations: - policies.kyverno.io/title: Disallow hostPath in CEL expressions - policies.kyverno.io/category: Pod Security Standards (Baseline) in CEL - policies.kyverno.io/severity: medium - policies.kyverno.io/subject: Pod,Volume - policies.kyverno.io/minversion: 1.11.0 - kyverno.io/kubernetes-version: "1.26-1.27" - policies.kyverno.io/description: >- - HostPath volumes let Pods use host directories and volumes in containers. - Using host resources can be used to access shared data or escalate privileges - and should not be allowed. This policy ensures no hostPath volumes are in use. -spec: - validationFailureAction: Audit - background: true - rules: - - name: host-path - match: - any: - - resources: - kinds: - - Pod - operations: - - CREATE - - UPDATE - validate: - cel: - expressions: - - expression: "object.spec.?volumes.orValue([]).all(volume, size(volume) == 0 || !has(volume.hostPath))" - message: "HostPath volumes are forbidden. The field spec.volumes[*].hostPath must be unset" diff --git a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/educates/_ytt_lib/kyverno-baseline/upstream/pod-security-cel/baseline/disallow-host-ports-range/disallow-host-ports-range.yaml b/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/educates/_ytt_lib/kyverno-baseline/upstream/pod-security-cel/baseline/disallow-host-ports-range/disallow-host-ports-range.yaml deleted file mode 100644 index 211fc502a..000000000 --- a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/educates/_ytt_lib/kyverno-baseline/upstream/pod-security-cel/baseline/disallow-host-ports-range/disallow-host-ports-range.yaml +++ /dev/null @@ -1,45 +0,0 @@ -apiVersion: kyverno.io/v1 -kind: ClusterPolicy -metadata: - name: disallow-host-ports-range - annotations: - policies.kyverno.io/title: Disallow hostPorts Range (Alternate) in CEL expressions - policies.kyverno.io/category: Pod Security Standards (Baseline) in CEL - policies.kyverno.io/severity: medium - policies.kyverno.io/subject: Pod - policies.kyverno.io/minversion: 1.11.0 - kyverno.io/kubernetes-version: "1.26-1.27" - policies.kyverno.io/description: >- - Access to host ports allows potential snooping of network traffic and should not be - allowed, or at minimum restricted to a known list. This policy ensures the `hostPort` - field is set to one in the designated list. Note that Kubernetes Pod Security Admission - does not support this rule. -spec: - validationFailureAction: Audit - background: true - rules: - - name: host-port-range - match: - any: - - resources: - kinds: - - Pod - operations: - - CREATE - - UPDATE - validate: - cel: - variables: - - name: allContainers - expression: >- - object.spec.containers + - object.spec.?initContainers.orValue([]) + - object.spec.?ephemeralContainers.orValue([]) - expressions: - - expression: >- - variables.allContainers.all(container, - container.?ports.orValue([]).all(port, - size(port) == 0 || - !has(port.hostPort) || (port.hostPort >= 5000 && port.hostPort <= 6000) )) - message: >- - The only permitted hostPorts are in the range 5000-6000. diff --git a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/educates/_ytt_lib/kyverno-baseline/upstream/pod-security-cel/baseline/disallow-host-ports/disallow-host-ports.yaml b/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/educates/_ytt_lib/kyverno-baseline/upstream/pod-security-cel/baseline/disallow-host-ports/disallow-host-ports.yaml deleted file mode 100644 index b7603ecfb..000000000 --- a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/educates/_ytt_lib/kyverno-baseline/upstream/pod-security-cel/baseline/disallow-host-ports/disallow-host-ports.yaml +++ /dev/null @@ -1,53 +0,0 @@ -apiVersion: kyverno.io/v1 -kind: ClusterPolicy -metadata: - name: disallow-host-ports - annotations: - policies.kyverno.io/title: Disallow hostPorts in CEL expressions - policies.kyverno.io/category: Pod Security Standards (Baseline) in CEL - policies.kyverno.io/severity: medium - policies.kyverno.io/subject: Pod - policies.kyverno.io/minversion: 1.11.0 - kyverno.io/kubernetes-version: "1.26-1.27" - policies.kyverno.io/description: >- - Access to host ports allows potential snooping of network traffic and should not be - allowed, or at minimum restricted to a known list. This policy ensures the `hostPort` - field is unset or set to `0`. -spec: - validationFailureAction: Audit - background: true - rules: - - name: host-ports-none - match: - any: - - resources: - kinds: - - Pod - operations: - - CREATE - - UPDATE - validate: - cel: - expressions: - - expression: >- - object.spec.containers.all(container, !has(container.ports) || - container.ports.all(port, !has(port.hostPort) || port.hostPort == 0)) - message: >- - Use of host ports is disallowed. The field spec.containers[*].ports[*].hostPort - must either be unset or set to `0`. - - - expression: >- - !has(object.spec.initContainers) || - object.spec.initContainers.all(container, !has(container.ports) || - container.ports.all(port, !has(port.hostPort) || port.hostPort == 0)) - message: >- - Use of host ports is disallowed. The field spec.initContainers[*].ports[*].hostPort - must either be unset or set to `0`. - - - expression: >- - !has(object.spec.ephemeralContainers) || - object.spec.ephemeralContainers.all(container, !has(container.ports) || - container.ports.all(port, !has(port.hostPort) || port.hostPort == 0)) - message: >- - Use of host ports is disallowed. The field spec.ephemeralContainers[*].ports[*].hostPort - must either be unset or set to `0`. diff --git a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/educates/_ytt_lib/kyverno-baseline/upstream/pod-security-cel/baseline/disallow-host-process/disallow-host-process.yaml b/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/educates/_ytt_lib/kyverno-baseline/upstream/pod-security-cel/baseline/disallow-host-process/disallow-host-process.yaml deleted file mode 100644 index da74ffd67..000000000 --- a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/educates/_ytt_lib/kyverno-baseline/upstream/pod-security-cel/baseline/disallow-host-process/disallow-host-process.yaml +++ /dev/null @@ -1,43 +0,0 @@ -apiVersion: kyverno.io/v1 -kind: ClusterPolicy -metadata: - name: disallow-host-process - annotations: - policies.kyverno.io/title: Disallow hostProcess in CEL expressions - policies.kyverno.io/category: Pod Security Standards (Baseline) in CEL - policies.kyverno.io/severity: medium - policies.kyverno.io/subject: Pod - policies.kyverno.io/minversion: 1.11.0 - kyverno.io/kubernetes-version: "1.26-1.27" - policies.kyverno.io/description: >- - Windows pods offer the ability to run HostProcess containers which enables privileged - access to the Windows node. Privileged access to the host is disallowed in the baseline - policy. HostProcess pods are an alpha feature as of Kubernetes v1.22. This policy ensures - the `hostProcess` field, if present, is set to `false`. -spec: - validationFailureAction: Audit - background: true - rules: - - name: host-process-containers - match: - any: - - resources: - kinds: - - Pod - operations: - - CREATE - - UPDATE - validate: - cel: - variables: - - name: allContainers - expression: "(object.spec.containers + (has(object.spec.initContainers) ? object.spec.initContainers : []) + (has(object.spec.ephemeralContainers) ? object.spec.ephemeralContainers : []))" - expressions: - - expression: >- - variables.allContainers.all(container, - container.?securityContext.?windowsOptions.?hostProcess.orValue(false) == false) - message: >- - HostProcess containers are disallowed. The field spec.containers[*].securityContext.windowsOptions.hostProcess, - spec.initContainers[*].securityContext.windowsOptions.hostProcess, and - spec.ephemeralContainers[*].securityContext.windowsOptions.hostProcess - must either be undefined or set to `false`. diff --git a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/educates/_ytt_lib/kyverno-baseline/upstream/pod-security-cel/baseline/disallow-privileged-containers/disallow-privileged-containers.yaml b/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/educates/_ytt_lib/kyverno-baseline/upstream/pod-security-cel/baseline/disallow-privileged-containers/disallow-privileged-containers.yaml deleted file mode 100644 index 5046692e4..000000000 --- a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/educates/_ytt_lib/kyverno-baseline/upstream/pod-security-cel/baseline/disallow-privileged-containers/disallow-privileged-containers.yaml +++ /dev/null @@ -1,36 +0,0 @@ -apiVersion: kyverno.io/v1 -kind: ClusterPolicy -metadata: - name: disallow-privileged-containers - annotations: - policies.kyverno.io/title: Disallow Privileged Containers in CEL expressions - policies.kyverno.io/category: Pod Security Standards (Baseline) in CEL - policies.kyverno.io/severity: medium - policies.kyverno.io/subject: Pod - policies.kyverno.io/minversion: 1.11.0 - kyverno.io/kyverno-version: 1.11.0 - kyverno.io/kubernetes-version: "1.26-1.27" - policies.kyverno.io/description: >- - Privileged mode disables most security mechanisms and must not be allowed. This policy - ensures Pods do not call for privileged mode. -spec: - validationFailureAction: Audit - background: true - rules: - - name: privileged-containers - match: - any: - - resources: - kinds: - - Pod - operations: - - CREATE - - UPDATE - validate: - cel: - variables: - - name: allContainers - expression: "(object.spec.containers + (has(object.spec.initContainers) ? object.spec.initContainers : []) + (has(object.spec.ephemeralContainers) ? object.spec.ephemeralContainers : []))" - expressions: - - expression: "variables.allContainers.all(container, container.?securityContext.?privileged.orValue(false) == false)" - message: "Privileged mode is disallowed. All containers must set the securityContext.privileged field to `false` or unset the field." diff --git a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/educates/_ytt_lib/kyverno-baseline/upstream/pod-security-cel/baseline/disallow-proc-mount/disallow-proc-mount.yaml b/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/educates/_ytt_lib/kyverno-baseline/upstream/pod-security-cel/baseline/disallow-proc-mount/disallow-proc-mount.yaml deleted file mode 100644 index 6b12ea58d..000000000 --- a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/educates/_ytt_lib/kyverno-baseline/upstream/pod-security-cel/baseline/disallow-proc-mount/disallow-proc-mount.yaml +++ /dev/null @@ -1,38 +0,0 @@ -apiVersion: kyverno.io/v1 -kind: ClusterPolicy -metadata: - name: disallow-proc-mount - annotations: - policies.kyverno.io/title: Disallow procMount in CEL expressions - policies.kyverno.io/category: Pod Security Standards (Baseline) in CEL - policies.kyverno.io/severity: medium - policies.kyverno.io/subject: Pod - policies.kyverno.io/minversion: 1.11.0 - kyverno.io/kyverno-version: 1.11.0 - kyverno.io/kubernetes-version: "1.26-1.27" - policies.kyverno.io/description: >- - The default /proc masks are set up to reduce attack surface and should be required. This policy - ensures nothing but the default procMount can be specified. Note that in order for users - to deviate from the `Default` procMount requires setting a feature gate at the API - server. -spec: - validationFailureAction: Audit - background: true - rules: - - name: check-proc-mount - match: - any: - - resources: - kinds: - - Pod - operations: - - CREATE - - UPDATE - validate: - cel: - variables: - - name: allContainers - expression: "(object.spec.containers + (has(object.spec.initContainers) ? object.spec.initContainers : []) + (has(object.spec.ephemeralContainers) ? object.spec.ephemeralContainers : []))" - expressions: - - expression: "variables.allContainers.all(container, container.?securityContext.?procMount.orValue('Default') == 'Default')" - message: "Changing the proc mount from the default is not allowed." diff --git a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/educates/_ytt_lib/kyverno-baseline/upstream/pod-security-cel/baseline/disallow-selinux/disallow-selinux.yaml b/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/educates/_ytt_lib/kyverno-baseline/upstream/pod-security-cel/baseline/disallow-selinux/disallow-selinux.yaml deleted file mode 100644 index b78bbd4ce..000000000 --- a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/educates/_ytt_lib/kyverno-baseline/upstream/pod-security-cel/baseline/disallow-selinux/disallow-selinux.yaml +++ /dev/null @@ -1,74 +0,0 @@ -apiVersion: kyverno.io/v1 -kind: ClusterPolicy -metadata: - name: disallow-selinux - annotations: - policies.kyverno.io/title: Disallow SELinux in CEL expressions - policies.kyverno.io/category: Pod Security Standards (Baseline) in CEL - policies.kyverno.io/severity: medium - policies.kyverno.io/subject: Pod - policies.kyverno.io/minversion: 1.11.0 - kyverno.io/kyverno-version: 1.11.0 - kyverno.io/kubernetes-version: "1.26-1.27" - policies.kyverno.io/description: >- - SELinux options can be used to escalate privileges and should not be allowed. This policy - ensures that the `seLinuxOptions` field is undefined. -spec: - validationFailureAction: Audit - background: true - rules: - - name: selinux-type - match: - any: - - resources: - kinds: - - Pod - operations: - - CREATE - - UPDATE - validate: - cel: - variables: - - name: allContainerTypes - expression: "(object.spec.containers + (has(object.spec.initContainers) ? object.spec.initContainers : []) + (has(object.spec.ephemeralContainers) ? object.spec.ephemeralContainers : []))" - - name: seLinuxTypes - expression: "['container_t', 'container_init_t', 'container_kvm_t']" - expressions: - - expression: >- - (!has(object.spec.securityContext) || - !has(object.spec.securityContext.seLinuxOptions) || - !has(object.spec.securityContext.seLinuxOptions.type) || - variables.seLinuxTypes.exists(type, type == object.spec.securityContext.seLinuxOptions.type)) && - variables.allContainerTypes.all(container, - !has(container.securityContext) || - !has(container.securityContext.seLinuxOptions) || - !has(container.securityContext.seLinuxOptions.type) || - variables.seLinuxTypes.exists(type, type == container.securityContext.seLinuxOptions.type)) - message: >- - Setting the SELinux type is restricted. The field securityContext.seLinuxOptions.type must either be unset or set to one of the allowed values (container_t, container_init_t, or container_kvm_t). - - name: selinux-user-role - match: - any: - - resources: - kinds: - - Pod - operations: - - CREATE - - UPDATE - validate: - cel: - variables: - - name: allContainerTypes - expression: "(object.spec.containers + (has(object.spec.initContainers) ? object.spec.initContainers : []) + (has(object.spec.ephemeralContainers) ? object.spec.ephemeralContainers : []))" - expressions: - - expression: >- - (!has(object.spec.securityContext) || - !has(object.spec.securityContext.seLinuxOptions) || - (!has(object.spec.securityContext.seLinuxOptions.user) && !has(object.spec.securityContext.seLinuxOptions.role))) && - variables.allContainerTypes.all(container, - !has(container.securityContext) || - !has(container.securityContext.seLinuxOptions) || - (!has(container.securityContext.seLinuxOptions.user) && !has(container.securityContext.seLinuxOptions.role))) - message: >- - Setting the SELinux user or role is forbidden. The fields seLinuxOptions.user and seLinuxOptions.role must be unset. - \ No newline at end of file diff --git a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/educates/_ytt_lib/kyverno-baseline/upstream/pod-security-cel/baseline/restrict-seccomp/restrict-seccomp.yaml b/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/educates/_ytt_lib/kyverno-baseline/upstream/pod-security-cel/baseline/restrict-seccomp/restrict-seccomp.yaml deleted file mode 100644 index 4e74a34f6..000000000 --- a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/educates/_ytt_lib/kyverno-baseline/upstream/pod-security-cel/baseline/restrict-seccomp/restrict-seccomp.yaml +++ /dev/null @@ -1,46 +0,0 @@ -apiVersion: kyverno.io/v1 -kind: ClusterPolicy -metadata: - name: restrict-seccomp - annotations: - policies.kyverno.io/title: Restrict Seccomp in CEL expressions - policies.kyverno.io/category: Pod Security Standards (Baseline) in CEL - policies.kyverno.io/severity: medium - policies.kyverno.io/subject: Pod - policies.kyverno.io/minversion: 1.11.0 - kyverno.io/kyverno-version: 1.11.0 - kyverno.io/kubernetes-version: "1.26-1.27" - policies.kyverno.io/description: >- - The seccomp profile must not be explicitly set to Unconfined. This policy, - requiring Kubernetes v1.19 or later, ensures that seccomp is unset or - set to `RuntimeDefault` or `Localhost`. -spec: - background: true - validationFailureAction: Audit - rules: - - name: check-seccomp - match: - any: - - resources: - kinds: - - Pod - operations: - - CREATE - - UPDATE - validate: - cel: - variables: - - name: allContainers - expression: "(object.spec.containers + (has(object.spec.initContainers) ? object.spec.initContainers : []) + (has(object.spec.ephemeralContainers) ? object.spec.ephemeralContainers : []))" - - name: allowedProfileTypes - expression: "['RuntimeDefault', 'Localhost']" - expressions: - - expression: >- - (object.spec.?securityContext.?seccompProfile.?type.orValue('Localhost') - in variables.allowedProfileTypes) && - (variables.allContainers.all(container, - container.?securityContext.?seccompProfile.?type.orValue('Localhost') - in variables.allowedProfileTypes)) - message: >- - Use of custom Seccomp profiles is disallowed. The field - spec.containers[*].securityContext.seccompProfile.type must be unset or set to `RuntimeDefault` or `Localhost`. diff --git a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/educates/_ytt_lib/kyverno-baseline/upstream/pod-security-cel/baseline/restrict-sysctls/restrict-sysctls.yaml b/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/educates/_ytt_lib/kyverno-baseline/upstream/pod-security-cel/baseline/restrict-sysctls/restrict-sysctls.yaml deleted file mode 100644 index 294685d36..000000000 --- a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/educates/_ytt_lib/kyverno-baseline/upstream/pod-security-cel/baseline/restrict-sysctls/restrict-sysctls.yaml +++ /dev/null @@ -1,47 +0,0 @@ -apiVersion: kyverno.io/v1 -kind: ClusterPolicy -metadata: - name: restrict-sysctls - annotations: - policies.kyverno.io/title: Restrict sysctls in CEL expressions - policies.kyverno.io/category: Pod Security Standards (Baseline) in CEL - policies.kyverno.io/severity: medium - policies.kyverno.io/subject: Pod - policies.kyverno.io/minversion: 1.11.0 - kyverno.io/kyverno-version: 1.11.0 - kyverno.io/kubernetes-version: "1.26-1.27" - policies.kyverno.io/description: >- - Sysctls can disable security mechanisms or affect all containers on a - host, and should be disallowed except for an allowed "safe" subset. A - sysctl is considered safe if it is namespaced in the container or the - Pod, and it is isolated from other Pods or processes on the same Node. - This policy ensures that only those "safe" subsets can be specified in - a Pod. -spec: - validationFailureAction: Audit - background: true - rules: - - name: check-sysctls - match: - any: - - resources: - kinds: - - Pod - operations: - - CREATE - - UPDATE - validate: - cel: - variables: - - name: allowedSysctls - expression: "['kernel.shm_rmid_forced','net.ipv4.ip_local_port_range','net.ipv4.ip_unprivileged_port_start','net.ipv4.tcp_syncookies','net.ipv4.ping_group_range']" - expressions: - - expression: >- - object.spec.?securityContext.?sysctls.orValue([]).all(sysctl, sysctl == '' || - has(sysctl.name) && sysctl.name in variables.allowedSysctls) - message: >- - Setting additional sysctls above the allowed type is disallowed. - The field spec.securityContext.sysctls must be unset or not use any other names - than kernel.shm_rmid_forced, net.ipv4.ip_local_port_range, - net.ipv4.ip_unprivileged_port_start, net.ipv4.tcp_syncookies and - net.ipv4.ping_group_range. diff --git a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/educates/_ytt_lib/kyverno-policies/require-ingress-session-name.yaml b/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/educates/_ytt_lib/kyverno-policies/require-ingress-session-name.yaml deleted file mode 100644 index 5caf3b398..000000000 --- a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/educates/_ytt_lib/kyverno-policies/require-ingress-session-name.yaml +++ /dev/null @@ -1,33 +0,0 @@ -apiVersion: kyverno.io/v1 -kind: ClusterPolicy -metadata: - name: require-ingress-session-name -spec: - validationFailureAction: enforce - background: true - rules: - - name: require-ingress-session-name - match: - resources: - kinds: - - Ingress - context: - - name: session_namespace - apiCall: - urlPath: "/api/v1/namespaces/{{request.namespace}}" - jmesPath: 'metadata.labels."training.educates.dev/session.name" || ''@''' - preconditions: - all: - - key: "{{ request.operation }}" - operator: AnyIn - value: ["CREATE", "UPDATE"] - validate: - message: "Ingress host name must embed the workshop session name." - foreach: - - list: "request.object.spec.rules" - deny: - conditions: - any: - - key: "{{ contains(element.host, session_namespace) }}" - operator: NotEquals - value: true diff --git a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/educates/_ytt_lib/kyverno-policies/upstream/LICENSE b/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/educates/_ytt_lib/kyverno-policies/upstream/LICENSE deleted file mode 100644 index 261eeb9e9..000000000 --- a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/educates/_ytt_lib/kyverno-policies/upstream/LICENSE +++ /dev/null @@ -1,201 +0,0 @@ - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright [yyyy] [name of copyright owner] - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. diff --git a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/educates/_ytt_lib/kyverno-policies/upstream/best-practices-cel/disallow-empty-ingress-host/disallow-empty-ingress-host.yaml b/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/educates/_ytt_lib/kyverno-policies/upstream/best-practices-cel/disallow-empty-ingress-host/disallow-empty-ingress-host.yaml deleted file mode 100644 index 62df5473d..000000000 --- a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/educates/_ytt_lib/kyverno-policies/upstream/best-practices-cel/disallow-empty-ingress-host/disallow-empty-ingress-host.yaml +++ /dev/null @@ -1,35 +0,0 @@ -apiVersion: kyverno.io/v1 -kind: ClusterPolicy -metadata: - name: disallow-empty-ingress-host - annotations: - policies.kyverno.io/title: Disallow empty Ingress host in CEL expressions - policies.kyverno.io/category: Best Practices in CEL - policies.kyverno.io/minversion: 1.11.0 - kyverno.io/kubernetes-version: "1.26-1.27" - policies.kyverno.io/severity: medium - policies.kyverno.io/subject: Ingress - policies.kyverno.io/description: >- - An ingress resource needs to define an actual host name - in order to be valid. This policy ensures that there is a - hostname for each rule defined. -spec: - validationFailureAction: Audit - background: false - rules: - - name: disallow-empty-ingress-host - match: - any: - - resources: - kinds: - - Ingress - operations: - - CREATE - - UPDATE - validate: - cel: - expressions: - - expression: >- - object.spec.?rules.orValue([]).all(rule, has(rule.host) && has(rule.http)) - message: "The Ingress host name must be defined, not empty." - diff --git a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/educates/_ytt_lib/kyverno-policies/upstream/best-practices-cel/restrict-node-port/restrict-node-port.yaml b/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/educates/_ytt_lib/kyverno-policies/upstream/best-practices-cel/restrict-node-port/restrict-node-port.yaml deleted file mode 100644 index 9ea76c4b4..000000000 --- a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/educates/_ytt_lib/kyverno-policies/upstream/best-practices-cel/restrict-node-port/restrict-node-port.yaml +++ /dev/null @@ -1,36 +0,0 @@ -apiVersion: kyverno.io/v1 -kind: ClusterPolicy -metadata: - name: restrict-nodeport - annotations: - policies.kyverno.io/title: Disallow NodePort in CEL expressions - policies.kyverno.io/category: Best Practices in CEL - policies.kyverno.io/minversion: 1.11.0 - kyverno.io/kubernetes-version: "1.26-1.27" - policies.kyverno.io/severity: medium - policies.kyverno.io/subject: Service - policies.kyverno.io/description: >- - A Kubernetes Service of type NodePort uses a host port to receive traffic from - any source. A NetworkPolicy cannot be used to control traffic to host ports. - Although NodePort Services can be useful, their use must be limited to Services - with additional upstream security checks. This policy validates that any new Services - do not use the `NodePort` type. -spec: - validationFailureAction: Audit - background: true - rules: - - name: validate-nodeport - match: - any: - - resources: - kinds: - - Service - operations: - - CREATE - - UPDATE - validate: - cel: - expressions: - - expression: "has(object.spec.type) ? (object.spec.type != 'NodePort') : true" - message: "Services of type NodePort are not allowed." - diff --git a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/educates/_ytt_lib/kyverno-policies/upstream/best-practices-cel/restrict-service-external-ips/restrict-service-external-ips.yaml b/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/educates/_ytt_lib/kyverno-policies/upstream/best-practices-cel/restrict-service-external-ips/restrict-service-external-ips.yaml deleted file mode 100644 index 4d75de9da..000000000 --- a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/educates/_ytt_lib/kyverno-policies/upstream/best-practices-cel/restrict-service-external-ips/restrict-service-external-ips.yaml +++ /dev/null @@ -1,39 +0,0 @@ -apiVersion: kyverno.io/v1 -kind: ClusterPolicy -metadata: - name: restrict-external-ips - annotations: - policies.kyverno.io/title: Restrict External IPs in CEL expressions - policies.kyverno.io/category: Best Practices in CEL - policies.kyverno.io/minversion: 1.11.0 - kyverno.io/kubernetes-version: "1.26-1.27" - policies.kyverno.io/severity: medium - policies.kyverno.io/subject: Service - policies.kyverno.io/description: >- - Service externalIPs can be used for a MITM attack (CVE-2020-8554). - Restrict externalIPs or limit to a known set of addresses. - See: https://github.com/kyverno/kyverno/issues/1367. This policy validates - that the `externalIPs` field is not set on a Service. -spec: - validationFailureAction: Audit - background: true - rules: - - name: check-ips - match: - any: - - resources: - kinds: - - Service - operations: - - CREATE - - UPDATE - validate: - cel: - expressions: - - expression: "!has(object.spec.externalIPs)" - # restrict external IP addresses - # you can alternatively restrict to a known set of addresses using: - # !has(object.spec.externalIPs) || - # object.spec.externalIPs.all(ip, ip in ["37.10.11.53", "153.10.20.1"]) - message: "externalIPs are not allowed." - diff --git a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/educates/_ytt_lib/kyverno-policies/upstream/nginx-ingress-cel/disallow-ingress-nginx-custom-snippets/disallow-ingress-nginx-custom-snippets.yaml b/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/educates/_ytt_lib/kyverno-policies/upstream/nginx-ingress-cel/disallow-ingress-nginx-custom-snippets/disallow-ingress-nginx-custom-snippets.yaml deleted file mode 100644 index b8bf7d365..000000000 --- a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/educates/_ytt_lib/kyverno-policies/upstream/nginx-ingress-cel/disallow-ingress-nginx-custom-snippets/disallow-ingress-nginx-custom-snippets.yaml +++ /dev/null @@ -1,49 +0,0 @@ -apiVersion: kyverno.io/v1 -kind: ClusterPolicy -metadata: - name: disallow-ingress-nginx-custom-snippets - annotations: - policies.kyverno.io/title: Disallow Custom Snippets in CEL expressions - policies.kyverno.io/category: Security, NGINX Ingress in CEL - policies.kyverno.io/subject: ConfigMap, Ingress - policies.kyverno.io/minversion: "1.11.0" - kyverno.io/kyverno-version: "1.11.0" - kyverno.io/kubernetes-version: "1.26-1.27" - policies.kyverno.io/description: >- - Users that can create or update ingress objects can use the custom snippets - feature to obtain all secrets in the cluster (CVE-2021-25742). This policy - disables allow-snippet-annotations in the ingress-nginx configuration and - blocks *-snippet annotations on an Ingress. - See: https://github.com/kubernetes/ingress-nginx/issues/7837 -spec: - validationFailureAction: Enforce - rules: - - name: check-config-map - match: - any: - - resources: - kinds: - - ConfigMap - operations: - - CREATE - - UPDATE - validate: - cel: - expressions: - - expression: "object.?data[?'allow-snippet-annotations'].orValue('false') == 'false'" - message: "ingress-nginx allow-snippet-annotations must be set to false" - - name: check-ingress-annotations - match: - any: - - resources: - kinds: - - networking.k8s.io/v1/Ingress - operations: - - CREATE - - UPDATE - validate: - cel: - expressions: - - expression: "!object.metadata.?annotations.orValue([]).exists(annotation, annotation.endsWith('-snippet'))" - message: "ingress-nginx custom snippets are not allowed" - diff --git a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/educates/_ytt_lib/kyverno-policies/upstream/nginx-ingress-cel/restrict-annotations/restrict-annotations.yaml b/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/educates/_ytt_lib/kyverno-policies/upstream/nginx-ingress-cel/restrict-annotations/restrict-annotations.yaml deleted file mode 100644 index cf61a4ac9..000000000 --- a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/educates/_ytt_lib/kyverno-policies/upstream/nginx-ingress-cel/restrict-annotations/restrict-annotations.yaml +++ /dev/null @@ -1,44 +0,0 @@ -apiVersion: kyverno.io/v1 -kind: ClusterPolicy -metadata: - name: restrict-annotations - annotations: - policies.kyverno.io/title: Restrict NGINX Ingress annotation values in CEL expressions - policies.kyverno.io/category: Security, NGINX Ingress in CEL - policies.kyverno.io/severity: high - policies.kyverno.io/subject: Ingress - policies.kyverno.io/minversion: "1.11.0" - kyverno.io/kyverno-version: "1.11.0" - kyverno.io/kubernetes-version: "1.26-1.27" - policies.kyverno.io/description: >- - This policy mitigates CVE-2021-25746 by restricting `metadata.annotations` to safe values. - See: https://github.com/kubernetes/ingress-nginx/blame/main/internal/ingress/inspector/rules.go. - This issue has been fixed in NGINX Ingress v1.2.0. For NGINX Ingress version 1.0.5+ the - "annotation-value-word-blocklist" configuration setting is also recommended. - Please refer to the CVE for details. -spec: - validationFailureAction: Enforce - rules: - - name: check-ingress - match: - any: - - resources: - kinds: - - networking.k8s.io/v1/Ingress - operations: - - CREATE - - UPDATE - validate: - cel: - expressions: - - expression: >- - !has(object.metadata.annotations) || - ( - !object.metadata.annotations.exists(annotation, object.metadata.annotations[annotation].matches('\\s*alias\\s*.*;')) && - !object.metadata.annotations.exists(annotation, object.metadata.annotations[annotation].matches('\\s*root\\s*.*;')) && - !object.metadata.annotations.exists(annotation, object.metadata.annotations[annotation].matches('/etc/(passwd|shadow|group|nginx|ingress-controller)')) && - !object.metadata.annotations.exists(annotation, object.metadata.annotations[annotation].matches('/var/run/secrets')) && - !object.metadata.annotations.exists(annotation, object.metadata.annotations[annotation].matches('.*_by_lua.*')) - ) - message: "spec.rules[].http.paths[].path value is not allowed" - diff --git a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/educates/_ytt_lib/kyverno-policies/upstream/nginx-ingress-cel/restrict-ingress-paths/restrict-ingress-paths.yaml b/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/educates/_ytt_lib/kyverno-policies/upstream/nginx-ingress-cel/restrict-ingress-paths/restrict-ingress-paths.yaml deleted file mode 100644 index f65692e8f..000000000 --- a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/educates/_ytt_lib/kyverno-policies/upstream/nginx-ingress-cel/restrict-ingress-paths/restrict-ingress-paths.yaml +++ /dev/null @@ -1,39 +0,0 @@ -apiVersion: kyverno.io/v1 -kind: ClusterPolicy -metadata: - name: restrict-ingress-paths - annotations: - policies.kyverno.io/title: Restrict NGINX Ingress path values in CEL expressions - policies.kyverno.io/category: Security, NGINX Ingress in CEL - policies.kyverno.io/severity: high - policies.kyverno.io/subject: Ingress - policies.kyverno.io/minversion: "1.11.0" - kyverno.io/kyverno-version: "1.11.0" - kyverno.io/kubernetes-version: "1.26-1.27" - policies.kyverno.io/description: >- - This policy mitigates CVE-2021-25745 by restricting `spec.rules[].http.paths[].path` to safe values. - Additional paths can be added as required. This issue has been fixed in NGINX Ingress v1.2.0. - Please refer to the CVE for details. -spec: - validationFailureAction: Enforce - rules: - - name: check-paths - match: - any: - - resources: - kinds: - - networking.k8s.io/v1/Ingress - operations: - - CREATE - - UPDATE - validate: - cel: - expressions: - - expression: >- - object.spec.?rules.orValue([]).all(rule, - rule.?http.?paths.orValue([]).all(p, - !p.path.contains('/etc') && !p.path.contains('/var/run/secrets') && - !p.path.contains('/root') && !p.path.contains('/var/run/kubernetes/serviceaccount') && - !p.path.contains('/etc/kubernetes/admin.conf'))) - message: "spec.rules[].http.paths[].path value is not allowed" - diff --git a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/educates/_ytt_lib/kyverno-policies/upstream/other-cel/disallow-localhost-services/disallow-localhost-services.yaml b/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/educates/_ytt_lib/kyverno-policies/upstream/other-cel/disallow-localhost-services/disallow-localhost-services.yaml deleted file mode 100644 index 247f5d900..000000000 --- a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/educates/_ytt_lib/kyverno-policies/upstream/other-cel/disallow-localhost-services/disallow-localhost-services.yaml +++ /dev/null @@ -1,34 +0,0 @@ -apiVersion: kyverno.io/v1 -kind: ClusterPolicy -metadata: - name: no-localhost-service - annotations: - policies.kyverno.io/title: Disallow Localhost ExternalName Services in CEL expressions - policies.kyverno.io/category: Sample in CEL - policies.kyverno.io/severity: medium - policies.kyverno.io/subject: Service - policies.kyverno.io/minversion: 1.11.0 - kyverno.io/kubernetes-version: "1.26-1.27" - policies.kyverno.io/description: >- - A Service of type ExternalName which points back to localhost can potentially be used to exploit - vulnerabilities in some Ingress controllers. This policy audits Services of type ExternalName - if the externalName field refers to localhost. -spec: - validationFailureAction: Audit - background: true - rules: - - name: no-localhost-service - match: - any: - - resources: - kinds: - - Service - operations: - - CREATE - - UPDATE - validate: - cel: - expressions: - - expression: "object.spec.type != 'ExternalName' || object.spec.externalName != 'localhost'" - message: "Service of type ExternalName cannot point to localhost." - diff --git a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/educates/_ytt_lib/kyverno-policies/upstream/other-cel/prevent-cr8escape/prevent-cr8escape.yaml b/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/educates/_ytt_lib/kyverno-policies/upstream/other-cel/prevent-cr8escape/prevent-cr8escape.yaml deleted file mode 100644 index 7370ddda6..000000000 --- a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/educates/_ytt_lib/kyverno-policies/upstream/other-cel/prevent-cr8escape/prevent-cr8escape.yaml +++ /dev/null @@ -1,38 +0,0 @@ -apiVersion: kyverno.io/v1 -kind: ClusterPolicy -metadata: - name: prevent-cr8escape - annotations: - policies.kyverno.io/title: Prevent cr8escape (CVE-2022-0811) in CEL expressions - policies.kyverno.io/category: Other in CEL - policies.kyverno.io/severity: high - kyverno.io/kyverno-version: 1.11.0 - policies.kyverno.io/minversion: 1.11.0 - kyverno.io/kubernetes-version: "1.26-1.27" - policies.kyverno.io/subject: Pod - policies.kyverno.io/description: >- - A vulnerability "cr8escape" (CVE-2022-0811) in CRI-O the container runtime engine - underpinning Kubernetes allows attackers to escape from a Kubernetes container - and gain root access to the host. The recommended remediation is to disallow - sysctl settings with + or = in their value. -spec: - validationFailureAction: Enforce - background: true - rules: - - name: restrict-sysctls-cr8escape - match: - any: - - resources: - kinds: - - Pod - operations: - - CREATE - - UPDATE - validate: - cel: - expressions: - - expression: >- - object.spec.?securityContext.?sysctls.orValue([]).all(sysctl, - !has(sysctl.value) || (!sysctl.value.contains('+') && !sysctl.value.contains('='))) - message: "characters '+' or '=' are not allowed in sysctls values" - diff --git a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/educates/_ytt_lib/kyverno-restricted/overlays.yaml b/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/educates/_ytt_lib/kyverno-restricted/overlays.yaml deleted file mode 100644 index 6b0672fe4..000000000 --- a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/educates/_ytt_lib/kyverno-restricted/overlays.yaml +++ /dev/null @@ -1,41 +0,0 @@ -#@ load("@ytt:data", "data") -#@ load("@ytt:overlay", "overlay") - -#! We remove the policy which requires a seccompProfile be specified as it -#! is too restrictive and doesn't align well with how pod security policies -#! worked previously. We fallback instead on policy defined in baseline. - -#@overlay/match by=overlay.subset({"kind":"ClusterPolicy", "metadata":{"name": "restrict-seccomp-strict"}}) -#@overlay/remove ---- -#@overlay/match by=overlay.subset({"kind":"ClusterPolicy"}),expects="1+" ---- -metadata: - #@overlay/replace via=lambda left, right: "educates-restricted-{}".format(left) - name: null - -#@overlay/match by=overlay.subset({"kind":"ClusterPolicy"}),expects="1+" ---- -spec: - rules: - #@overlay/match by=overlay.all,expects="0+" - - match: - any: - #@overlay/match by=overlay.all,expects="0+" - - resources: - #@overlay/match missing_ok=True - namespaceSelector: - matchExpressions: - - key: training.educates.dev/policy.engine - operator: In - values: - - kyverno - - key: training.educates.dev/policy.name - operator: In - values: - - restricted - -#@overlay/match by=overlay.subset({"kind":"ClusterPolicy"}),expects="1+" ---- -spec: - validationFailureAction: Enforce diff --git a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/educates/_ytt_lib/kyverno-restricted/upstream/LICENSE b/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/educates/_ytt_lib/kyverno-restricted/upstream/LICENSE deleted file mode 100644 index 261eeb9e9..000000000 --- a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/educates/_ytt_lib/kyverno-restricted/upstream/LICENSE +++ /dev/null @@ -1,201 +0,0 @@ - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright [yyyy] [name of copyright owner] - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. diff --git a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/educates/_ytt_lib/kyverno-restricted/upstream/pod-security-cel/restricted/disallow-capabilities-strict/disallow-capabilities-strict.yaml b/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/educates/_ytt_lib/kyverno-restricted/upstream/pod-security-cel/restricted/disallow-capabilities-strict/disallow-capabilities-strict.yaml deleted file mode 100644 index 843e3ee55..000000000 --- a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/educates/_ytt_lib/kyverno-restricted/upstream/pod-security-cel/restricted/disallow-capabilities-strict/disallow-capabilities-strict.yaml +++ /dev/null @@ -1,89 +0,0 @@ -apiVersion: kyverno.io/v1 -kind: ClusterPolicy -metadata: - name: disallow-capabilities-strict - annotations: - policies.kyverno.io/title: Disallow Capabilities (Strict) in CEL expressions - policies.kyverno.io/category: Pod Security Standards (Restricted) in CEL - policies.kyverno.io/severity: medium - policies.kyverno.io/minversion: 1.11.0 - kyverno.io/kyverno-version: 1.11.0 - kyverno.io/kubernetes-version: "1.26-1.27" - policies.kyverno.io/subject: Pod - policies.kyverno.io/description: >- - Adding capabilities other than `NET_BIND_SERVICE` is disallowed. In addition, - all containers must explicitly drop `ALL` capabilities. -spec: - validationFailureAction: Audit - background: true - rules: - - name: require-drop-all - match: - any: - - resources: - kinds: - - Pod - operations: - - CREATE - - UPDATE - validate: - message: >- - Containers must drop `ALL` capabilities. - cel: - expressions: - - expression: >- - object.spec.containers.all(container, has(container.securityContext) && - has(container.securityContext.capabilities) && - has(container.securityContext.capabilities.drop) && - container.securityContext.capabilities.drop.exists_one(capability, capability == 'ALL')) - - - expression: >- - !has(object.spec.initContainers) || - object.spec.initContainers.all(container, has(container.securityContext) && - has(container.securityContext.capabilities) && - has(container.securityContext.capabilities.drop) && - container.securityContext.capabilities.drop.exists_one(capability, capability == 'ALL')) - - - expression: >- - !has(object.spec.ephemeralContainers) || - object.spec.ephemeralContainers.all(container, has(container.securityContext) && - has(container.securityContext.capabilities) && - has(container.securityContext.capabilities.drop) && - container.securityContext.capabilities.drop.exists_one(capability, capability == 'ALL')) - - name: adding-capabilities-strict - match: - any: - - resources: - kinds: - - Pod - operations: - - CREATE - - UPDATE - validate: - cel: - expressions: - - expression: >- - object.spec.containers.all(container, !has(container.securityContext) || - !has(container.securityContext.capabilities) || - !has(container.securityContext.capabilities.add) || - ((size(container.securityContext.capabilities.add) == 1) && (container.securityContext.capabilities.add[0] == 'NET_BIND_SERVICE'))) - message: >- - Any capabilities added other than NET_BIND_SERVICE are disallowed. - - - expression: >- - !has(object.spec.initContainers) || - object.spec.initContainers.all(container, !has(container.securityContext) || - !has(container.securityContext.capabilities) || - !has(container.securityContext.capabilities.add) || - ((size(container.securityContext.capabilities.add) == 1) && (container.securityContext.capabilities.add[0] == 'NET_BIND_SERVICE'))) - message: >- - Any capabilities added other than NET_BIND_SERVICE are disallowed. - - - expression: >- - !has(object.spec.ephemeralContainers) || - object.spec.ephemeralContainers.all(container, !has(container.securityContext) || - !has(container.securityContext.capabilities) || - !has(container.securityContext.capabilities.add) || - ((size(container.securityContext.capabilities.add) == 1) && (container.securityContext.capabilities.add[0] == 'NET_BIND_SERVICE'))) - message: >- - Any capabilities added other than NET_BIND_SERVICE are disallowed. diff --git a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/educates/_ytt_lib/kyverno-restricted/upstream/pod-security-cel/restricted/disallow-privilege-escalation/disallow-privilege-escalation.yaml b/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/educates/_ytt_lib/kyverno-restricted/upstream/pod-security-cel/restricted/disallow-privilege-escalation/disallow-privilege-escalation.yaml deleted file mode 100644 index d11f88ff9..000000000 --- a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/educates/_ytt_lib/kyverno-restricted/upstream/pod-security-cel/restricted/disallow-privilege-escalation/disallow-privilege-escalation.yaml +++ /dev/null @@ -1,43 +0,0 @@ -apiVersion: kyverno.io/v1 -kind: ClusterPolicy -metadata: - name: disallow-privilege-escalation - annotations: - policies.kyverno.io/title: Disallow Privilege Escalation in CEL - policies.kyverno.io/category: Pod Security Standards (Restricted) in CEL - policies.kyverno.io/severity: medium - policies.kyverno.io/subject: Pod - policies.kyverno.io/minversion: 1.11.0 - kyverno.io/kyverno-version: 1.11.0 - kyverno.io/kubernetes-version: "1.26-1.27" - policies.kyverno.io/description: >- - Privilege escalation, such as via set-user-ID or set-group-ID file mode, should not be allowed. - This policy ensures the `allowPrivilegeEscalation` field is set to `false`. -spec: - validationFailureAction: Audit - background: true - rules: - - name: privilege-escalation - match: - any: - - resources: - kinds: - - Pod - operations: - - CREATE - - UPDATE - validate: - cel: - variables: - - name: allContainers - expression: >- - object.spec.containers + - object.spec.?initContainers.orValue([]) + - object.spec.?ephemeralContainers.orValue([]) - expressions: - - expression: >- - variables.allContainers.all(container, - container.?securityContext.allowPrivilegeEscalation.orValue(true) == false) - message: >- - Privilege escalation is disallowed. - All containers must set the securityContext.allowPrivilegeEscalation field to `false`. diff --git a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/educates/_ytt_lib/kyverno-restricted/upstream/pod-security-cel/restricted/require-run-as-non-root-user/require-run-as-non-root-user.yaml b/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/educates/_ytt_lib/kyverno-restricted/upstream/pod-security-cel/restricted/require-run-as-non-root-user/require-run-as-non-root-user.yaml deleted file mode 100644 index 0bd042b0f..000000000 --- a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/educates/_ytt_lib/kyverno-restricted/upstream/pod-security-cel/restricted/require-run-as-non-root-user/require-run-as-non-root-user.yaml +++ /dev/null @@ -1,64 +0,0 @@ -apiVersion: kyverno.io/v1 -kind: ClusterPolicy -metadata: - name: require-run-as-non-root-user - annotations: - policies.kyverno.io/title: Require Run As Non-Root User in CEL - policies.kyverno.io/category: Pod Security Standards (Restricted) in CEL - policies.kyverno.io/severity: medium - policies.kyverno.io/subject: Pod - policies.kyverno.io/minversion: 1.11.0 - kyverno.io/kyverno-version: 1.11.0 - kyverno.io/kubernetes-version: "1.26-1.27" - policies.kyverno.io/description: >- - Containers must be required to run as non-root users. This policy ensures - `runAsUser` is either unset or set to a number greater than zero. -spec: - validationFailureAction: Audit - background: true - rules: - - name: run-as-non-root-user - match: - any: - - resources: - kinds: - - Pod - operations: - - CREATE - - UPDATE - validate: - cel: - expressions: - - expression: >- - !has(object.spec.securityContext) || - !has(object.spec.securityContext.runAsUser) || - object.spec.securityContext.runAsUser > 0 - message: >- - Running as root is not allowed. The field spec.securityContext.runAsUser must be unset or - set to a number greater than zero. - - - expression: >- - object.spec.containers.all(container, !has(container.securityContext) || - !has(container.securityContext.runAsUser) || - container.securityContext.runAsUser > 0) - message: >- - Running as root is not allowed. The field spec.containers[*].securityContext.runAsUser must be unset or - set to a number greater than zero - - - expression: >- - !has(object.spec.initContainers) || - object.spec.initContainers.all(container, !has(container.securityContext) || - !has(container.securityContext.runAsUser) || - container.securityContext.runAsUser > 0) - message: >- - Running as root is not allowed. The field spec.initContainers[*].securityContext.runAsUser must be unset or - set to a number greater than zero - - - expression: >- - !has(object.spec.ephemeralContainers) || - object.spec.ephemeralContainers.all(container, !has(container.securityContext) || - !has(container.securityContext.runAsUser) || - container.securityContext.runAsUser > 0) - message: >- - Running as root is not allowed. The field spec.ephemeralContainers[*].securityContext.runAsUser must be unset or - set to a number greater than zero diff --git a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/educates/_ytt_lib/kyverno-restricted/upstream/pod-security-cel/restricted/require-run-as-nonroot/require-run-as-nonroot.yaml b/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/educates/_ytt_lib/kyverno-restricted/upstream/pod-security-cel/restricted/require-run-as-nonroot/require-run-as-nonroot.yaml deleted file mode 100644 index 268fd2340..000000000 --- a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/educates/_ytt_lib/kyverno-restricted/upstream/pod-security-cel/restricted/require-run-as-nonroot/require-run-as-nonroot.yaml +++ /dev/null @@ -1,62 +0,0 @@ -apiVersion: kyverno.io/v1 -kind: ClusterPolicy -metadata: - name: require-run-as-nonroot - annotations: - policies.kyverno.io/title: Require runAsNonRoot in CEL - policies.kyverno.io/category: Pod Security Standards (Restricted) in CEL - policies.kyverno.io/severity: medium - policies.kyverno.io/subject: Pod - policies.kyverno.io/minversion: 1.11.0 - kyverno.io/kyverno-version: 1.11.0 - kyverno.io/kubernetes-version: "1.26-1.27" - policies.kyverno.io/description: >- - Containers must be required to run as non-root. This policy ensures - `runAsNonRoot` is set to true. -spec: - validationFailureAction: Audit - background: true - rules: - - name: run-as-non-root - match: - any: - - resources: - kinds: - - Pod - operations: - - CREATE - - UPDATE - validate: - cel: - expressions: - - expression: >- - ( - ( - has(object.spec.securityContext) && - has(object.spec.securityContext.runAsNonRoot) && - object.spec.securityContext.runAsNonRoot == true - ) && ( - ( - object.spec.containers + - (has(object.spec.initContainers) ? object.spec.initContainers : []) + - (has(object.spec.ephemeralContainers) ? object.spec.ephemeralContainers : []) - ).all(container, - !has(container.securityContext) || - !has(container.securityContext.runAsNonRoot) || - container.securityContext.runAsNonRoot == true) - ) - ) || ( - ( - object.spec.containers + - (has(object.spec.initContainers) ? object.spec.initContainers : []) + - (has(object.spec.ephemeralContainers) ? object.spec.ephemeralContainers : []) - ).all(container, - has(container.securityContext) && - has(container.securityContext.runAsNonRoot) && - container.securityContext.runAsNonRoot == true) - ) - message: >- - Running as root is not allowed. Either the field spec.securityContext.runAsNonRoot or all of - spec.containers[*].securityContext.runAsNonRoot, spec.initContainers[*].securityContext.runAsNonRoot and - spec.ephemeralContainers[*].securityContext.runAsNonRoot, must be set to true. - diff --git a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/educates/_ytt_lib/kyverno-restricted/upstream/pod-security-cel/restricted/restrict-seccomp-strict/restrict-seccomp-strict.yaml b/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/educates/_ytt_lib/kyverno-restricted/upstream/pod-security-cel/restricted/restrict-seccomp-strict/restrict-seccomp-strict.yaml deleted file mode 100644 index b1c75662f..000000000 --- a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/educates/_ytt_lib/kyverno-restricted/upstream/pod-security-cel/restricted/restrict-seccomp-strict/restrict-seccomp-strict.yaml +++ /dev/null @@ -1,75 +0,0 @@ -apiVersion: kyverno.io/v1 -kind: ClusterPolicy -metadata: - name: restrict-seccomp-strict - annotations: - policies.kyverno.io/title: Restrict Seccomp (Strict) in CEL - policies.kyverno.io/category: Pod Security Standards (Restricted) in CEL - policies.kyverno.io/severity: medium - policies.kyverno.io/subject: Pod - policies.kyverno.io/minversion: 1.11.0 - kyverno.io/kyverno-version: 1.11.0 - kyverno.io/kubernetes-version: "1.26-1.27" - policies.kyverno.io/description: >- - The seccomp profile in the Restricted group must not be explicitly set to Unconfined - but additionally must also not allow an unset value. This policy, - requiring Kubernetes v1.19 or later, ensures that seccomp is - set to `RuntimeDefault` or `Localhost`. A known issue prevents a policy such as this - using `anyPattern` from being persisted properly in Kubernetes 1.23.0-1.23.2. -spec: - background: true - validationFailureAction: Audit - rules: - - name: check-seccomp-strict - match: - any: - - resources: - kinds: - - Pod - operations: - - CREATE - - UPDATE - validate: - cel: - expressions: - - expression: >- - !has(object.spec.securityContext) || - !has(object.spec.securityContext.seccompProfile) || - !has(object.spec.securityContext.seccompProfile.type) || - object.spec.securityContext.seccompProfile.type == 'RuntimeDefault' || - object.spec.securityContext.seccompProfile.type == 'Localhost' - message: >- - Use of custom Seccomp profiles is disallowed. The field - spec.securityContext.seccompProfile.type must be set to `RuntimeDefault` or `Localhost`. - - - expression: >- - object.spec.containers.all(container, !has(container.securityContext) || - !has(container.securityContext.seccompProfile) || - !has(container.securityContext.seccompProfile.type) || - container.securityContext.seccompProfile.type == 'RuntimeDefault' || - container.securityContext.seccompProfile.type == 'Localhost') - message: >- - Use of custom Seccomp profiles is disallowed. The field - spec.containers[*].securityContext.seccompProfile.type must be set to `RuntimeDefault` or `Localhost`. - - - expression: >- - !has(object.spec.initContainers) || - object.spec.initContainers.all(container, !has(container.securityContext) || - !has(container.securityContext.seccompProfile) || - !has(container.securityContext.seccompProfile.type) || - container.securityContext.seccompProfile.type == 'RuntimeDefault' || - container.securityContext.seccompProfile.type == 'Localhost') - message: >- - Use of custom Seccomp profiles is disallowed. The field - spec.initContainers[*].securityContext.seccompProfile.type must be set to `RuntimeDefault` or `Localhost`. - - - expression: >- - !has(object.spec.ephemeralContainers) || - object.spec.ephemeralContainers.all(container, !has(container.securityContext) || - !has(container.securityContext.seccompProfile) || - !has(container.securityContext.seccompProfile.type) || - container.securityContext.seccompProfile.type == 'RuntimeDefault' || - container.securityContext.seccompProfile.type == 'Localhost') - message: >- - Use of custom Seccomp profiles is disallowed. The field - spec.ephemeralContainers[*].securityContext.seccompProfile.type must be set to `RuntimeDefault` or `Localhost`. diff --git a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/educates/_ytt_lib/kyverno-restricted/upstream/pod-security-cel/restricted/restrict-volume-types/restrict-volume-types.yaml b/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/educates/_ytt_lib/kyverno-restricted/upstream/pod-security-cel/restricted/restrict-volume-types/restrict-volume-types.yaml deleted file mode 100644 index 5dec2183d..000000000 --- a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/educates/_ytt_lib/kyverno-restricted/upstream/pod-security-cel/restricted/restrict-volume-types/restrict-volume-types.yaml +++ /dev/null @@ -1,45 +0,0 @@ -apiVersion: kyverno.io/v1 -kind: ClusterPolicy -metadata: - name: restrict-volume-types - annotations: - policies.kyverno.io/title: Restrict Volume Types in CEL - policies.kyverno.io/category: Pod Security Standards (Restricted) in CEL - policies.kyverno.io/severity: medium - policies.kyverno.io/subject: Pod,Volume - policies.kyverno.io/minversion: 1.11.0 - kyverno.io/kubernetes-version: "1.26-1.27" - kyverno.io/kyverno-version: 1.11.0 - policies.kyverno.io/description: >- - In addition to restricting HostPath volumes, the restricted pod security profile - limits usage of non-core volume types to those defined through PersistentVolumes. - This policy blocks any other type of volume other than those in the allow list. -spec: - validationFailureAction: Audit - background: true - rules: - - name: restricted-volumes - match: - any: - - resources: - kinds: - - Pod - operations: - - CREATE - - UPDATE - validate: - cel: - expressions: - - expression: >- - !has(object.spec.volumes) || - object.spec.volumes.all(vol, has(vol.configMap) || - has(vol.csi) || - has(vol.downwardAPI) || - has(vol.emptyDir) || - has(vol.ephemeral) || - has(vol.persistentVolumeClaim) || - has(vol.projected) || - has(vol.secret)) - message: >- - Only the following types of volumes may be used: configMap, csi, downwardAPI, - emptyDir, ephemeral, persistentVolumeClaim, projected, and secret. diff --git a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/educates/_ytt_lib/lookup-service-token/clusterrolebindings.yaml b/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/educates/_ytt_lib/lookup-service-token/clusterrolebindings.yaml deleted file mode 100644 index 05f2f3f15..000000000 --- a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/educates/_ytt_lib/lookup-service-token/clusterrolebindings.yaml +++ /dev/null @@ -1,13 +0,0 @@ -#! Cluster role bindings for the remote access. -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRoleBinding -metadata: - name: educates-remote-access -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: ClusterRole - name: educates-remote-access -subjects: -- kind: ServiceAccount - name: remote-access - namespace: educates diff --git a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/educates/_ytt_lib/lookup-service-token/clusterroles.yaml b/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/educates/_ytt_lib/lookup-service-token/clusterroles.yaml deleted file mode 100644 index b945fded8..000000000 --- a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/educates/_ytt_lib/lookup-service-token/clusterroles.yaml +++ /dev/null @@ -1,26 +0,0 @@ -#! Cluster role for the remote access clients. -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - name: educates-remote-access -rules: - - apiGroups: - - training.educates.dev - resources: - - trainingportals - - workshopenvironments - - workshopsessions - - workshopallocations - - workshops - verbs: - - get - - list - - watch - - apiGroups: - - "" - resources: - - customresourcedefinitions - verbs: - - get - - list - - watch diff --git a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/educates/_ytt_lib/lookup-service-token/secrets.yaml b/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/educates/_ytt_lib/lookup-service-token/secrets.yaml deleted file mode 100644 index 7ed512e00..000000000 --- a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/educates/_ytt_lib/lookup-service-token/secrets.yaml +++ /dev/null @@ -1,9 +0,0 @@ -apiVersion: v1 -kind: Secret -metadata: - name: remote-access-token - namespace: educates - annotations: - kubernetes.io/service-account.name: remote-access - kapp.k14s.io/change-rule: "upsert after upserting educates/sa-with-separate-token-secret" -type: kubernetes.io/service-account-token diff --git a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/educates/_ytt_lib/lookup-service-token/serviceaccounts.yaml b/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/educates/_ytt_lib/lookup-service-token/serviceaccounts.yaml deleted file mode 100644 index b31894cb2..000000000 --- a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/educates/_ytt_lib/lookup-service-token/serviceaccounts.yaml +++ /dev/null @@ -1,8 +0,0 @@ -#! ServiceAccount for remote access clients. -apiVersion: v1 -kind: ServiceAccount -metadata: - name: remote-access - namespace: educates - annotations: - kapp.k14s.io/change-group: "educates/sa-with-separate-token-secret" diff --git a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/educates/_ytt_lib/lookup-service/00-package.star b/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/educates/_ytt_lib/lookup-service/00-package.star deleted file mode 100644 index 43f7bc24d..000000000 --- a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/educates/_ytt_lib/lookup-service/00-package.star +++ /dev/null @@ -1,55 +0,0 @@ -load("@ytt:data", "data") -load("@ytt:base64", "base64") -load("@ytt:json", "json") - -def xgetattr(object, path, default=None): - def _lookup(object, key, default=None): - keys = key.split(".") - value = default - for key in keys: - value = getattr(object, key, None) - if value == None: - return default - end - object = value - end - return value - end - - return _lookup(object, path, default) -end - -def image_reference(name): - registry = xgetattr(data.values, "imageRegistry.host", "registry.default.svc.cluster.local") - if xgetattr(data.values, "imageRegistry.namespace", "") != "": - registry = "{}/{}".format(registry, data.values.imageRegistry.namespace) - end - image = "{}/educates-{}:{}".format(registry, name, data.values.version) - for item in data.values.imageVersions: - if item.name == name: - image = item.image - break - end - end - return image -end - -def image_pull_policy(image): - tag = image.split(":") - always = len(tag) <= 1 or tag[-1] in ["latest", "main", "master", "develop"] - return always and "Always" or "IfNotPresent" -end - -#! def image_pull_secrets(): -#! return [item["name"] for item in data.values.clusterSecrets.pullSecretRefs] -#! end -#! -#! def docker_config_json(host, username, password): -#! return json.encode({ -#! "auths": { -#! host: { -#! "auth": base64.encode("{}:{}".format(username, password)) -#! } -#! } -#! }) -#! end diff --git a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/educates/_ytt_lib/lookup-service/overlays.yaml/overlay-ca-injector.yaml b/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/educates/_ytt_lib/lookup-service/overlays.yaml/overlay-ca-injector.yaml deleted file mode 100644 index b6e8f517f..000000000 --- a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/educates/_ytt_lib/lookup-service/overlays.yaml/overlay-ca-injector.yaml +++ /dev/null @@ -1,40 +0,0 @@ -#@ load("@ytt:overlay", "overlay") -#@ load("@ytt:data", "data") - -#@overlay/match by=overlay.subset({"kind":"Deployment"}) ---- -spec: - template: - spec: - #@ if data.values.caName != None and data.values.caName != "": - #@overlay/match missing_ok=True - initContainers: - - name: ca-trust-store-initialization - image: #@ data.values.workshopBaseImage - imagePullPolicy: #@ data.values.workshopBaseImagePullPolicy - securityContext: - allowPrivilegeEscalation: false - runAsNonRoot: false - runAsUser: 0 - command: - - /opt/eduk8s/sbin/setup-certificates - volumeMounts: - - name: workshop-ca - mountPath: /etc/pki/ca-trust/source/anchors/Cluster_Ingress_CA.pem - subPath: ca.crt - - name: workshop-ca-trust - mountPath: /mnt - containers: - #@overlay/match by="name" - - name: lookup-service - volumeMounts: - - name: workshop-ca-trust - mountPath: /etc/pki/ca-trust - readOnly: true - volumes: - - name: workshop-ca - secret: - secretName: #@ data.values.caName - - name: workshop-ca-trust - emptyDir: {} - #@ end diff --git a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/educates/_ytt_lib/lookup-service/overlays.yaml/overlay-image.yaml b/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/educates/_ytt_lib/lookup-service/overlays.yaml/overlay-image.yaml deleted file mode 100644 index 9b8d0c701..000000000 --- a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/educates/_ytt_lib/lookup-service/overlays.yaml/overlay-image.yaml +++ /dev/null @@ -1,13 +0,0 @@ -#@ load("@ytt:overlay", "overlay") -#@ load("@ytt:data", "data") - -#@overlay/match by=overlay.subset({"kind":"Deployment"}) ---- -spec: - template: - spec: - containers: - #@overlay/match by="name" - - name: lookup-service - image: #@ data.values.image - imagePullPolicy: #@ data.values.imagePullPolicy \ No newline at end of file diff --git a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/educates/_ytt_lib/lookup-service/overlays.yaml/overlay-ingress.yaml b/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/educates/_ytt_lib/lookup-service/overlays.yaml/overlay-ingress.yaml deleted file mode 100644 index ed24c3e63..000000000 --- a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/educates/_ytt_lib/lookup-service/overlays.yaml/overlay-ingress.yaml +++ /dev/null @@ -1,25 +0,0 @@ -#@ load("@ytt:overlay", "overlay") -#@ load("@ytt:data", "data") - -#@overlay/match by=overlay.subset({"kind":"Ingress"}) ---- -metadata: - #@overlay/match missing_ok=True - #@ if/end data.values.certName: - annotations: - ingress.kubernetes.io/force-ssl-redirect: "true" - nginx.ingress.kubernetes.io/force-ssl-redirect: "true" - nginx.ingress.kubernetes.io/ssl-redirect: "true" -spec: - #@overlay/match missing_ok=True - #@ if/end data.values.ingressClass: - ingressClassName: #@ data.values.ingressClass - rules: - #@overlay/match by=overlay.index(0) - - host: #@ data.values.tld - #@overlay/match missing_ok=True - #@ if/end data.values.certName: - tls: - - hosts: - - #@ data.values.tld - secretName: #@ data.values.certName diff --git a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/educates/_ytt_lib/lookup-service/upstream/clusterrolebindings.yaml b/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/educates/_ytt_lib/lookup-service/upstream/clusterrolebindings.yaml deleted file mode 100644 index 9a710104a..000000000 --- a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/educates/_ytt_lib/lookup-service/upstream/clusterrolebindings.yaml +++ /dev/null @@ -1,13 +0,0 @@ -#! Cluster role bindings for the lookup service. -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRoleBinding -metadata: - name: educates-lookup-service -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: ClusterRole - name: educates-lookup-service -subjects: -- kind: ServiceAccount - name: lookup-service - namespace: educates diff --git a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/educates/_ytt_lib/lookup-service/upstream/clusterroles.yaml b/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/educates/_ytt_lib/lookup-service/upstream/clusterroles.yaml deleted file mode 100644 index c4ddc10b7..000000000 --- a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/educates/_ytt_lib/lookup-service/upstream/clusterroles.yaml +++ /dev/null @@ -1,74 +0,0 @@ -#! Cluster role for the lookup service application. -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - name: educates-lookup-service -rules: - #! We need ability to watch for changes to CRDs so kopf can tell if its own - #! custom resources have changed. - #! NOTE: Disabled as this results in Educates not being able to be uninstalled - #! when any of the lookup service configuration exists. - #! - apiGroups: - #! - apiextensions.k8s.io - #! resources: - #! - customresourcedefinitions - #! verbs: - #! - get - #! - list - #! - watch - #! We need the ability to watch for namespace changes. This is required by - #! kopf to know when to start and stop watching for changes to the specific - #! namespace is has been told to monitor. - - apiGroups: - - "" - resources: - - namespaces - verbs: - - get - - list - - watch - #! We need the ability to create events in the application namespace so kopf - #! can log events. - - apiGroups: - - "" - resources: - - events - verbs: - - create - #! We need read/write access to the ClusterConfig, ClientConfig and - #! TenantConfig custom resources from the lookup.educates.dev API group. - - apiGroups: - - lookup.educates.dev - resources: - - clusterconfigs - - clientconfigs - - tenantconfigs - verbs: - - get - - list - - watch - - patch - - update - #! We need update access to the finalizers of the ClusterConfig, ClientConfig - #! and TenantConfig custom resources from the lookup.educates.dev API group so - #! kopf can track deletion. - - apiGroups: - - lookup.educates.dev - resources: - - clusterconfigs/finalizers - - clientconfigs/finalizers - - tenantconfigs/finalizers - verbs: - - update - #! We need read access to the secrets in the application namespace, so we can - #! read the kubeconfig for the managed cluster. This is done as cluster role - #! rather than role against a namespace, as the actual namespace name is - #! configurable and not fixed. - - apiGroups: - - "" - resources: - - secrets - verbs: - - get - - list - - watch diff --git a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/educates/_ytt_lib/lookup-service/upstream/deployments.yaml b/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/educates/_ytt_lib/lookup-service/upstream/deployments.yaml deleted file mode 100644 index 0bfb24220..000000000 --- a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/educates/_ytt_lib/lookup-service/upstream/deployments.yaml +++ /dev/null @@ -1,30 +0,0 @@ -#! Deployment for the lookup service. It will be listening on port 8080. -apiVersion: apps/v1 -kind: Deployment -metadata: - name: lookup-service - namespace: educates -spec: - replicas: 1 - selector: - matchLabels: - app: lookup-service - template: - metadata: - labels: - app: lookup-service - spec: - serviceAccountName: lookup-service - containers: - - name: lookup-service - image: NAME - imagePullPolicy: Always - ports: - - containerPort: 8080 - volumeMounts: - - name: cluster-access-token - mountPath: /opt/cluster-access-token - volumes: - - name: cluster-access-token - secret: - secretName: remote-access-token diff --git a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/educates/_ytt_lib/lookup-service/upstream/ingresses.yaml b/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/educates/_ytt_lib/lookup-service/upstream/ingresses.yaml deleted file mode 100644 index ff81b35fe..000000000 --- a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/educates/_ytt_lib/lookup-service/upstream/ingresses.yaml +++ /dev/null @@ -1,18 +0,0 @@ -#! Ingress for the lookup service mapping to the lookup service Service. -apiVersion: networking.k8s.io/v1 -kind: Ingress -metadata: - name: lookup-service - namespace: educates -spec: - rules: - - host: HOST - http: - paths: - - path: / - pathType: Prefix - backend: - service: - name: lookup-service - port: - number: 80 diff --git a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/educates/_ytt_lib/lookup-service/upstream/serviceaccounts.yaml b/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/educates/_ytt_lib/lookup-service/upstream/serviceaccounts.yaml deleted file mode 100644 index 807d973ee..000000000 --- a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/educates/_ytt_lib/lookup-service/upstream/serviceaccounts.yaml +++ /dev/null @@ -1,6 +0,0 @@ -#! ServiceAccount to run the lookup service application. -apiVersion: v1 -kind: ServiceAccount -metadata: - name: lookup-service - namespace: educates diff --git a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/educates/_ytt_lib/lookup-service/upstream/services.yaml b/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/educates/_ytt_lib/lookup-service/upstream/services.yaml deleted file mode 100644 index aef1d259c..000000000 --- a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/educates/_ytt_lib/lookup-service/upstream/services.yaml +++ /dev/null @@ -1,13 +0,0 @@ -#! Service for the lookup service. -apiVersion: v1 -kind: Service -metadata: - name: lookup-service - namespace: educates -spec: - type: ClusterIP - ports: - - port: 80 - targetPort: 8080 - selector: - app: lookup-service diff --git a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/educates/_ytt_lib/values-schema.yaml b/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/educates/_ytt_lib/values-schema.yaml deleted file mode 100644 index d931ae6d8..000000000 --- a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/educates/_ytt_lib/values-schema.yaml +++ /dev/null @@ -1,13 +0,0 @@ -#@data/values-schema ---- -#! Ingress -tld: "" -certName: "" -ingressClass: "" -#! Custom CA -caName: "" -#! Images -image: "" -imagePullPolicy: "" -workshopBaseImage: "" -workshopBaseImagePullPolicy: "" diff --git a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/external-dns/overlays/.gitkeep b/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/external-dns/overlays/.gitkeep deleted file mode 100644 index e69de29bb..000000000 diff --git a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/external-dns/overlays/assertions.yaml b/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/external-dns/overlays/assertions.yaml deleted file mode 100644 index 66ac8ffda..000000000 --- a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/external-dns/overlays/assertions.yaml +++ /dev/null @@ -1,30 +0,0 @@ -#@ load("@ytt:data", "data") -#@ load("@ytt:assert", "assert") - -#@ if data.values.infraProvider == "custom": - -#! Search deployment args for provider and source flags -#@ providerFound = False -#@ sourceFound = False -#@ for entry in data.values.deployment.args: -#@ if entry.startswith("--provider"): -#@ providerFound = True -#@ end -#@ if entry.startswith("--source"): -#@ sourceFound = True -#@ end -#@ end - -#! Fail to render if provider or source flag are not present -#@ failMessage = "" -#@ if not providerFound: -#@ failMessage += "\n--provider is required in deployment.args to define a DNS provider where records will be created" -#@ end -#@ if not sourceFound: -#@ failMessage += "\n--source is required in deployment.args to query for endpoints" -#@ end -#@ if failMessage != "": -#@ assert.fail("Missing required values:{}".format(failMessage)) -#@ end - -#@ end diff --git a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/external-dns/overlays/defaults.star b/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/external-dns/overlays/defaults.star deleted file mode 100644 index a23ca2696..000000000 --- a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/external-dns/overlays/defaults.star +++ /dev/null @@ -1,72 +0,0 @@ -load("@ytt:data", "data") - -def get_default_aws_args(): - args = [ - "--provider=aws", - "--source=service", - "--aws-prefer-cname", - "--aws-zone-match-parent", - "--registry=txt", - "--txt-prefix=txt", - ] - #! These are removed as in AWS we just need the wildcard for the envoy service - #! "--source=ingress", - #! "--source=contour-httpproxy", - - if hasattr(data.values.aws, "args"): - if data.values.aws.args.zone_type: - args.append("--aws-zone-type={}".format(data.values.aws.args.zone_type)) - end - - if data.values.aws.args.policy: - args.append("--policy={}".format(data.values.aws.args.policy)) - end - - if data.values.aws.args.domain_filter: - args.append("--domain-filter={}".format(data.values.aws.args.domain_filter)) - end - - if data.values.aws.args.txt_owner_id: - args.append("--txt-owner-id={}".format(data.values.aws.args.txt_owner_id)) - end - end - - return args -end - -def get_default_google_args(): - args = [ - "--provider=google", - "--source=service", - "--log-format=json", - "--registry=txt", - "--txt-prefix=txt", - ] - #! These are removed as in GCP we just need the wildcard for the envoy service - #! "--source=ingress", - #! "--source=contour-httpproxy", - - if hasattr(data.values.gcp, "args"): - if data.values.gcp.args.zone_visibility: - args.append("--google-zone-visibility={}".format(data.values.gcp.args.zone_visibility)) - end - - if data.values.gcp.args.policy: - args.append("--policy={}".format(data.values.gcp.args.policy)) - end - - if data.values.gcp.args.domain_filter: - args.append("--domain-filter={}".format(data.values.gcp.args.domain_filter)) - end - - if data.values.gcp.args.txt_owner_id: - args.append("--txt-owner-id={}".format(data.values.gcp.args.txt_owner_id)) - end - - if data.values.gcp.args.project: - args.append("--google-project={}".format(data.values.gcp.args.project)) - end - end - - return args -end diff --git a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/external-dns/overlays/overlay-aws.yaml b/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/external-dns/overlays/overlay-aws.yaml deleted file mode 100644 index c687876b3..000000000 --- a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/external-dns/overlays/overlay-aws.yaml +++ /dev/null @@ -1,65 +0,0 @@ -#@ load("@ytt:overlay", "overlay") -#@ load("@ytt:data", "data") -#@ load("@ytt:base64", "base64") -#@ load("@ytt:assert", "assert") -#@ load("defaults.star", "get_default_aws_args") - -#@ if data.values.infraProvider=="aws": - -#@ (hasAwsCredsAccessKey, _) = assert.try_to(lambda: len(data.values.aws.credentials.accessKey) > 0) -#@ (hasAwsCredsSecretKey, _) = assert.try_to(lambda: len(data.values.aws.credentials.secretKey) > 0) -#@ if (hasAwsCredsSecretKey and not hasAwsCredsAccessKey) or (not hasAwsCredsSecretKey and hasAwsCredsAccessKey): -#@ assert.fail("`aws.credentials.accessKey` and `aws.credentials.secretKey` must both be provided") -#@ end - -#@overlay/match by=overlay.subset({"kind":"Deployment", "metadata": {"name": "external-dns"}}) -#@overlay/match-child-defaults missing_ok=True ---- -spec: - template: - spec: - containers: - #@overlay/match by="name" - - name: external-dns - #@overlay/replace - args: #@ get_default_aws_args() - -#@ if hasAwsCredsAccessKey and hasAwsCredsSecretKey: - -#! When providing the `aws.credentials` the provider must be `aws` -#@ if "--provider=aws" not in get_default_aws_args(): -#@ assert.fail("Use of `aws.credentials` requires using the aws provider") -#@ end - ---- -apiVersion: v1 -kind: Secret -metadata: - name: external-dns-aws-values - namespace: #@ data.values.namespace -type: Opaque -data: - awsAccessKeyID: #@ base64.encode("{}".format(data.values.aws.credentials.accessKey)) - awsSecretAccessKey: #@ base64.encode("{}".format(data.values.aws.credentials.secretKey)) - -#@overlay/match by=overlay.subset({"kind":"Deployment", "metadata":{"name":"external-dns"}}) -#@overlay/match-child-defaults missing_ok=True ---- -spec: - template: - spec: - containers: - #@overlay/match by=overlay.subset({"name": "external-dns"}) - - env: - - name: AWS_ACCESS_KEY_ID - valueFrom: - secretKeyRef: - name: external-dns-aws-values - key: awsAccessKeyID - - name: AWS_SECRET_ACCESS_KEY - valueFrom: - secretKeyRef: - name: external-dns-aws-values - key: awsSecretAccessKey -#@ end -#@ end diff --git a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/external-dns/overlays/overlay-azure.yaml b/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/external-dns/overlays/overlay-azure.yaml deleted file mode 100644 index 9a641b980..000000000 --- a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/external-dns/overlays/overlay-azure.yaml +++ /dev/null @@ -1,58 +0,0 @@ -#@ load("@ytt:overlay", "overlay") -#@ load("@ytt:data", "data") -#@ load("@ytt:json", "json") -#@ load("@ytt:struct", "struct") -#@ load("@ytt:assert", "assert") - -#@ if data.values.azure: -#@ if data.values.azure.resourceGroup == "": -#@ assert.fail("`data.values.azure.resourceGroup` must be specified") -#@ end -#@ if data.values.azure.tenantId == "": -#@ assert.fail("`data.values.azure.tenantId` must be specified") -#@ end -#@ if data.values.azure.subscriptionId == "": -#@ assert.fail("`data.values.azure.subscriptionId` must be specified") -#@ end -#@ if data.values.azure.useManagedIdentityExtension in [None, False] and data.values.azure.aadClientSecret in [None, ""]: -#@ assert.fail("`data.values.azure.aadClientSecret` must be specified if not using managed identity extension") -#@ end -#@ if data.values.azure.useManagedIdentityExtension in [None, False] and data.values.azure.aadClientId in [None, ""]: -#@ assert.fail("`data.values.azure.aadClientId` must be specified if not using managed identity extension") -#@ end -#@ -#@ json_data = {} -#@ azure_config = data.values.azure -#@ for key in azure_config: -#@ if azure_config[key] != None: -#@ json_data[key] = azure_config[key] -#@ end -#@ end - ---- -apiVersion: v1 -kind: Secret -metadata: - name: azure-config-file - namespace: #@ data.values.namespace -type: Opaque -stringData: - azure.json: #@ json.encode(json_data) - -#@overlay/match by=overlay.subset({"kind":"Deployment", "metadata":{"name":"external-dns"}}) -#@overlay/match-child-defaults missing_ok=True ---- -spec: - template: - spec: - volumes: - - name: azure-config-file - secret: - secretName: azure-config-file - containers: - #@overlay/match by=overlay.subset({"name": "external-dns"}) - - volumeMounts: - - name: azure-config-file - mountPath: /etc/kubernetes - readOnly: true -#@ end diff --git a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/external-dns/overlays/overlay-clusterrole.yaml b/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/external-dns/overlays/overlay-clusterrole.yaml deleted file mode 100644 index c577a0646..000000000 --- a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/external-dns/overlays/overlay-clusterrole.yaml +++ /dev/null @@ -1,10 +0,0 @@ -#@ load("@ytt:data", "data") -#@ load("@ytt:overlay", "overlay") - -#@overlay/match by=overlay.subset({"kind":"ClusterRole"}), expects=1 ---- -rules: - #@overlay/append - - apiGroups: ["projectcontour.io"] - resources: ["httpproxies"] - verbs: ["get", "watch", "list"] diff --git a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/external-dns/overlays/overlay-custom.yaml b/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/external-dns/overlays/overlay-custom.yaml deleted file mode 100644 index 13bb54ebe..000000000 --- a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/external-dns/overlays/overlay-custom.yaml +++ /dev/null @@ -1,28 +0,0 @@ -#@ load("@ytt:overlay", "overlay") -#@ load("@ytt:data", "data") - -#@ if data.values.infraProvider=="custom": - -#@overlay/match by=overlay.subset({"kind":"Deployment", "metadata":{"name":"external-dns"}}) ---- -spec: - template: - spec: - containers: - #@overlay/match by=overlay.subset({"name": "external-dns"}) - - name: external-dns - #@overlay/remove - args: - -#@overlay/match by=overlay.subset({"kind":"Deployment", "metadata":{"name":"external-dns"}}) -#@overlay/match-child-defaults missing_ok=True ---- -spec: - template: - spec: - containers: - #@overlay/match by=overlay.subset({"name": "external-dns"}) - - name: external-dns - args: #@ data.values.deployment.args - -#@ end diff --git a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/external-dns/overlays/overlay-deployment.yaml b/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/external-dns/overlays/overlay-deployment.yaml deleted file mode 100644 index 5bac5c5c0..000000000 --- a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/external-dns/overlays/overlay-deployment.yaml +++ /dev/null @@ -1,60 +0,0 @@ -#@ load("@ytt:overlay", "overlay") -#@ load("@ytt:data", "data") - -#! First remove upstream configuration, then replace. -#! The initial removal is because the ytt `replace` operator -#! doesn't add any missing keys (a "replace-insert" feature has been requested). -#! To avoid the case when upstream changes occur that add or remove keys, -#! we just remove all of them and then in the next block, add them back in. - -#@overlay/match by=overlay.subset({"kind":"Deployment", "metadata":{"name":"external-dns"}}) -#@overlay/match-child-defaults missing_ok=True ---- -spec: - template: - spec: - containers: - #@overlay/match by=overlay.subset({"name": "external-dns"}) - - - #@overlay/remove - env: - #@overlay/remove - securityContext: - #@overlay/remove - volumeMounts: - #@overlay/remove - volumes: - -#@overlay/match by=overlay.subset({"kind":"Deployment", "metadata":{"name":"external-dns"}}) -#@overlay/match-child-defaults missing_ok=True ---- -spec: - template: - #@overlay/merge missing_ok=True - metadata: - #@overlay/merge missing_ok=True - #@ if/end data.values.deployment.podLabels != None: - labels: #@ data.values.deployment.podLabels - spec: - containers: - #@overlay/match by="name" - - name: external-dns - #@ if/end data.values.deployment.env: - env: #@ data.values.deployment.env - #@ if data.values.deployment.securityContext: - securityContext: #@ data.values.deployment.securityContext - #@ else: - securityContext: - allowPrivilegeEscalation: false - runAsNonRoot: true - runAsUser: 65534 - readOnlyRootFilesystem: true - capabilities: - drop: ["ALL"] - seccompProfile: - type: RuntimeDefault - #@ end - #@ if/end data.values.deployment.volumeMounts: - volumeMounts: #@ data.values.deployment.volumeMounts - #@ if/end data.values.deployment.volumes: - volumes: #@ data.values.deployment.volumes diff --git a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/external-dns/overlays/overlay-google.yaml b/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/external-dns/overlays/overlay-google.yaml deleted file mode 100644 index 1db094187..000000000 --- a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/external-dns/overlays/overlay-google.yaml +++ /dev/null @@ -1,30 +0,0 @@ -#@ load("@ytt:overlay", "overlay") -#@ load("@ytt:data", "data") -#@ load("@ytt:base64", "base64") -#@ load("@ytt:assert", "assert") -#@ load("defaults.star", "get_default_google_args") - -#@ if data.values.infraProvider=="gcp": - -#@overlay/match by=overlay.subset({"kind":"Deployment", "metadata": {"name": "external-dns"}}) -#@overlay/match-child-defaults missing_ok=True ---- -spec: - template: - spec: - containers: - #@overlay/match by="name" - - name: external-dns - #@overlay/replace - args: #@ get_default_google_args() - -#@overlay/match by=overlay.subset({"kind":"Deployment", "metadata":{"name":"external-dns"}}) -#@overlay/match-child-defaults missing_ok=True ---- -spec: - template: - spec: - nodeSelector: - iam.gke.io/gke-metadata-server-enabled: "true" -#@ end - diff --git a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/external-dns/overlays/overlay-image.yaml b/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/external-dns/overlays/overlay-image.yaml deleted file mode 100644 index fbee27395..000000000 --- a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/external-dns/overlays/overlay-image.yaml +++ /dev/null @@ -1,15 +0,0 @@ -#@ load("@ytt:overlay", "overlay") -#@ load("@ytt:data", "data") - -#@overlay/match by=overlay.subset({"kind":"Deployment", "metadata": {"name": "external-dns"}}) ---- -spec: - template: - spec: - containers: - #@overlay/match by=overlay.map_key("name") - - name: external-dns - #@overlay/replace - image: #@ data.values.image.name - #@overlay/match missing_ok=True - imagePullPolicy: #@ data.values.image.pullPolicy \ No newline at end of file diff --git a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/external-dns/overlays/overlay-ns.yaml b/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/external-dns/overlays/overlay-ns.yaml deleted file mode 100644 index 87dc2c24b..000000000 --- a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/external-dns/overlays/overlay-ns.yaml +++ /dev/null @@ -1,27 +0,0 @@ -#@ load("@ytt:data", "data") -#@ load("@ytt:overlay", "overlay") - -#@ if/end data.values.createNamespace: -#@overlay/insert ---- -apiVersion: v1 -kind: Namespace -metadata: - name: #@ data.values.namespace - -#@ deployment=overlay.subset({"kind": "Deployment"}) -#@ sa=overlay.subset({"kind":"ServiceAccount"}) -#@overlay/match by=overlay.or_op(deployment, sa), expects=2 ---- -metadata: - #@overlay/match missing_ok=True - namespace: #@ data.values.namespace - -#@overlay/match by=overlay.subset({"kind":"ClusterRoleBinding"}) ---- -subjects: - #@overlay/match by="name" - - name: external-dns - #@overlay/match missing_ok=True - namespace: #@ data.values.namespace - diff --git a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/external-dns/overlays/overlay-serviceaccount.yaml b/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/external-dns/overlays/overlay-serviceaccount.yaml deleted file mode 100644 index 432b86f45..000000000 --- a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/external-dns/overlays/overlay-serviceaccount.yaml +++ /dev/null @@ -1,9 +0,0 @@ -#@ load("@ytt:data", "data") -#@ load("@ytt:overlay", "overlay") - -#@overlay/match by=overlay.subset({"kind":"ServiceAccount", "metadata":{"name":"external-dns"}}) -#@overlay/match-child-defaults missing_ok=True ---- -metadata: - #@ if/end data.values.serviceaccount.annotations: - annotations: #@ data.values.serviceaccount.annotations diff --git a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/external-dns/upstream/external-dns-clusterrole.yaml b/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/external-dns/upstream/external-dns-clusterrole.yaml deleted file mode 100644 index 5bcc705b4..000000000 --- a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/external-dns/upstream/external-dns-clusterrole.yaml +++ /dev/null @@ -1,17 +0,0 @@ -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - name: external-dns -rules: - - apiGroups: [''] - resources: ['endpoints', 'pods', 'services'] - verbs: ['get', 'watch', 'list'] - - apiGroups: ['extensions'] - resources: ['ingresses'] - verbs: ['get', 'watch', 'list'] - - apiGroups: ["networking.k8s.io"] - resources: ["ingresses"] - verbs: ["get","watch","list"] - - apiGroups: [""] - resources: ["nodes"] - verbs: ["watch", "list"] diff --git a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/external-dns/upstream/external-dns-clusterrolebinding.yaml b/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/external-dns/upstream/external-dns-clusterrolebinding.yaml deleted file mode 100644 index f50cfba77..000000000 --- a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/external-dns/upstream/external-dns-clusterrolebinding.yaml +++ /dev/null @@ -1,12 +0,0 @@ -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRoleBinding -metadata: - name: external-dns-viewer -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: ClusterRole - name: external-dns -subjects: - - kind: ServiceAccount - name: external-dns - namespace: default diff --git a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/external-dns/upstream/external-dns-deployment.yaml b/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/external-dns/upstream/external-dns-deployment.yaml deleted file mode 100644 index 989587b61..000000000 --- a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/external-dns/upstream/external-dns-deployment.yaml +++ /dev/null @@ -1,23 +0,0 @@ -apiVersion: apps/v1 -kind: Deployment -metadata: - name: external-dns -spec: - strategy: - type: Recreate - selector: - matchLabels: - app: external-dns - template: - metadata: - labels: - app: external-dns - spec: - serviceAccountName: external-dns - containers: - - name: external-dns - image: registry.k8s.io/external-dns/external-dns - args: - - --source=service - - --source=ingress - - --registry=txt diff --git a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/external-dns/upstream/external-dns-serviceaccount.yaml b/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/external-dns/upstream/external-dns-serviceaccount.yaml deleted file mode 100644 index 5b022409b..000000000 --- a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/external-dns/upstream/external-dns-serviceaccount.yaml +++ /dev/null @@ -1,4 +0,0 @@ -apiVersion: v1 -kind: ServiceAccount -metadata: - name: external-dns diff --git a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/external-dns/values-schema.yaml b/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/external-dns/values-schema.yaml deleted file mode 100644 index 110a3ddf1..000000000 --- a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/external-dns/values-schema.yaml +++ /dev/null @@ -1,136 +0,0 @@ -#! schema.yaml - -#@ def example_args(): -- --source=service -- --txt-owner-id=k8s -- --domain-filter=k8s.example.org -- --namespace=tanzu-system-service-discovery -- --provider=rfc2136 -- --rfc2136-host=100.69.97.77 -- --rfc2136-port=53 -- --rfc2136-zone=k8s.example.org -- --rfc2136-tsig-secret=MTlQs3NNU= -- --rfc2136-tsig-secret-alg=hmac-sha256 -- --rfc2136-tsig-keyname=externaldns-key -- --rfc2136-tsig-axfr -#@ end - -#@ def example_values(): ---- -namespace: tanzu-system-service-discovery -deployment: - args: #@ example_args() - env: [] - securityContext: {} - volumeMounts: [] - volumes: [] -serviceaccount: - annotations: - key: value -#@ end - -#@data/values-schema -#@schema/title "external-dns values schema" -#@schema/desc "OpenAPIv3 Schema for external-dns" -#@schema/examples ("Example of external-dns values", example_values()[0]) ---- -#@schema/desc "Infrastructure provider for the underlying infrastructure" -#@schema/validation one_of=["aws", "azure", "gcp", "custom"] -infraProvider: "custom" -#@schema/desc "The namespace in which to deploy ExternalDNS" -namespace: external-dns -#@schema/desc "Create/delete the namespace ExternalDNS is deployed to when the package is installed/uninstalled" -createNamespace: true -#@schema/desc "Image version to use for the ExternalDNS container" -image: - name: "registry.k8s.io/external-dns/external-dns:v0.14.2" - pullPolicy: "IfNotPresent" -#@schema/desc "Deployment related configuration" -deployment: - #@schema/desc "List of arguments passed via command-line to external-dns. For more guidance on configuration options for your desired DNS provider, consult the ExternalDNS docs at https://github.com/kubernetes-sigs/external-dns#running-externaldns." - #@schema/examples ("Example for rfc2136", example_args()) - args: [""] - #@schema/desc "List of environment variables to set in the external-dns container." - #@schema/nullable - env: - - name: "" - value: "" - #@schema/type any=True - valueFrom: null - #@schema/desc "SecurityContext defines the security options the external-dns container should be run with. More info: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/" - #@schema/type any=True - securityContext: null - #@schema/desc "Pod volumes to mount into the external-dns container's filesystem." - #@schema/nullable - volumeMounts: - #@schema/type any=True - - null - #@schema/desc "List of volumes that can be mounted by containers belonging to the external-dns pod. More info: https://kubernetes.io/docs/concepts/storage/volumes" - #@schema/nullable - volumes: - #@schema/type any=True - - null - #@schema/desc "Labels to be added to all deployment pods" - #@schema/type any=True - podLabels: null -#@schema/desc "Service account related configuration" -serviceaccount: - #@schema/desc "Annotations that can be set on the external-dns service account. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/annotations/" - #@schema/type any=True - annotations: null - -#@schema/desc "AWS provider related configuration" -#@schema/nullable -aws: - #@schema/nullable - credentials: - #@schema/desc "AWS access key. When provided along with the aws.secretKey, a Secret will be created and referenced in the external-dns Deployment." - accessKey: "" - #@schema/desc "AWS secret key. When provided along with the aws.accessKey, a Secret will be created and referenced in the external-dns Deployment." - secretKey: "" - args: - zone_type: "public" - policy: "upsert-only" - domain_filter: "" - txt_owner_id: "educates" - -#@schema/desc "Azure configuration. Package will create azure.json Secret, Volume, and VolumeMount with supplied values." -#@schema/nullable -azure: - #@schema/desc "AAD Client ID" - #@schema/nullable - aadClientId: "" - #@schema/desc "AAD Client Secret" - #@schema/nullable - aadClientSecret: "" - #@schema/desc "Cloud" - #@schema/nullable - cloud: "" - #@schema/desc "Resource Group" - resourceGroup: "" - #@schema/desc "Subscription ID" - subscriptionId: "" - #@schema/desc "Tenant ID" - tenantId: "" - #@schema/desc "Use manaaged identity extension" - #@schema/nullable - useManagedIdentityExtension: false - #@schema/desc "User Assigned Identity ID" - #@schema/nullable - userAssignedIdentityID: "" - -#@schema/desc "gcp provider related configuration" -#@schema/nullable -gcp: - #! #@schema/nullable - #! credentials: - #! #@schema/desc "AWS access key. When provided along with the aws.secretKey, a Secret will be created and referenced in the external-dns Deployment." - #! accessKey: "" - #! #@schema/desc "AWS secret key. When provided along with the aws.accessKey, a Secret will be created and referenced in the external-dns Deployment." - #! secretKey: "" - args: - project: "" - zone_visibility: "public" - policy: "upsert-only" - domain_filter: "" - txt_owner_id: "educates" diff --git a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/kapp-controller/upstream/release.yml b/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/kapp-controller/upstream/release.yml deleted file mode 100644 index 1e9bc737c..000000000 --- a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/kapp-controller/upstream/release.yml +++ /dev/null @@ -1,2711 +0,0 @@ ---- -apiVersion: v1 -kind: Namespace -metadata: - name: kapp-controller ---- -apiVersion: v1 -kind: Namespace -metadata: - name: kapp-controller-packaging-global ---- -apiVersion: apiregistration.k8s.io/v1 -kind: APIService -metadata: - name: v1alpha1.data.packaging.carvel.dev -spec: - group: data.packaging.carvel.dev - groupPriorityMinimum: 100 - service: - name: packaging-api - namespace: kapp-controller - version: v1alpha1 - versionPriority: 100 ---- -apiVersion: v1 -kind: Service -metadata: - name: packaging-api - namespace: kapp-controller -spec: - ports: - - name: main - port: 443 - protocol: TCP - targetPort: api - - name: metrics - port: 8080 - protocol: TCP - targetPort: metrics - selector: - app: kapp-controller ---- -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - name: internalpackagemetadatas.internal.packaging.carvel.dev -spec: - group: internal.packaging.carvel.dev - names: - kind: InternalPackageMetadata - listKind: InternalPackageMetadataList - plural: internalpackagemetadatas - singular: internalpackagemetadata - scope: Namespaced - versions: - - name: v1alpha1 - schema: - openAPIV3Schema: - properties: - apiVersion: - description: 'APIVersion defines the versioned schema of this representation - of an object. Servers should convert recognized schemas to the latest - internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' - type: string - kind: - description: 'Kind is a string value representing the REST resource this - object represents. Servers may infer this from the endpoint the client - submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' - type: string - metadata: - type: object - spec: - properties: - categories: - description: Classifiers of the package (optional; Array of strings) - items: - type: string - type: array - displayName: - description: Human friendly name of the package (optional; string) - type: string - iconSVGBase64: - description: Base64 encoded icon (optional; string) - type: string - longDescription: - description: Long description of the package (optional; string) - type: string - maintainers: - description: List of maintainer info for the package. Currently only - supports the name key. (optional; array of maintner info) - items: - properties: - name: - type: string - type: object - type: array - providerName: - description: Name of the entity distributing the package (optional; - string) - type: string - shortDescription: - description: Short desription of the package (optional; string) - type: string - supportDescription: - description: Description of the support available for the package - (optional; string) - type: string - type: object - required: - - spec - type: object - served: true - storage: true - subresources: - status: {} ---- -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - name: internalpackages.internal.packaging.carvel.dev -spec: - group: internal.packaging.carvel.dev - names: - kind: InternalPackage - listKind: InternalPackageList - plural: internalpackages - singular: internalpackage - scope: Namespaced - versions: - - name: v1alpha1 - schema: - openAPIV3Schema: - properties: - apiVersion: - description: 'APIVersion defines the versioned schema of this representation - of an object. Servers should convert recognized schemas to the latest - internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' - type: string - kind: - description: 'Kind is a string value representing the REST resource this - object represents. Servers may infer this from the endpoint the client - submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' - type: string - metadata: - type: object - spec: - properties: - capacityRequirementsDescription: - description: 'System requirements needed to install the package. Note: - these requirements will not be verified by kapp-controller on installation. - (optional; string)' - type: string - includedSoftware: - description: IncludedSoftware can be used to show the software contents - of a Package. This is especially useful if the underlying versions - do not match the Package version - items: - description: IncludedSoftware contains the underlying Software Contents - of a Package - properties: - description: - type: string - displayName: - type: string - version: - type: string - type: object - type: array - kappControllerVersionSelection: - description: KappControllerVersionSelection specifies the versions - of kapp-controller which can install this package - properties: - constraints: - type: string - type: object - kubernetesVersionSelection: - description: KubernetesVersionSelection specifies the versions of - k8s which this package can be installed on - properties: - constraints: - type: string - type: object - licenses: - description: Description of the licenses that apply to the package - software (optional; Array of strings) - items: - type: string - type: array - refName: - description: The name of the PackageMetadata associated with this - version Must be a valid PackageMetadata name (see PackageMetadata - CR for details) Cannot be empty - type: string - releaseNotes: - description: Version release notes (optional; string) - type: string - releasedAt: - description: Timestamp of release (iso8601 formatted string; optional) - format: date-time - nullable: true - type: string - template: - properties: - spec: - properties: - canceled: - description: Cancels current and future reconciliations (optional; - default=false) - type: boolean - cluster: - description: Specifies that app should be deployed to destination - cluster; by default, cluster is same as where this resource - resides (optional; v0.5.0+) - properties: - kubeconfigSecretRef: - description: Specifies secret containing kubeconfig (required) - properties: - key: - description: Specifies key that contains kubeconfig - (optional) - type: string - name: - description: Specifies secret name within app's namespace - (required) - type: string - type: object - namespace: - description: Specifies namespace in destination cluster - (optional) - type: string - type: object - defaultNamespace: - description: Specifies the default namespace to install the - App resources, by default this is same as the App's namespace - (optional; v0.48.0+) - type: string - deploy: - items: - properties: - kapp: - description: Use kapp to deploy resources - properties: - delete: - description: Configuration for delete command (optional) - properties: - rawOptions: - description: Pass through options to kapp delete - (optional) - items: - type: string - type: array - type: object - inspect: - description: 'Configuration for inspect command - (optional) as of kapp-controller v0.31.0, inspect - is disabled by default add rawOptions or use an - empty inspect config like `inspect: {}` to enable' - properties: - rawOptions: - description: Pass through options to kapp inspect - (optional) - items: - type: string - type: array - type: object - intoNs: - description: Override namespace for all resources - (optional) - type: string - mapNs: - description: Provide custom namespace override mapping - (optional) - items: - type: string - type: array - rawOptions: - description: Pass through options to kapp deploy - (optional) - items: - type: string - type: array - type: object - type: object - type: array - fetch: - items: - properties: - git: - description: Uses git to clone repository - properties: - depth: - description: depth of commits to fetch; 1 (default) - means only latest commit, 0 means everything (optional) - format: int64 - type: integer - forceHTTPBasicAuth: - description: Force the usage of HTTP Basic Auth - when Basic Auth is provided (optional) - type: boolean - lfsSkipSmudge: - description: Skip lfs download (optional) - type: boolean - ref: - description: Branch, tag, commit; origin is the - name of the remote (optional) - type: string - refSelection: - description: Specifies a strategy to resolve to - an explicit ref (optional; v0.24.0+) - properties: - semver: - properties: - constraints: - type: string - prereleases: - properties: - identifiers: - items: - type: string - type: array - type: object - type: object - type: object - secretRef: - description: 'Secret with auth details. allowed - keys: ssh-privatekey, ssh-knownhosts, username, - password (optional) (if ssh-knownhosts is not - specified, git will not perform strict host checking)' - properties: - name: - description: Object is expected to be within - same namespace - type: string - type: object - subPath: - description: Grab only portion of repository (optional) - type: string - url: - description: http or ssh urls are supported (required) - type: string - type: object - helmChart: - description: Uses helm fetch to fetch specified chart - properties: - name: - description: 'Example: stable/redis' - type: string - repository: - properties: - secretRef: - properties: - name: - description: Object is expected to be within - same namespace - type: string - type: object - url: - description: Repository url; scheme of oci:// - will fetch experimental helm oci chart (v0.19.0+) - (required) - type: string - type: object - version: - type: string - type: object - http: - description: Uses http library to fetch file - properties: - secretRef: - description: 'Secret to provide auth details (optional) - Secret may include one or more keys: username, - password' - properties: - name: - description: Object is expected to be within - same namespace - type: string - type: object - sha256: - description: Checksum to verify after download (optional) - type: string - subPath: - description: Grab only portion of download (optional) - type: string - url: - description: 'URL can point to one of following - formats: text, tgz, zip http and https url are - supported; plain file, tgz and tar types are supported - (required)' - type: string - type: object - image: - description: Pulls content from Docker/OCI registry - properties: - secretRef: - description: 'Secret may include one or more keys: - username, password, token. By default anonymous - access is used for authentication.' - properties: - name: - description: Object is expected to be within - same namespace - type: string - type: object - subPath: - description: Grab only portion of image (optional) - type: string - tagSelection: - description: Specifies a strategy to choose a tag - (optional; v0.24.0+) if specified, do not include - a tag in url key - properties: - semver: - properties: - constraints: - type: string - prereleases: - properties: - identifiers: - items: - type: string - type: array - type: object - type: object - type: object - url: - description: 'Docker image url; unqualified, tagged, - or digest references supported (required) Example: - username/app1-config:v0.1.0' - type: string - type: object - imgpkgBundle: - description: Pulls imgpkg bundle from Docker/OCI registry - (v0.17.0+) - properties: - image: - description: Docker image url; unqualified, tagged, - or digest references supported (required) - type: string - secretRef: - description: 'Secret may include one or more keys: - username, password, token. By default anonymous - access is used for authentication.' - properties: - name: - description: Object is expected to be within - same namespace - type: string - type: object - tagSelection: - description: Specifies a strategy to choose a tag - (optional; v0.24.0+) if specified, do not include - a tag in url key - properties: - semver: - properties: - constraints: - type: string - prereleases: - properties: - identifiers: - items: - type: string - type: array - type: object - type: object - type: object - type: object - inline: - description: Pulls content from within this resource; - or other resources in the cluster - properties: - paths: - additionalProperties: - type: string - description: Specifies mapping of paths to their - content; not recommended for sensitive values - as CR is not encrypted (optional) - type: object - pathsFrom: - description: Specifies content via secrets and config - maps; data values are recommended to be placed - in secrets (optional) - items: - properties: - configMapRef: - properties: - directoryPath: - description: Specifies where to place - files found in secret (optional) - type: string - name: - type: string - type: object - secretRef: - properties: - directoryPath: - description: Specifies where to place - files found in secret (optional) - type: string - name: - type: string - type: object - type: object - type: array - type: object - path: - description: Relative path to place the fetched artifacts - type: string - type: object - type: array - noopDelete: - description: Deletion requests for the App will result in - the App CR being deleted, but its associated resources will - not be deleted (optional; default=false; v0.18.0+) - type: boolean - paused: - description: Pauses _future_ reconciliation; does _not_ affect - currently running reconciliation (optional; default=false) - type: boolean - serviceAccountName: - description: Specifies that app should be deployed authenticated - via given service account, found in this namespace (optional; - v0.6.0+) - type: string - syncPeriod: - description: Specifies the length of time to wait, in time - + unit format, before reconciling. Always >= 30s. If value - below 30s is specified, 30s will be used. (optional; v0.9.0+; - default=30s) - type: string - template: - items: - properties: - cue: - properties: - inputExpression: - description: Cue expression for single path component, - can be used to unify ValuesFrom into a given field - (optional) - type: string - outputExpression: - description: Cue expression to output, default will - export all visible fields (optional) - type: string - paths: - description: Explicit list of files/directories - (optional) - items: - type: string - type: array - valuesFrom: - description: Provide values (optional) - items: - properties: - configMapRef: - properties: - name: - type: string - type: object - downwardAPI: - properties: - items: - items: - properties: - fieldPath: - description: 'Required: Selects - a field of the app: only annotations, - labels, uid, name and namespace - are supported.' - type: string - kappControllerVersion: - description: 'Optional: Get running - KappController version, defaults - (empty) to retrieving the current - running version.. Can be manually - supplied instead.' - properties: - version: - type: string - type: object - kubernetesAPIs: - description: 'Optional: Get running - KubernetesAPIs from cluster, defaults - (empty) to retrieving the APIs - from the cluster. Can be manually - supplied instead, e.g ["group/version", - "group2/version2"]' - properties: - groupVersions: - items: - type: string - type: array - type: object - kubernetesVersion: - description: 'Optional: Get running - Kubernetes version from cluster, - defaults (empty) to retrieving - the version from the cluster. - Can be manually supplied instead.' - properties: - version: - type: string - type: object - name: - type: string - type: object - type: array - type: object - path: - type: string - secretRef: - properties: - name: - type: string - type: object - type: object - type: array - type: object - helmTemplate: - description: Use helm template command to render helm - chart - properties: - kubernetesAPIs: - description: 'Optional: Use kubernetes group/versions - resources available in the live cluster' - properties: - groupVersions: - items: - type: string - type: array - type: object - kubernetesVersion: - description: 'Optional: Get Kubernetes version, - defaults (empty) to retrieving the version from - the cluster. Can be manually overridden to a value - instead.' - properties: - version: - type: string - type: object - name: - description: Set name explicitly, default is App - CR's name (optional; v0.13.0+) - type: string - namespace: - description: Set namespace explicitly, default is - App CR's namespace (optional; v0.13.0+) - type: string - path: - description: Path to chart (optional; v0.13.0+) - type: string - valuesFrom: - description: One or more secrets, config maps, paths - that provide values (optional) - items: - properties: - configMapRef: - properties: - name: - type: string - type: object - downwardAPI: - properties: - items: - items: - properties: - fieldPath: - description: 'Required: Selects - a field of the app: only annotations, - labels, uid, name and namespace - are supported.' - type: string - kappControllerVersion: - description: 'Optional: Get running - KappController version, defaults - (empty) to retrieving the current - running version.. Can be manually - supplied instead.' - properties: - version: - type: string - type: object - kubernetesAPIs: - description: 'Optional: Get running - KubernetesAPIs from cluster, defaults - (empty) to retrieving the APIs - from the cluster. Can be manually - supplied instead, e.g ["group/version", - "group2/version2"]' - properties: - groupVersions: - items: - type: string - type: array - type: object - kubernetesVersion: - description: 'Optional: Get running - Kubernetes version from cluster, - defaults (empty) to retrieving - the version from the cluster. - Can be manually supplied instead.' - properties: - version: - type: string - type: object - name: - type: string - type: object - type: array - type: object - path: - type: string - secretRef: - properties: - name: - type: string - type: object - type: object - type: array - type: object - jsonnet: - description: TODO implement jsonnet - type: object - kbld: - description: Use kbld to resolve image references to - use digests - properties: - paths: - items: - type: string - type: array - type: object - kustomize: - description: TODO implement kustomize - type: object - sops: - description: Use sops to decrypt *.sops.yml files (optional; - v0.11.0+) - properties: - age: - properties: - privateKeysSecretRef: - description: Secret with private armored PGP - private keys (required) - properties: - name: - type: string - type: object - type: object - paths: - description: Lists paths to decrypt explicitly (optional; - v0.13.0+) - items: - type: string - type: array - pgp: - description: Use PGP to decrypt files (required) - properties: - privateKeysSecretRef: - description: Secret with private armored PGP - private keys (required) - properties: - name: - type: string - type: object - type: object - type: object - ytt: - description: Use ytt to template configuration - properties: - fileMarks: - description: Control metadata about input files - passed to ytt (optional; v0.18.0+) see https://carvel.dev/ytt/docs/latest/file-marks/ - for more details - items: - type: string - type: array - ignoreUnknownComments: - description: Ignores comments that ytt doesn't recognize - (optional; default=false) - type: boolean - inline: - description: Specify additional files, including - data values (optional) - properties: - paths: - additionalProperties: - type: string - description: Specifies mapping of paths to their - content; not recommended for sensitive values - as CR is not encrypted (optional) - type: object - pathsFrom: - description: Specifies content via secrets and - config maps; data values are recommended to - be placed in secrets (optional) - items: - properties: - configMapRef: - properties: - directoryPath: - description: Specifies where to place - files found in secret (optional) - type: string - name: - type: string - type: object - secretRef: - properties: - directoryPath: - description: Specifies where to place - files found in secret (optional) - type: string - name: - type: string - type: object - type: object - type: array - type: object - paths: - description: Lists paths to provide to ytt explicitly - (optional) - items: - type: string - type: array - strict: - description: Forces strict mode https://github.com/k14s/ytt/blob/develop/docs/strict.md - (optional; default=false) - type: boolean - valuesFrom: - description: Provide values via ytt's --data-values-file - (optional; v0.19.0-alpha.9) - items: - properties: - configMapRef: - properties: - name: - type: string - type: object - downwardAPI: - properties: - items: - items: - properties: - fieldPath: - description: 'Required: Selects - a field of the app: only annotations, - labels, uid, name and namespace - are supported.' - type: string - kappControllerVersion: - description: 'Optional: Get running - KappController version, defaults - (empty) to retrieving the current - running version.. Can be manually - supplied instead.' - properties: - version: - type: string - type: object - kubernetesAPIs: - description: 'Optional: Get running - KubernetesAPIs from cluster, defaults - (empty) to retrieving the APIs - from the cluster. Can be manually - supplied instead, e.g ["group/version", - "group2/version2"]' - properties: - groupVersions: - items: - type: string - type: array - type: object - kubernetesVersion: - description: 'Optional: Get running - Kubernetes version from cluster, - defaults (empty) to retrieving - the version from the cluster. - Can be manually supplied instead.' - properties: - version: - type: string - type: object - name: - type: string - type: object - type: array - type: object - path: - type: string - secretRef: - properties: - name: - type: string - type: object - type: object - type: array - type: object - type: object - type: array - type: object - required: - - spec - type: object - valuesSchema: - description: valuesSchema can be used to show template values that - can be configured by users when a Package is installed in an OpenAPI - schema format. - properties: - openAPIv3: - nullable: true - type: object - x-kubernetes-preserve-unknown-fields: true - type: object - version: - description: Package version; Referenced by PackageInstall; Must be - valid semver (required) Cannot be empty - type: string - type: object - required: - - spec - type: object - served: true - storage: true - subresources: - status: {} ---- -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - name: apps.kappctrl.k14s.io -spec: - group: kappctrl.k14s.io - names: - categories: - - carvel - kind: App - listKind: AppList - plural: apps - singular: app - scope: Namespaced - versions: - - additionalPrinterColumns: - - description: Friendly description - jsonPath: .status.friendlyDescription - name: Description - type: string - - description: Last time app started being deployed. Does not mean anything was - changed. - jsonPath: .status.deploy.startedAt - name: Since-Deploy - type: date - - description: Time since creation - jsonPath: .metadata.creationTimestamp - name: Age - type: date - name: v1alpha1 - schema: - openAPIV3Schema: - description: 'An App is a set of Kubernetes resources. These resources could - span any number of namespaces or could be cluster-wide (e.g. CRDs). An App - is represented in kapp-controller using a App CR. The App CR comprises of - three main sections: spec.fetch – declare source for fetching configuration - and OCI images spec.template – declare templating tool and values spec.deploy - – declare deployment tool and any deploy specific configuration' - properties: - apiVersion: - description: 'APIVersion defines the versioned schema of this representation - of an object. Servers should convert recognized schemas to the latest - internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' - type: string - kind: - description: 'Kind is a string value representing the REST resource this - object represents. Servers may infer this from the endpoint the client - submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' - type: string - metadata: - type: object - spec: - properties: - canceled: - description: Cancels current and future reconciliations (optional; - default=false) - type: boolean - cluster: - description: Specifies that app should be deployed to destination - cluster; by default, cluster is same as where this resource resides - (optional; v0.5.0+) - properties: - kubeconfigSecretRef: - description: Specifies secret containing kubeconfig (required) - properties: - key: - description: Specifies key that contains kubeconfig (optional) - type: string - name: - description: Specifies secret name within app's namespace - (required) - type: string - type: object - namespace: - description: Specifies namespace in destination cluster (optional) - type: string - type: object - defaultNamespace: - description: Specifies the default namespace to install the App resources, - by default this is same as the App's namespace (optional; v0.48.0+) - type: string - deploy: - items: - properties: - kapp: - description: Use kapp to deploy resources - properties: - delete: - description: Configuration for delete command (optional) - properties: - rawOptions: - description: Pass through options to kapp delete (optional) - items: - type: string - type: array - type: object - inspect: - description: 'Configuration for inspect command (optional) - as of kapp-controller v0.31.0, inspect is disabled by - default add rawOptions or use an empty inspect config - like `inspect: {}` to enable' - properties: - rawOptions: - description: Pass through options to kapp inspect (optional) - items: - type: string - type: array - type: object - intoNs: - description: Override namespace for all resources (optional) - type: string - mapNs: - description: Provide custom namespace override mapping (optional) - items: - type: string - type: array - rawOptions: - description: Pass through options to kapp deploy (optional) - items: - type: string - type: array - type: object - type: object - type: array - fetch: - items: - properties: - git: - description: Uses git to clone repository - properties: - depth: - description: depth of commits to fetch; 1 (default) means - only latest commit, 0 means everything (optional) - format: int64 - type: integer - forceHTTPBasicAuth: - description: Force the usage of HTTP Basic Auth when Basic - Auth is provided (optional) - type: boolean - lfsSkipSmudge: - description: Skip lfs download (optional) - type: boolean - ref: - description: Branch, tag, commit; origin is the name of - the remote (optional) - type: string - refSelection: - description: Specifies a strategy to resolve to an explicit - ref (optional; v0.24.0+) - properties: - semver: - properties: - constraints: - type: string - prereleases: - properties: - identifiers: - items: - type: string - type: array - type: object - type: object - type: object - secretRef: - description: 'Secret with auth details. allowed keys: ssh-privatekey, - ssh-knownhosts, username, password (optional) (if ssh-knownhosts - is not specified, git will not perform strict host checking)' - properties: - name: - description: Object is expected to be within same namespace - type: string - type: object - subPath: - description: Grab only portion of repository (optional) - type: string - url: - description: http or ssh urls are supported (required) - type: string - type: object - helmChart: - description: Uses helm fetch to fetch specified chart - properties: - name: - description: 'Example: stable/redis' - type: string - repository: - properties: - secretRef: - properties: - name: - description: Object is expected to be within same - namespace - type: string - type: object - url: - description: Repository url; scheme of oci:// will fetch - experimental helm oci chart (v0.19.0+) (required) - type: string - type: object - version: - type: string - type: object - http: - description: Uses http library to fetch file - properties: - secretRef: - description: 'Secret to provide auth details (optional) - Secret may include one or more keys: username, password' - properties: - name: - description: Object is expected to be within same namespace - type: string - type: object - sha256: - description: Checksum to verify after download (optional) - type: string - subPath: - description: Grab only portion of download (optional) - type: string - url: - description: 'URL can point to one of following formats: - text, tgz, zip http and https url are supported; plain - file, tgz and tar types are supported (required)' - type: string - type: object - image: - description: Pulls content from Docker/OCI registry - properties: - secretRef: - description: 'Secret may include one or more keys: username, - password, token. By default anonymous access is used for - authentication.' - properties: - name: - description: Object is expected to be within same namespace - type: string - type: object - subPath: - description: Grab only portion of image (optional) - type: string - tagSelection: - description: Specifies a strategy to choose a tag (optional; - v0.24.0+) if specified, do not include a tag in url key - properties: - semver: - properties: - constraints: - type: string - prereleases: - properties: - identifiers: - items: - type: string - type: array - type: object - type: object - type: object - url: - description: 'Docker image url; unqualified, tagged, or - digest references supported (required) Example: username/app1-config:v0.1.0' - type: string - type: object - imgpkgBundle: - description: Pulls imgpkg bundle from Docker/OCI registry (v0.17.0+) - properties: - image: - description: Docker image url; unqualified, tagged, or digest - references supported (required) - type: string - secretRef: - description: 'Secret may include one or more keys: username, - password, token. By default anonymous access is used for - authentication.' - properties: - name: - description: Object is expected to be within same namespace - type: string - type: object - tagSelection: - description: Specifies a strategy to choose a tag (optional; - v0.24.0+) if specified, do not include a tag in url key - properties: - semver: - properties: - constraints: - type: string - prereleases: - properties: - identifiers: - items: - type: string - type: array - type: object - type: object - type: object - type: object - inline: - description: Pulls content from within this resource; or other - resources in the cluster - properties: - paths: - additionalProperties: - type: string - description: Specifies mapping of paths to their content; - not recommended for sensitive values as CR is not encrypted - (optional) - type: object - pathsFrom: - description: Specifies content via secrets and config maps; - data values are recommended to be placed in secrets (optional) - items: - properties: - configMapRef: - properties: - directoryPath: - description: Specifies where to place files found - in secret (optional) - type: string - name: - type: string - type: object - secretRef: - properties: - directoryPath: - description: Specifies where to place files found - in secret (optional) - type: string - name: - type: string - type: object - type: object - type: array - type: object - path: - description: Relative path to place the fetched artifacts - type: string - type: object - type: array - noopDelete: - description: Deletion requests for the App will result in the App - CR being deleted, but its associated resources will not be deleted - (optional; default=false; v0.18.0+) - type: boolean - paused: - description: Pauses _future_ reconciliation; does _not_ affect currently - running reconciliation (optional; default=false) - type: boolean - serviceAccountName: - description: Specifies that app should be deployed authenticated via - given service account, found in this namespace (optional; v0.6.0+) - type: string - syncPeriod: - description: Specifies the length of time to wait, in time + unit - format, before reconciling. Always >= 30s. If value below 30s is - specified, 30s will be used. (optional; v0.9.0+; default=30s) - type: string - template: - items: - properties: - cue: - properties: - inputExpression: - description: Cue expression for single path component, can - be used to unify ValuesFrom into a given field (optional) - type: string - outputExpression: - description: Cue expression to output, default will export - all visible fields (optional) - type: string - paths: - description: Explicit list of files/directories (optional) - items: - type: string - type: array - valuesFrom: - description: Provide values (optional) - items: - properties: - configMapRef: - properties: - name: - type: string - type: object - downwardAPI: - properties: - items: - items: - properties: - fieldPath: - description: 'Required: Selects a field - of the app: only annotations, labels, - uid, name and namespace are supported.' - type: string - kappControllerVersion: - description: 'Optional: Get running KappController - version, defaults (empty) to retrieving - the current running version.. Can be manually - supplied instead.' - properties: - version: - type: string - type: object - kubernetesAPIs: - description: 'Optional: Get running KubernetesAPIs - from cluster, defaults (empty) to retrieving - the APIs from the cluster. Can be manually - supplied instead, e.g ["group/version", - "group2/version2"]' - properties: - groupVersions: - items: - type: string - type: array - type: object - kubernetesVersion: - description: 'Optional: Get running Kubernetes - version from cluster, defaults (empty) - to retrieving the version from the cluster. - Can be manually supplied instead.' - properties: - version: - type: string - type: object - name: - type: string - type: object - type: array - type: object - path: - type: string - secretRef: - properties: - name: - type: string - type: object - type: object - type: array - type: object - helmTemplate: - description: Use helm template command to render helm chart - properties: - kubernetesAPIs: - description: 'Optional: Use kubernetes group/versions resources - available in the live cluster' - properties: - groupVersions: - items: - type: string - type: array - type: object - kubernetesVersion: - description: 'Optional: Get Kubernetes version, defaults - (empty) to retrieving the version from the cluster. Can - be manually overridden to a value instead.' - properties: - version: - type: string - type: object - name: - description: Set name explicitly, default is App CR's name - (optional; v0.13.0+) - type: string - namespace: - description: Set namespace explicitly, default is App CR's - namespace (optional; v0.13.0+) - type: string - path: - description: Path to chart (optional; v0.13.0+) - type: string - valuesFrom: - description: One or more secrets, config maps, paths that - provide values (optional) - items: - properties: - configMapRef: - properties: - name: - type: string - type: object - downwardAPI: - properties: - items: - items: - properties: - fieldPath: - description: 'Required: Selects a field - of the app: only annotations, labels, - uid, name and namespace are supported.' - type: string - kappControllerVersion: - description: 'Optional: Get running KappController - version, defaults (empty) to retrieving - the current running version.. Can be manually - supplied instead.' - properties: - version: - type: string - type: object - kubernetesAPIs: - description: 'Optional: Get running KubernetesAPIs - from cluster, defaults (empty) to retrieving - the APIs from the cluster. Can be manually - supplied instead, e.g ["group/version", - "group2/version2"]' - properties: - groupVersions: - items: - type: string - type: array - type: object - kubernetesVersion: - description: 'Optional: Get running Kubernetes - version from cluster, defaults (empty) - to retrieving the version from the cluster. - Can be manually supplied instead.' - properties: - version: - type: string - type: object - name: - type: string - type: object - type: array - type: object - path: - type: string - secretRef: - properties: - name: - type: string - type: object - type: object - type: array - type: object - jsonnet: - description: TODO implement jsonnet - type: object - kbld: - description: Use kbld to resolve image references to use digests - properties: - paths: - items: - type: string - type: array - type: object - kustomize: - description: TODO implement kustomize - type: object - sops: - description: Use sops to decrypt *.sops.yml files (optional; - v0.11.0+) - properties: - age: - properties: - privateKeysSecretRef: - description: Secret with private armored PGP private - keys (required) - properties: - name: - type: string - type: object - type: object - paths: - description: Lists paths to decrypt explicitly (optional; - v0.13.0+) - items: - type: string - type: array - pgp: - description: Use PGP to decrypt files (required) - properties: - privateKeysSecretRef: - description: Secret with private armored PGP private - keys (required) - properties: - name: - type: string - type: object - type: object - type: object - ytt: - description: Use ytt to template configuration - properties: - fileMarks: - description: Control metadata about input files passed to - ytt (optional; v0.18.0+) see https://carvel.dev/ytt/docs/latest/file-marks/ - for more details - items: - type: string - type: array - ignoreUnknownComments: - description: Ignores comments that ytt doesn't recognize - (optional; default=false) - type: boolean - inline: - description: Specify additional files, including data values - (optional) - properties: - paths: - additionalProperties: - type: string - description: Specifies mapping of paths to their content; - not recommended for sensitive values as CR is not - encrypted (optional) - type: object - pathsFrom: - description: Specifies content via secrets and config - maps; data values are recommended to be placed in - secrets (optional) - items: - properties: - configMapRef: - properties: - directoryPath: - description: Specifies where to place files - found in secret (optional) - type: string - name: - type: string - type: object - secretRef: - properties: - directoryPath: - description: Specifies where to place files - found in secret (optional) - type: string - name: - type: string - type: object - type: object - type: array - type: object - paths: - description: Lists paths to provide to ytt explicitly (optional) - items: - type: string - type: array - strict: - description: Forces strict mode https://github.com/k14s/ytt/blob/develop/docs/strict.md - (optional; default=false) - type: boolean - valuesFrom: - description: Provide values via ytt's --data-values-file - (optional; v0.19.0-alpha.9) - items: - properties: - configMapRef: - properties: - name: - type: string - type: object - downwardAPI: - properties: - items: - items: - properties: - fieldPath: - description: 'Required: Selects a field - of the app: only annotations, labels, - uid, name and namespace are supported.' - type: string - kappControllerVersion: - description: 'Optional: Get running KappController - version, defaults (empty) to retrieving - the current running version.. Can be manually - supplied instead.' - properties: - version: - type: string - type: object - kubernetesAPIs: - description: 'Optional: Get running KubernetesAPIs - from cluster, defaults (empty) to retrieving - the APIs from the cluster. Can be manually - supplied instead, e.g ["group/version", - "group2/version2"]' - properties: - groupVersions: - items: - type: string - type: array - type: object - kubernetesVersion: - description: 'Optional: Get running Kubernetes - version from cluster, defaults (empty) - to retrieving the version from the cluster. - Can be manually supplied instead.' - properties: - version: - type: string - type: object - name: - type: string - type: object - type: array - type: object - path: - type: string - secretRef: - properties: - name: - type: string - type: object - type: object - type: array - type: object - type: object - type: array - type: object - status: - properties: - conditions: - items: - properties: - message: - description: Human-readable message indicating details about - last transition. - type: string - reason: - description: Unique, this should be a short, machine understandable - string that gives the reason for condition's last transition. - If it reports "ResizeStarted" that means the underlying persistent - volume is being resized. - type: string - status: - type: string - type: - description: ConditionType represents reconciler state - type: string - required: - - status - - type - type: object - type: array - consecutiveReconcileFailures: - type: integer - consecutiveReconcileSuccesses: - type: integer - deploy: - properties: - error: - type: string - exitCode: - type: integer - finished: - type: boolean - kapp: - description: KappDeployStatus contains the associated AppCR deployed - resources - properties: - associatedResources: - description: AssociatedResources contains the associated App - label, namespaces and GKs - properties: - groupKinds: - items: - description: GroupKind specifies a Group and a Kind, - but does not force a version. This is useful for - identifying concepts during lookup stages without - having partially valid types - properties: - group: - type: string - kind: - type: string - required: - - group - - kind - type: object - type: array - label: - type: string - namespaces: - items: - type: string - type: array - type: object - type: object - startedAt: - format: date-time - type: string - stderr: - type: string - stdout: - type: string - updatedAt: - format: date-time - type: string - type: object - fetch: - properties: - error: - type: string - exitCode: - type: integer - startedAt: - format: date-time - type: string - stderr: - type: string - stdout: - type: string - updatedAt: - format: date-time - type: string - type: object - friendlyDescription: - type: string - inspect: - properties: - error: - type: string - exitCode: - type: integer - stderr: - type: string - stdout: - type: string - updatedAt: - format: date-time - type: string - type: object - managedAppName: - type: string - observedGeneration: - description: Populated based on metadata.generation when controller - observes a change to the resource; if this value is out of data, - other status fields do not reflect latest state - format: int64 - type: integer - template: - properties: - error: - type: string - exitCode: - type: integer - stderr: - type: string - updatedAt: - format: date-time - type: string - type: object - usefulErrorMessage: - type: string - type: object - required: - - spec - type: object - served: true - storage: true - subresources: - status: {} ---- -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - name: packageinstalls.packaging.carvel.dev -spec: - group: packaging.carvel.dev - names: - categories: - - carvel - kind: PackageInstall - listKind: PackageInstallList - plural: packageinstalls - shortNames: - - pkgi - singular: packageinstall - scope: Namespaced - versions: - - additionalPrinterColumns: - - description: PackageMetadata name - jsonPath: .spec.packageRef.refName - name: Package name - type: string - - description: PackageMetadata version - jsonPath: .status.version - name: Package version - type: string - - description: Friendly description - jsonPath: .status.friendlyDescription - name: Description - type: string - - description: Time since creation - jsonPath: .metadata.creationTimestamp - name: Age - type: date - name: v1alpha1 - schema: - openAPIV3Schema: - description: A Package Install is an actual installation of a package and - its underlying resources on a Kubernetes cluster. It is represented in kapp-controller - by a PackageInstall CR. A PackageInstall CR must reference a Package CR. - properties: - apiVersion: - description: 'APIVersion defines the versioned schema of this representation - of an object. Servers should convert recognized schemas to the latest - internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' - type: string - kind: - description: 'Kind is a string value representing the REST resource this - object represents. Servers may infer this from the endpoint the client - submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' - type: string - metadata: - type: object - spec: - properties: - canceled: - description: Canceled when set to true will stop all active changes - type: boolean - cluster: - description: Specifies that Package should be deployed to destination - cluster; by default, cluster is same as where this resource resides - (optional) - properties: - kubeconfigSecretRef: - description: Specifies secret containing kubeconfig (required) - properties: - key: - description: Specifies key that contains kubeconfig (optional) - type: string - name: - description: Specifies secret name within app's namespace - (required) - type: string - type: object - namespace: - description: Specifies namespace in destination cluster (optional) - type: string - type: object - defaultNamespace: - description: Specifies the default namespace to install the Package - resources, by default this is same as the PackageInstall namespace - (optional; v0.48.0+) - type: string - noopDelete: - description: When NoopDelete set to true, PackageInstall deletion - should delete PackageInstall/App CR but preserve App's associated - resources. - type: boolean - packageRef: - description: Specifies the name of the package to install (required) - properties: - refName: - type: string - versionSelection: - properties: - constraints: - type: string - prereleases: - properties: - identifiers: - items: - type: string - type: array - type: object - type: object - type: object - paused: - description: Paused when set to true will ignore all pending changes, - once it set back to false, pending changes will be applied - type: boolean - serviceAccountName: - description: Specifies service account that will be used to install - underlying package contents - type: string - syncPeriod: - description: Controls frequency of App reconciliation in time + unit - format. Always >= 30s. If value below 30s is specified, 30s will - be used. - type: string - values: - description: Values to be included in package's templating step (currently - only included in the first templating step) (optional) - items: - properties: - secretRef: - properties: - key: - type: string - name: - type: string - type: object - type: object - type: array - type: object - status: - properties: - conditions: - items: - properties: - message: - description: Human-readable message indicating details about - last transition. - type: string - reason: - description: Unique, this should be a short, machine understandable - string that gives the reason for condition's last transition. - If it reports "ResizeStarted" that means the underlying persistent - volume is being resized. - type: string - status: - type: string - type: - description: ConditionType represents reconciler state - type: string - required: - - status - - type - type: object - type: array - friendlyDescription: - type: string - lastAttemptedVersion: - description: LastAttemptedVersion specifies what version was last - attempted to be installed. It does _not_ indicate it was successfully - installed. - type: string - observedGeneration: - description: Populated based on metadata.generation when controller - observes a change to the resource; if this value is out of data, - other status fields do not reflect latest state - format: int64 - type: integer - usefulErrorMessage: - type: string - version: - description: TODO this is desired resolved version (not actually deployed) - type: string - type: object - required: - - spec - type: object - served: true - storage: true - subresources: - status: {} ---- -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - packaging.carvel.dev/global-namespace: kapp-controller-packaging-global - name: packagerepositories.packaging.carvel.dev -spec: - group: packaging.carvel.dev - names: - categories: - - carvel - kind: PackageRepository - listKind: PackageRepositoryList - plural: packagerepositories - shortNames: - - pkgr - singular: packagerepository - scope: Namespaced - versions: - - additionalPrinterColumns: - - description: Time since creation - jsonPath: .metadata.creationTimestamp - name: Age - type: date - - description: Friendly description - jsonPath: .status.friendlyDescription - name: Description - type: string - name: v1alpha1 - schema: - openAPIV3Schema: - description: A package repository is a collection of packages and their metadata. - Similar to a maven repository or a rpm repository, adding a package repository - to a cluster gives users of that cluster the ability to install any of the - packages from that repository. - properties: - apiVersion: - description: 'APIVersion defines the versioned schema of this representation - of an object. Servers should convert recognized schemas to the latest - internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' - type: string - kind: - description: 'Kind is a string value representing the REST resource this - object represents. Servers may infer this from the endpoint the client - submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' - type: string - metadata: - type: object - spec: - properties: - fetch: - properties: - git: - description: Uses git to clone repository containing package list - properties: - depth: - description: depth of commits to fetch; 1 (default) means - only latest commit, 0 means everything (optional) - format: int64 - type: integer - forceHTTPBasicAuth: - description: Force the usage of HTTP Basic Auth when Basic - Auth is provided (optional) - type: boolean - lfsSkipSmudge: - description: Skip lfs download (optional) - type: boolean - ref: - description: Branch, tag, commit; origin is the name of the - remote (optional) - type: string - refSelection: - description: Specifies a strategy to resolve to an explicit - ref (optional; v0.24.0+) - properties: - semver: - properties: - constraints: - type: string - prereleases: - properties: - identifiers: - items: - type: string - type: array - type: object - type: object - type: object - secretRef: - description: 'Secret with auth details. allowed keys: ssh-privatekey, - ssh-knownhosts, username, password (optional) (if ssh-knownhosts - is not specified, git will not perform strict host checking)' - properties: - name: - description: Object is expected to be within same namespace - type: string - type: object - subPath: - description: Grab only portion of repository (optional) - type: string - url: - description: http or ssh urls are supported (required) - type: string - type: object - http: - description: Uses http library to fetch file containing packages - properties: - secretRef: - description: 'Secret to provide auth details (optional) Secret - may include one or more keys: username, password' - properties: - name: - description: Object is expected to be within same namespace - type: string - type: object - sha256: - description: Checksum to verify after download (optional) - type: string - subPath: - description: Grab only portion of download (optional) - type: string - url: - description: 'URL can point to one of following formats: text, - tgz, zip http and https url are supported; plain file, tgz - and tar types are supported (required)' - type: string - type: object - image: - description: Image url; unqualified, tagged, or digest references - supported (required) - properties: - secretRef: - description: 'Secret may include one or more keys: username, - password, token. By default anonymous access is used for - authentication.' - properties: - name: - description: Object is expected to be within same namespace - type: string - type: object - subPath: - description: Grab only portion of image (optional) - type: string - tagSelection: - description: Specifies a strategy to choose a tag (optional; - v0.24.0+) if specified, do not include a tag in url key - properties: - semver: - properties: - constraints: - type: string - prereleases: - properties: - identifiers: - items: - type: string - type: array - type: object - type: object - type: object - url: - description: 'Docker image url; unqualified, tagged, or digest - references supported (required) Example: username/app1-config:v0.1.0' - type: string - type: object - imgpkgBundle: - description: Pulls imgpkg bundle from Docker/OCI registry - properties: - image: - description: Docker image url; unqualified, tagged, or digest - references supported (required) - type: string - secretRef: - description: 'Secret may include one or more keys: username, - password, token. By default anonymous access is used for - authentication.' - properties: - name: - description: Object is expected to be within same namespace - type: string - type: object - tagSelection: - description: Specifies a strategy to choose a tag (optional; - v0.24.0+) if specified, do not include a tag in url key - properties: - semver: - properties: - constraints: - type: string - prereleases: - properties: - identifiers: - items: - type: string - type: array - type: object - type: object - type: object - type: object - inline: - description: Pull content from within this resource; or other - resources in the cluster - properties: - paths: - additionalProperties: - type: string - description: Specifies mapping of paths to their content; - not recommended for sensitive values as CR is not encrypted - (optional) - type: object - pathsFrom: - description: Specifies content via secrets and config maps; - data values are recommended to be placed in secrets (optional) - items: - properties: - configMapRef: - properties: - directoryPath: - description: Specifies where to place files found - in secret (optional) - type: string - name: - type: string - type: object - secretRef: - properties: - directoryPath: - description: Specifies where to place files found - in secret (optional) - type: string - name: - type: string - type: object - type: object - type: array - type: object - type: object - paused: - description: Paused when set to true will ignore all pending changes, - once it set back to false, pending changes will be applied - type: boolean - syncPeriod: - description: Controls frequency of PackageRepository reconciliation - type: string - required: - - fetch - type: object - status: - properties: - conditions: - items: - properties: - message: - description: Human-readable message indicating details about - last transition. - type: string - reason: - description: Unique, this should be a short, machine understandable - string that gives the reason for condition's last transition. - If it reports "ResizeStarted" that means the underlying persistent - volume is being resized. - type: string - status: - type: string - type: - description: ConditionType represents reconciler state - type: string - required: - - status - - type - type: object - type: array - consecutiveReconcileFailures: - type: integer - consecutiveReconcileSuccesses: - type: integer - deploy: - properties: - error: - type: string - exitCode: - type: integer - finished: - type: boolean - kapp: - description: KappDeployStatus contains the associated AppCR deployed - resources - properties: - associatedResources: - description: AssociatedResources contains the associated App - label, namespaces and GKs - properties: - groupKinds: - items: - description: GroupKind specifies a Group and a Kind, - but does not force a version. This is useful for - identifying concepts during lookup stages without - having partially valid types - properties: - group: - type: string - kind: - type: string - required: - - group - - kind - type: object - type: array - label: - type: string - namespaces: - items: - type: string - type: array - type: object - type: object - startedAt: - format: date-time - type: string - stderr: - type: string - stdout: - type: string - updatedAt: - format: date-time - type: string - type: object - fetch: - properties: - error: - type: string - exitCode: - type: integer - startedAt: - format: date-time - type: string - stderr: - type: string - stdout: - type: string - updatedAt: - format: date-time - type: string - type: object - friendlyDescription: - type: string - observedGeneration: - description: Populated based on metadata.generation when controller - observes a change to the resource; if this value is out of data, - other status fields do not reflect latest state - format: int64 - type: integer - template: - properties: - error: - type: string - exitCode: - type: integer - stderr: - type: string - updatedAt: - format: date-time - type: string - type: object - usefulErrorMessage: - type: string - type: object - required: - - spec - type: object - served: true - storage: true - subresources: - status: {} ---- -apiVersion: apps/v1 -kind: Deployment -metadata: - annotations: - kapp-controller.carvel.dev/version: v0.55.1 - kbld.k14s.io/images: | - - origins: - - local: - path: /home/runner/work/kapp-controller/kapp-controller - - git: - dirty: true - remoteURL: https://github.com/carvel-dev/kapp-controller - sha: dd15f4ff05bc0d3a17ab739b3b86d84a1ae5d024 - tags: - - v0.55.1 - url: ghcr.io/carvel-dev/kapp-controller@sha256:cf250cb1d03ba0f391fa35a9424ace7327a07bd69b41c94d62e69c58d143566e - name: kapp-controller - namespace: kapp-controller -spec: - replicas: 1 - revisionHistoryLimit: 0 - selector: - matchLabels: - app: kapp-controller - template: - metadata: - labels: - app: kapp-controller - spec: - containers: - - args: - - -packaging-global-namespace=kapp-controller-packaging-global - - -enable-api-priority-and-fairness=True - - -tls-cipher-suites= - env: - - name: KAPPCTRL_MEM_TMP_DIR - value: /etc/kappctrl-mem-tmp - - name: KAPPCTRL_SIDECAREXEC_SOCK - value: /etc/kappctrl-mem-tmp/sidecarexec.sock - - name: KAPPCTRL_SYSTEM_NAMESPACE - valueFrom: - fieldRef: - fieldPath: metadata.namespace - - name: KAPPCTRL_API_PORT - value: "8443" - image: ghcr.io/carvel-dev/kapp-controller@sha256:cf250cb1d03ba0f391fa35a9424ace7327a07bd69b41c94d62e69c58d143566e - name: kapp-controller - ports: - - containerPort: 8443 - name: api - protocol: TCP - - containerPort: 8080 - name: metrics - protocol: TCP - resources: - requests: - cpu: 120m - memory: 100Mi - securityContext: - allowPrivilegeEscalation: false - capabilities: - drop: - - ALL - readOnlyRootFilesystem: true - runAsNonRoot: true - seccompProfile: - type: RuntimeDefault - volumeMounts: - - mountPath: /etc/kappctrl-mem-tmp - name: template-fs - - mountPath: /home/kapp-controller - name: home - - args: - - --sidecarexec - env: - - name: KAPPCTRL_SIDECAREXEC_SOCK - value: /etc/kappctrl-mem-tmp/sidecarexec.sock - - name: IMGPKG_ACTIVE_KEYCHAINS - value: gke,aks,ecr - image: ghcr.io/carvel-dev/kapp-controller@sha256:cf250cb1d03ba0f391fa35a9424ace7327a07bd69b41c94d62e69c58d143566e - name: kapp-controller-sidecarexec - resources: - requests: - cpu: 120m - memory: 100Mi - securityContext: - allowPrivilegeEscalation: false - capabilities: - drop: - - ALL - readOnlyRootFilesystem: false - runAsNonRoot: true - seccompProfile: - type: RuntimeDefault - volumeMounts: - - mountPath: /etc/kappctrl-mem-tmp - name: template-fs - - mountPath: /home/kapp-controller - name: home - - mountPath: /var/run/secrets/kubernetes.io/serviceaccount - name: empty-sa - serviceAccount: kapp-controller-sa - volumes: - - emptyDir: - medium: Memory - name: template-fs - - emptyDir: - medium: Memory - name: home - - emptyDir: {} - name: empty-sa ---- -apiVersion: v1 -kind: ServiceAccount -metadata: - name: kapp-controller-sa - namespace: kapp-controller ---- -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - name: kapp-controller-cluster-role -rules: -- apiGroups: - - "" - resources: - - secrets - verbs: - - create - - get - - list - - watch -- apiGroups: - - "" - resources: - - serviceaccounts - verbs: - - get -- apiGroups: - - "" - resources: - - serviceaccounts/token - verbs: - - create -- apiGroups: - - kappctrl.k14s.io - resources: - - apps - - apps/status - verbs: - - '*' -- apiGroups: - - packaging.carvel.dev - resources: - - packageinstalls - - packageinstalls/status - - packageinstalls/finalizers - verbs: - - '*' -- apiGroups: - - packaging.carvel.dev - resources: - - packagerepositories - - packagerepositories/status - verbs: - - '*' -- apiGroups: - - internal.packaging.carvel.dev - resources: - - internalpackagemetadatas - verbs: - - '*' -- apiGroups: - - data.packaging.carvel.dev - resources: - - packagemetadatas - - packagemetadatas/status - verbs: - - '*' -- apiGroups: - - internal.packaging.carvel.dev - resources: - - internalpackages - verbs: - - '*' -- apiGroups: - - data.packaging.carvel.dev - resources: - - packages - - packages/status - verbs: - - '*' -- apiGroups: - - "" - resources: - - configmaps - verbs: - - '*' -- apiGroups: - - apiregistration.k8s.io - resources: - - apiservices - verbs: - - update - - get -- apiGroups: - - "" - resources: - - namespaces - verbs: - - list - - watch - - get - - update -- apiGroups: - - admissionregistration.k8s.io - resources: - - mutatingwebhookconfigurations - - validatingwebhookconfigurations - - validatingadmissionpolicies - - validatingadmissionpolicybindings - verbs: - - list - - watch -- apiGroups: - - authorization.k8s.io - resources: - - subjectaccessreviews - verbs: - - create -- apiGroups: - - flowcontrol.apiserver.k8s.io - resources: - - prioritylevelconfigurations - - flowschemas - verbs: - - list - - watch ---- -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - name: kapp-controller-user-role -rules: -- apiGroups: - - "" - resources: - - secrets - verbs: - - create - - get - - list - - watch -- apiGroups: - - "" - resources: - - serviceaccounts - verbs: - - get -- apiGroups: - - "" - resources: - - serviceaccounts/token - verbs: - - create -- apiGroups: - - kappctrl.k14s.io - resources: - - apps - - apps/status - verbs: - - '*' -- apiGroups: - - packaging.carvel.dev - resources: - - packageinstalls - - packageinstalls/status - - packageinstalls/finalizers - verbs: - - '*' -- apiGroups: - - "" - resources: - - configmaps - verbs: - - '*' -- apiGroups: - - packaging.carvel.dev - resources: - - packagerepositories - - packagerepositories/status - verbs: - - get - - list - - watch -- apiGroups: - - internal.packaging.carvel.dev - resources: - - internalpackagemetadatas - verbs: - - get - - list - - watch -- apiGroups: - - data.packaging.carvel.dev - resources: - - packagemetadatas - - packagemetadatas/status - verbs: - - get - - list - - watch -- apiGroups: - - internal.packaging.carvel.dev - resources: - - internalpackages - verbs: - - get - - list - - watch -- apiGroups: - - data.packaging.carvel.dev - resources: - - packages - - packages/status - verbs: - - get - - list - - watch ---- -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRoleBinding -metadata: - name: kapp-controller-cluster-role-binding -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: ClusterRole - name: kapp-controller-cluster-role -subjects: -- kind: ServiceAccount - name: kapp-controller-sa - namespace: kapp-controller ---- -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRoleBinding -metadata: - name: pkg-apiserver:system:auth-delegator -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: ClusterRole - name: system:auth-delegator -subjects: -- kind: ServiceAccount - name: kapp-controller-sa - namespace: kapp-controller ---- -apiVersion: rbac.authorization.k8s.io/v1 -kind: RoleBinding -metadata: - name: pkgserver-auth-reader - namespace: kube-system -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: Role - name: extension-apiserver-authentication-reader -subjects: -- kind: ServiceAccount - name: kapp-controller-sa - namespace: kapp-controller diff --git a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/kapp-controller/values-schema.yaml b/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/kapp-controller/values-schema.yaml deleted file mode 100644 index 913cfa07d..000000000 --- a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/kapp-controller/values-schema.yaml +++ /dev/null @@ -1,5 +0,0 @@ -#@data/values-schema ---- -#! No configuration supported. We need to add this to the schema to avoid errors -#@schema/nullable -namespace: "" \ No newline at end of file diff --git a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/kyverno/upstream/install.yaml b/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/kyverno/upstream/install.yaml deleted file mode 100644 index e679d00e3..000000000 --- a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/kyverno/upstream/install.yaml +++ /dev/null @@ -1,59182 +0,0 @@ ---- -apiVersion: v1 -kind: Namespace -metadata: - name: kyverno - labels: - app.kubernetes.io/instance: kyverno - app.kubernetes.io/part-of: kyverno - app.kubernetes.io/version: v1.15.1 ---- -apiVersion: v1 -kind: ServiceAccount -metadata: - name: kyverno-admission-controller - namespace: kyverno - labels: - app.kubernetes.io/component: admission-controller - app.kubernetes.io/instance: kyverno - app.kubernetes.io/part-of: kyverno - app.kubernetes.io/version: v1.15.1 -automountServiceAccountToken: false ---- -apiVersion: v1 -kind: ServiceAccount -metadata: - name: kyverno-background-controller - namespace: kyverno - labels: - app.kubernetes.io/component: background-controller - app.kubernetes.io/instance: kyverno - app.kubernetes.io/part-of: kyverno - app.kubernetes.io/version: v1.15.1 -automountServiceAccountToken: false ---- -apiVersion: v1 -kind: ServiceAccount -metadata: - name: kyverno-cleanup-controller - namespace: kyverno - labels: - app.kubernetes.io/component: cleanup-controller - app.kubernetes.io/instance: kyverno - app.kubernetes.io/part-of: kyverno - app.kubernetes.io/version: v1.15.1 -automountServiceAccountToken: false ---- -apiVersion: v1 -kind: ServiceAccount -metadata: - name: kyverno-reports-controller - namespace: kyverno - labels: - app.kubernetes.io/component: reports-controller - app.kubernetes.io/instance: kyverno - app.kubernetes.io/part-of: kyverno - app.kubernetes.io/version: v1.15.1 -automountServiceAccountToken: false ---- -apiVersion: v1 -kind: ConfigMap -metadata: - name: kyverno - namespace: kyverno - labels: - app.kubernetes.io/component: config - app.kubernetes.io/instance: kyverno - app.kubernetes.io/part-of: kyverno - app.kubernetes.io/version: v1.15.1 - annotations: - helm.sh/resource-policy: "keep" -data: - enableDefaultRegistryMutation: "true" - defaultRegistry: "docker.io" - generateSuccessEvents: "false" - excludeGroups: "system:nodes" - resourceFilters: >- - [*/*,kyverno,*] - [Event,*,*] - [*/*,kube-system,*] - [*/*,kube-public,*] - [*/*,kube-node-lease,*] - [Node,*,*] - [Node/?*,*,*] - [APIService,*,*] - [APIService/?*,*,*] - [TokenReview,*,*] - [SubjectAccessReview,*,*] - [SelfSubjectAccessReview,*,*] - [Binding,*,*] - [Pod/binding,*,*] - [ReplicaSet,*,*] - [ReplicaSet/?*,*,*] - [EphemeralReport,*,*] - [ClusterEphemeralReport,*,*] - [ClusterRole,*,kyverno:admission-controller] - [ClusterRole,*,kyverno:admission-controller:core] - [ClusterRole,*,kyverno:admission-controller:additional] - [ClusterRole,*,kyverno:background-controller] - [ClusterRole,*,kyverno:background-controller:core] - [ClusterRole,*,kyverno:background-controller:additional] - [ClusterRole,*,kyverno:cleanup-controller] - [ClusterRole,*,kyverno:cleanup-controller:core] - [ClusterRole,*,kyverno:cleanup-controller:additional] - [ClusterRole,*,kyverno:reports-controller] - [ClusterRole,*,kyverno:reports-controller:core] - [ClusterRole,*,kyverno:reports-controller:additional] - [ClusterRoleBinding,*,kyverno:admission-controller] - [ClusterRoleBinding,*,kyverno:background-controller] - [ClusterRoleBinding,*,kyverno:cleanup-controller] - [ClusterRoleBinding,*,kyverno:reports-controller] - [ServiceAccount,kyverno,kyverno-admission-controller] - [ServiceAccount/?*,kyverno,kyverno-admission-controller] - [ServiceAccount,kyverno,kyverno-background-controller] - [ServiceAccount/?*,kyverno,kyverno-background-controller] - [ServiceAccount,kyverno,kyverno-cleanup-controller] - [ServiceAccount/?*,kyverno,kyverno-cleanup-controller] - [ServiceAccount,kyverno,kyverno-reports-controller] - [ServiceAccount/?*,kyverno,kyverno-reports-controller] - [Role,kyverno,kyverno:admission-controller] - [Role,kyverno,kyverno:background-controller] - [Role,kyverno,kyverno:cleanup-controller] - [Role,kyverno,kyverno:reports-controller] - [RoleBinding,kyverno,kyverno:admission-controller] - [RoleBinding,kyverno,kyverno:background-controller] - [RoleBinding,kyverno,kyverno:cleanup-controller] - [RoleBinding,kyverno,kyverno:reports-controller] - [ConfigMap,kyverno,kyverno] - [ConfigMap,kyverno,kyverno-metrics] - [Deployment,kyverno,kyverno-admission-controller] - [Deployment/?*,kyverno,kyverno-admission-controller] - [Deployment,kyverno,kyverno-background-controller] - [Deployment/?*,kyverno,kyverno-background-controller] - [Deployment,kyverno,kyverno-cleanup-controller] - [Deployment/?*,kyverno,kyverno-cleanup-controller] - [Deployment,kyverno,kyverno-reports-controller] - [Deployment/?*,kyverno,kyverno-reports-controller] - [Pod,kyverno,kyverno-admission-controller-*] - [Pod/?*,kyverno,kyverno-admission-controller-*] - [Pod,kyverno,kyverno-background-controller-*] - [Pod/?*,kyverno,kyverno-background-controller-*] - [Pod,kyverno,kyverno-cleanup-controller-*] - [Pod/?*,kyverno,kyverno-cleanup-controller-*] - [Pod,kyverno,kyverno-reports-controller-*] - [Pod/?*,kyverno,kyverno-reports-controller-*] - [Job,kyverno,kyverno-hook-pre-delete] - [Job/?*,kyverno,kyverno-hook-pre-delete] - [NetworkPolicy,kyverno,kyverno-admission-controller] - [NetworkPolicy/?*,kyverno,kyverno-admission-controller] - [NetworkPolicy,kyverno,kyverno-background-controller] - [NetworkPolicy/?*,kyverno,kyverno-background-controller] - [NetworkPolicy,kyverno,kyverno-cleanup-controller] - [NetworkPolicy/?*,kyverno,kyverno-cleanup-controller] - [NetworkPolicy,kyverno,kyverno-reports-controller] - [NetworkPolicy/?*,kyverno,kyverno-reports-controller] - [PodDisruptionBudget,kyverno,kyverno-admission-controller] - [PodDisruptionBudget/?*,kyverno,kyverno-admission-controller] - [PodDisruptionBudget,kyverno,kyverno-background-controller] - [PodDisruptionBudget/?*,kyverno,kyverno-background-controller] - [PodDisruptionBudget,kyverno,kyverno-cleanup-controller] - [PodDisruptionBudget/?*,kyverno,kyverno-cleanup-controller] - [PodDisruptionBudget,kyverno,kyverno-reports-controller] - [PodDisruptionBudget/?*,kyverno,kyverno-reports-controller] - [Service,kyverno,kyverno-svc] - [Service/?*,kyverno,kyverno-svc] - [Service,kyverno,kyverno-svc-metrics] - [Service/?*,kyverno,kyverno-svc-metrics] - [Service,kyverno,kyverno-background-controller-metrics] - [Service/?*,kyverno,kyverno-background-controller-metrics] - [Service,kyverno,kyverno-cleanup-controller] - [Service/?*,kyverno,kyverno-cleanup-controller] - [Service,kyverno,kyverno-cleanup-controller-metrics] - [Service/?*,kyverno,kyverno-cleanup-controller-metrics] - [Service,kyverno,kyverno-reports-controller-metrics] - [Service/?*,kyverno,kyverno-reports-controller-metrics] - [ServiceMonitor,kyverno,kyverno-admission-controller] - [ServiceMonitor,kyverno,kyverno-background-controller] - [ServiceMonitor,kyverno,kyverno-cleanup-controller] - [ServiceMonitor,kyverno,kyverno-reports-controller] - [Secret,kyverno,kyverno-svc.kyverno.svc.*] - [Secret,kyverno,kyverno-cleanup-controller.kyverno.svc.*] - updateRequestThreshold: "1000" - webhooks: "{\"namespaceSelector\":{\"matchExpressions\":[{\"key\":\"kubernetes.io/metadata.name\",\"operator\":\"NotIn\",\"values\":[\"kube-system\"]},{\"key\":\"kubernetes.io/metadata.name\",\"operator\":\"NotIn\",\"values\":[\"kyverno\"]}],\"matchLabels\":null}}" - webhookAnnotations: "{\"admissions.enforcer/disabled\":\"true\"}" ---- -apiVersion: v1 -kind: ConfigMap -metadata: - name: kyverno-metrics - namespace: kyverno - labels: - app.kubernetes.io/component: config - app.kubernetes.io/instance: kyverno - app.kubernetes.io/part-of: kyverno - app.kubernetes.io/version: v1.15.1 -data: - namespaces: "{\"exclude\":[],\"include\":[]}" - metricsExposure: "{\"kyverno_admission_requests_total\":{\"disabledLabelDimensions\":[\"resource_namespace\"]},\"kyverno_admission_review_duration_seconds\":{\"disabledLabelDimensions\":[\"resource_namespace\"]},\"kyverno_cleanup_controller_deletedobjects_total\":{\"disabledLabelDimensions\":[\"resource_namespace\",\"policy_namespace\"]},\"kyverno_policy_execution_duration_seconds\":{\"disabledLabelDimensions\":[\"resource_namespace\",\"resource_request_operation\"]},\"kyverno_policy_results_total\":{\"disabledLabelDimensions\":[\"resource_namespace\",\"policy_namespace\"]},\"kyverno_policy_rule_info_total\":{\"disabledLabelDimensions\":[\"resource_namespace\",\"policy_namespace\"]}}" - bucketBoundaries: "0.005, 0.01, 0.025, 0.05, 0.1, 0.25, 0.5, 1, 2.5, 5, 10, 15, 20, 25, 30" ---- -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - labels: - app.kubernetes.io/component: crds - app.kubernetes.io/instance: kyverno - app.kubernetes.io/managed-by: Helm - app.kubernetes.io/part-of: kyverno-crds - app.kubernetes.io/version: 3.5.1 - helm.sh/chart: crds-3.5.1 - annotations: - controller-gen.kubebuilder.io/version: v0.17.3 - name: cleanuppolicies.kyverno.io -spec: - group: kyverno.io - names: - categories: - - kyverno - kind: CleanupPolicy - listKind: CleanupPolicyList - plural: cleanuppolicies - shortNames: - - cleanpol - singular: cleanuppolicy - scope: Namespaced - versions: - - additionalPrinterColumns: - - jsonPath: .spec.schedule - name: Schedule - type: string - - jsonPath: .metadata.creationTimestamp - name: Age - type: date - name: v2 - schema: - openAPIV3Schema: - description: CleanupPolicy defines a rule for resource cleanup. - properties: - apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - type: string - kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - metadata: - type: object - spec: - description: Spec declares policy behaviors. - properties: - conditions: - description: Conditions defines the conditions used to select the - resources which will be cleaned up. - properties: - all: - description: |- - AllConditions enable variable-based conditional rule execution. This is useful for - finer control of when an rule is applied. A condition can reference object data - using JMESPath notation. - Here, all of the conditions need to pass. - items: - properties: - key: - description: Key is the context entry (using JMESPath) for - conditional rule evaluation. - x-kubernetes-preserve-unknown-fields: true - message: - description: Message is an optional display message - type: string - operator: - description: |- - Operator is the conditional operation to perform. Valid operators are: - Equals, NotEquals, In, AnyIn, AllIn, NotIn, AnyNotIn, AllNotIn, GreaterThanOrEquals, - GreaterThan, LessThanOrEquals, LessThan, DurationGreaterThanOrEquals, DurationGreaterThan, - DurationLessThanOrEquals, DurationLessThan - enum: - - Equals - - NotEquals - - AnyIn - - AllIn - - AnyNotIn - - AllNotIn - - GreaterThanOrEquals - - GreaterThan - - LessThanOrEquals - - LessThan - - DurationGreaterThanOrEquals - - DurationGreaterThan - - DurationLessThanOrEquals - - DurationLessThan - type: string - value: - description: |- - Value is the conditional value, or set of values. The values can be fixed set - or can be variables declared using JMESPath. - x-kubernetes-preserve-unknown-fields: true - type: object - type: array - any: - description: |- - AnyConditions enable variable-based conditional rule execution. This is useful for - finer control of when an rule is applied. A condition can reference object data - using JMESPath notation. - Here, at least one of the conditions need to pass. - items: - properties: - key: - description: Key is the context entry (using JMESPath) for - conditional rule evaluation. - x-kubernetes-preserve-unknown-fields: true - message: - description: Message is an optional display message - type: string - operator: - description: |- - Operator is the conditional operation to perform. Valid operators are: - Equals, NotEquals, In, AnyIn, AllIn, NotIn, AnyNotIn, AllNotIn, GreaterThanOrEquals, - GreaterThan, LessThanOrEquals, LessThan, DurationGreaterThanOrEquals, DurationGreaterThan, - DurationLessThanOrEquals, DurationLessThan - enum: - - Equals - - NotEquals - - AnyIn - - AllIn - - AnyNotIn - - AllNotIn - - GreaterThanOrEquals - - GreaterThan - - LessThanOrEquals - - LessThan - - DurationGreaterThanOrEquals - - DurationGreaterThan - - DurationLessThanOrEquals - - DurationLessThan - type: string - value: - description: |- - Value is the conditional value, or set of values. The values can be fixed set - or can be variables declared using JMESPath. - x-kubernetes-preserve-unknown-fields: true - type: object - type: array - type: object - context: - description: Context defines variables and data sources that can be - used during rule execution. - items: - description: |- - ContextEntry adds variables and data sources to a rule Context. Either a - ConfigMap reference or a APILookup must be provided. - oneOf: - - required: - - configMap - - required: - - apiCall - - required: - - imageRegistry - - required: - - variable - - required: - - globalReference - properties: - apiCall: - description: |- - APICall is an HTTP request to the Kubernetes API server, or other JSON web service. - The data returned is stored in the context with the name for the context entry. - properties: - data: - description: |- - The data object specifies the POST data sent to the server. - Only applicable when the method field is set to POST. - items: - description: RequestData contains the HTTP POST data - properties: - key: - description: Key is a unique identifier for the data - value - type: string - value: - description: Value is the data value - x-kubernetes-preserve-unknown-fields: true - required: - - key - - value - type: object - type: array - default: - description: |- - Default is an optional arbitrary JSON object that the context - value is set to, if the apiCall returns error. - x-kubernetes-preserve-unknown-fields: true - jmesPath: - description: |- - JMESPath is an optional JSON Match Expression that can be used to - transform the JSON response returned from the server. For example - a JMESPath of "items | length(@)" applied to the API server response - for the URLPath "/apis/apps/v1/deployments" will return the total count - of deployments across all namespaces. - type: string - method: - default: GET - description: Method is the HTTP request type (GET or POST). - Defaults to GET. - enum: - - GET - - POST - type: string - service: - description: |- - Service is an API call to a JSON web service. - This is used for non-Kubernetes API server calls. - It's mutually exclusive with the URLPath field. - properties: - caBundle: - description: |- - CABundle is a PEM encoded CA bundle which will be used to validate - the server certificate. - type: string - headers: - description: Headers is a list of optional HTTP headers - to be included in the request. - items: - properties: - key: - description: Key is the header key - type: string - value: - description: Value is the header value - type: string - required: - - key - - value - type: object - type: array - url: - description: |- - URL is the JSON web service URL. A typical form is - `https://{service}.{namespace}:{port}/{path}`. - type: string - required: - - url - type: object - urlPath: - description: |- - URLPath is the URL path to be used in the HTTP GET or POST request to the - Kubernetes API server (e.g. "/api/v1/namespaces" or "/apis/apps/v1/deployments"). - The format required is the same format used by the `kubectl get --raw` command. - See https://kyverno.io/docs/writing-policies/external-data-sources/#variables-from-kubernetes-api-server-calls - for details. - It's mutually exclusive with the Service field. - type: string - type: object - configMap: - description: ConfigMap is the ConfigMap reference. - properties: - name: - description: Name is the ConfigMap name. - type: string - namespace: - description: Namespace is the ConfigMap namespace. - type: string - required: - - name - type: object - globalReference: - description: GlobalContextEntryReference is a reference to a - cached global context entry. - properties: - jmesPath: - description: |- - JMESPath is an optional JSON Match Expression that can be used to - transform the JSON response returned from the server. For example - a JMESPath of "items | length(@)" applied to the API server response - for the URLPath "/apis/apps/v1/deployments" will return the total count - of deployments across all namespaces. - type: string - name: - description: Name of the global context entry - type: string - required: - - name - type: object - imageRegistry: - description: |- - ImageRegistry defines requests to an OCI/Docker V2 registry to fetch image - details. - properties: - imageRegistryCredentials: - description: ImageRegistryCredentials provides credentials - that will be used for authentication with registry - properties: - allowInsecureRegistry: - description: AllowInsecureRegistry allows insecure access - to a registry. - type: boolean - providers: - description: |- - Providers specifies a list of OCI Registry names, whose authentication providers are provided. - It can be of one of these values: default,google,azure,amazon,github. - items: - description: ImageRegistryCredentialsProvidersType - provides the list of credential providers required. - enum: - - default - - amazon - - azure - - google - - github - type: string - type: array - secrets: - description: |- - Secrets specifies a list of secrets that are provided for credentials. - Secrets must live in the Kyverno namespace. - items: - type: string - type: array - type: object - jmesPath: - description: |- - JMESPath is an optional JSON Match Expression that can be used to - transform the ImageData struct returned as a result of processing - the image reference. - type: string - reference: - description: |- - Reference is image reference to a container image in the registry. - Example: ghcr.io/kyverno/kyverno:latest - type: string - required: - - reference - type: object - name: - description: Name is the variable name. - type: string - variable: - description: Variable defines an arbitrary JMESPath context - variable that can be defined inline. - properties: - default: - description: |- - Default is an optional arbitrary JSON object that the variable may take if the JMESPath - expression evaluates to nil - x-kubernetes-preserve-unknown-fields: true - jmesPath: - description: |- - JMESPath is an optional JMESPath Expression that can be used to - transform the variable. - type: string - value: - description: Value is any arbitrary JSON object representable - in YAML or JSON form. - x-kubernetes-preserve-unknown-fields: true - type: object - required: - - name - type: object - type: array - deletionPropagationPolicy: - description: DeletionPropagationPolicy defines how resources will - be deleted (Foreground, Background, Orphan). - enum: - - Foreground - - Background - - Orphan - type: string - exclude: - description: |- - ExcludeResources defines when cleanuppolicy should not be applied. The exclude - criteria can include resource information (e.g. kind, name, namespace, labels) - and admission review request information like the name or role. - not: - required: - - any - - all - properties: - all: - description: All allows specifying resources which will be ANDed - items: - description: ResourceFilter allow users to "AND" or "OR" between - resources - properties: - clusterRoles: - description: ClusterRoles is the list of cluster-wide role - names for the user. - items: - type: string - type: array - resources: - description: ResourceDescription contains information about - the resource being created or modified. - not: - required: - - name - - names - properties: - annotations: - additionalProperties: - type: string - description: |- - Annotations is a map of annotations (key-value pairs of type string). Annotation keys - and values support the wildcard characters "*" (matches zero or many characters) and - "?" (matches at least one character). - type: object - kinds: - description: Kinds is a list of resource kinds. - items: - type: string - type: array - name: - description: |- - Name is the name of the resource. The name supports wildcard characters - "*" (matches zero or many characters) and "?" (at least one character). - NOTE: "Name" is being deprecated in favor of "Names". - type: string - names: - description: |- - Names are the names of the resources. Each name supports wildcard characters - "*" (matches zero or many characters) and "?" (at least one character). - items: - type: string - type: array - namespaceSelector: - description: |- - NamespaceSelector is a label selector for the resource namespace. Label keys and values - in `matchLabels` support the wildcard characters `*` (matches zero or many characters) - and `?` (matches one character).Wildcards allows writing label selectors like - ["storage.k8s.io/*": "*"]. Note that using ["*" : "*"] matches any key and value but - does not match an empty label set. - properties: - matchExpressions: - description: matchExpressions is a list of label - selector requirements. The requirements are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key that the - selector applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - namespaces: - description: |- - Namespaces is a list of namespaces names. Each name supports wildcard characters - "*" (matches zero or many characters) and "?" (at least one character). - items: - type: string - type: array - operations: - description: Operations can contain values ["CREATE, - "UPDATE", "CONNECT", "DELETE"], which are used to - match a specific action. - items: - description: AdmissionOperation can have one of the - values CREATE, UPDATE, CONNECT, DELETE, which are - used to match a specific action. - enum: - - CREATE - - CONNECT - - UPDATE - - DELETE - type: string - type: array - selector: - description: |- - Selector is a label selector. Label keys and values in `matchLabels` support the wildcard - characters `*` (matches zero or many characters) and `?` (matches one character). - Wildcards allows writing label selectors like ["storage.k8s.io/*": "*"]. Note that - using ["*" : "*"] matches any key and value but does not match an empty label set. - properties: - matchExpressions: - description: matchExpressions is a list of label - selector requirements. The requirements are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key that the - selector applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - type: object - roles: - description: Roles is the list of namespaced role names - for the user. - items: - type: string - type: array - subjects: - description: Subjects is the list of subject names like - users, user groups, and service accounts. - items: - description: |- - Subject contains a reference to the object or user identities a role binding applies to. This can either hold a direct API object reference, - or a value for non-objects such as user and group names. - properties: - apiGroup: - description: |- - APIGroup holds the API group of the referenced subject. - Defaults to "" for ServiceAccount subjects. - Defaults to "rbac.authorization.k8s.io" for User and Group subjects. - type: string - kind: - description: |- - Kind of object being referenced. Values defined by this API group are "User", "Group", and "ServiceAccount". - If the Authorizer does not recognized the kind value, the Authorizer should report an error. - type: string - name: - description: Name of the object being referenced. - type: string - namespace: - description: |- - Namespace of the referenced object. If the object kind is non-namespace, such as "User" or "Group", and this value is not empty - the Authorizer should report an error. - type: string - required: - - kind - - name - type: object - x-kubernetes-map-type: atomic - type: array - type: object - type: array - any: - description: Any allows specifying resources which will be ORed - items: - description: ResourceFilter allow users to "AND" or "OR" between - resources - properties: - clusterRoles: - description: ClusterRoles is the list of cluster-wide role - names for the user. - items: - type: string - type: array - resources: - description: ResourceDescription contains information about - the resource being created or modified. - not: - required: - - name - - names - properties: - annotations: - additionalProperties: - type: string - description: |- - Annotations is a map of annotations (key-value pairs of type string). Annotation keys - and values support the wildcard characters "*" (matches zero or many characters) and - "?" (matches at least one character). - type: object - kinds: - description: Kinds is a list of resource kinds. - items: - type: string - type: array - name: - description: |- - Name is the name of the resource. The name supports wildcard characters - "*" (matches zero or many characters) and "?" (at least one character). - NOTE: "Name" is being deprecated in favor of "Names". - type: string - names: - description: |- - Names are the names of the resources. Each name supports wildcard characters - "*" (matches zero or many characters) and "?" (at least one character). - items: - type: string - type: array - namespaceSelector: - description: |- - NamespaceSelector is a label selector for the resource namespace. Label keys and values - in `matchLabels` support the wildcard characters `*` (matches zero or many characters) - and `?` (matches one character).Wildcards allows writing label selectors like - ["storage.k8s.io/*": "*"]. Note that using ["*" : "*"] matches any key and value but - does not match an empty label set. - properties: - matchExpressions: - description: matchExpressions is a list of label - selector requirements. The requirements are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key that the - selector applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - namespaces: - description: |- - Namespaces is a list of namespaces names. Each name supports wildcard characters - "*" (matches zero or many characters) and "?" (at least one character). - items: - type: string - type: array - operations: - description: Operations can contain values ["CREATE, - "UPDATE", "CONNECT", "DELETE"], which are used to - match a specific action. - items: - description: AdmissionOperation can have one of the - values CREATE, UPDATE, CONNECT, DELETE, which are - used to match a specific action. - enum: - - CREATE - - CONNECT - - UPDATE - - DELETE - type: string - type: array - selector: - description: |- - Selector is a label selector. Label keys and values in `matchLabels` support the wildcard - characters `*` (matches zero or many characters) and `?` (matches one character). - Wildcards allows writing label selectors like ["storage.k8s.io/*": "*"]. Note that - using ["*" : "*"] matches any key and value but does not match an empty label set. - properties: - matchExpressions: - description: matchExpressions is a list of label - selector requirements. The requirements are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key that the - selector applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - type: object - roles: - description: Roles is the list of namespaced role names - for the user. - items: - type: string - type: array - subjects: - description: Subjects is the list of subject names like - users, user groups, and service accounts. - items: - description: |- - Subject contains a reference to the object or user identities a role binding applies to. This can either hold a direct API object reference, - or a value for non-objects such as user and group names. - properties: - apiGroup: - description: |- - APIGroup holds the API group of the referenced subject. - Defaults to "" for ServiceAccount subjects. - Defaults to "rbac.authorization.k8s.io" for User and Group subjects. - type: string - kind: - description: |- - Kind of object being referenced. Values defined by this API group are "User", "Group", and "ServiceAccount". - If the Authorizer does not recognized the kind value, the Authorizer should report an error. - type: string - name: - description: Name of the object being referenced. - type: string - namespace: - description: |- - Namespace of the referenced object. If the object kind is non-namespace, such as "User" or "Group", and this value is not empty - the Authorizer should report an error. - type: string - required: - - kind - - name - type: object - x-kubernetes-map-type: atomic - type: array - type: object - type: array - type: object - match: - description: |- - MatchResources defines when cleanuppolicy should be applied. The match - criteria can include resource information (e.g. kind, name, namespace, labels) - and admission review request information like the user name or role. - At least one kind is required. - not: - required: - - any - - all - properties: - all: - description: All allows specifying resources which will be ANDed - items: - description: ResourceFilter allow users to "AND" or "OR" between - resources - properties: - clusterRoles: - description: ClusterRoles is the list of cluster-wide role - names for the user. - items: - type: string - type: array - resources: - description: ResourceDescription contains information about - the resource being created or modified. - not: - required: - - name - - names - properties: - annotations: - additionalProperties: - type: string - description: |- - Annotations is a map of annotations (key-value pairs of type string). Annotation keys - and values support the wildcard characters "*" (matches zero or many characters) and - "?" (matches at least one character). - type: object - kinds: - description: Kinds is a list of resource kinds. - items: - type: string - type: array - name: - description: |- - Name is the name of the resource. The name supports wildcard characters - "*" (matches zero or many characters) and "?" (at least one character). - NOTE: "Name" is being deprecated in favor of "Names". - type: string - names: - description: |- - Names are the names of the resources. Each name supports wildcard characters - "*" (matches zero or many characters) and "?" (at least one character). - items: - type: string - type: array - namespaceSelector: - description: |- - NamespaceSelector is a label selector for the resource namespace. Label keys and values - in `matchLabels` support the wildcard characters `*` (matches zero or many characters) - and `?` (matches one character).Wildcards allows writing label selectors like - ["storage.k8s.io/*": "*"]. Note that using ["*" : "*"] matches any key and value but - does not match an empty label set. - properties: - matchExpressions: - description: matchExpressions is a list of label - selector requirements. The requirements are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key that the - selector applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - namespaces: - description: |- - Namespaces is a list of namespaces names. Each name supports wildcard characters - "*" (matches zero or many characters) and "?" (at least one character). - items: - type: string - type: array - operations: - description: Operations can contain values ["CREATE, - "UPDATE", "CONNECT", "DELETE"], which are used to - match a specific action. - items: - description: AdmissionOperation can have one of the - values CREATE, UPDATE, CONNECT, DELETE, which are - used to match a specific action. - enum: - - CREATE - - CONNECT - - UPDATE - - DELETE - type: string - type: array - selector: - description: |- - Selector is a label selector. Label keys and values in `matchLabels` support the wildcard - characters `*` (matches zero or many characters) and `?` (matches one character). - Wildcards allows writing label selectors like ["storage.k8s.io/*": "*"]. Note that - using ["*" : "*"] matches any key and value but does not match an empty label set. - properties: - matchExpressions: - description: matchExpressions is a list of label - selector requirements. The requirements are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key that the - selector applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - type: object - roles: - description: Roles is the list of namespaced role names - for the user. - items: - type: string - type: array - subjects: - description: Subjects is the list of subject names like - users, user groups, and service accounts. - items: - description: |- - Subject contains a reference to the object or user identities a role binding applies to. This can either hold a direct API object reference, - or a value for non-objects such as user and group names. - properties: - apiGroup: - description: |- - APIGroup holds the API group of the referenced subject. - Defaults to "" for ServiceAccount subjects. - Defaults to "rbac.authorization.k8s.io" for User and Group subjects. - type: string - kind: - description: |- - Kind of object being referenced. Values defined by this API group are "User", "Group", and "ServiceAccount". - If the Authorizer does not recognized the kind value, the Authorizer should report an error. - type: string - name: - description: Name of the object being referenced. - type: string - namespace: - description: |- - Namespace of the referenced object. If the object kind is non-namespace, such as "User" or "Group", and this value is not empty - the Authorizer should report an error. - type: string - required: - - kind - - name - type: object - x-kubernetes-map-type: atomic - type: array - type: object - type: array - any: - description: Any allows specifying resources which will be ORed - items: - description: ResourceFilter allow users to "AND" or "OR" between - resources - properties: - clusterRoles: - description: ClusterRoles is the list of cluster-wide role - names for the user. - items: - type: string - type: array - resources: - description: ResourceDescription contains information about - the resource being created or modified. - not: - required: - - name - - names - properties: - annotations: - additionalProperties: - type: string - description: |- - Annotations is a map of annotations (key-value pairs of type string). Annotation keys - and values support the wildcard characters "*" (matches zero or many characters) and - "?" (matches at least one character). - type: object - kinds: - description: Kinds is a list of resource kinds. - items: - type: string - type: array - name: - description: |- - Name is the name of the resource. The name supports wildcard characters - "*" (matches zero or many characters) and "?" (at least one character). - NOTE: "Name" is being deprecated in favor of "Names". - type: string - names: - description: |- - Names are the names of the resources. Each name supports wildcard characters - "*" (matches zero or many characters) and "?" (at least one character). - items: - type: string - type: array - namespaceSelector: - description: |- - NamespaceSelector is a label selector for the resource namespace. Label keys and values - in `matchLabels` support the wildcard characters `*` (matches zero or many characters) - and `?` (matches one character).Wildcards allows writing label selectors like - ["storage.k8s.io/*": "*"]. Note that using ["*" : "*"] matches any key and value but - does not match an empty label set. - properties: - matchExpressions: - description: matchExpressions is a list of label - selector requirements. The requirements are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key that the - selector applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - namespaces: - description: |- - Namespaces is a list of namespaces names. Each name supports wildcard characters - "*" (matches zero or many characters) and "?" (at least one character). - items: - type: string - type: array - operations: - description: Operations can contain values ["CREATE, - "UPDATE", "CONNECT", "DELETE"], which are used to - match a specific action. - items: - description: AdmissionOperation can have one of the - values CREATE, UPDATE, CONNECT, DELETE, which are - used to match a specific action. - enum: - - CREATE - - CONNECT - - UPDATE - - DELETE - type: string - type: array - selector: - description: |- - Selector is a label selector. Label keys and values in `matchLabels` support the wildcard - characters `*` (matches zero or many characters) and `?` (matches one character). - Wildcards allows writing label selectors like ["storage.k8s.io/*": "*"]. Note that - using ["*" : "*"] matches any key and value but does not match an empty label set. - properties: - matchExpressions: - description: matchExpressions is a list of label - selector requirements. The requirements are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key that the - selector applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - type: object - roles: - description: Roles is the list of namespaced role names - for the user. - items: - type: string - type: array - subjects: - description: Subjects is the list of subject names like - users, user groups, and service accounts. - items: - description: |- - Subject contains a reference to the object or user identities a role binding applies to. This can either hold a direct API object reference, - or a value for non-objects such as user and group names. - properties: - apiGroup: - description: |- - APIGroup holds the API group of the referenced subject. - Defaults to "" for ServiceAccount subjects. - Defaults to "rbac.authorization.k8s.io" for User and Group subjects. - type: string - kind: - description: |- - Kind of object being referenced. Values defined by this API group are "User", "Group", and "ServiceAccount". - If the Authorizer does not recognized the kind value, the Authorizer should report an error. - type: string - name: - description: Name of the object being referenced. - type: string - namespace: - description: |- - Namespace of the referenced object. If the object kind is non-namespace, such as "User" or "Group", and this value is not empty - the Authorizer should report an error. - type: string - required: - - kind - - name - type: object - x-kubernetes-map-type: atomic - type: array - type: object - type: array - type: object - schedule: - description: The schedule in Cron format - type: string - required: - - match - - schedule - type: object - status: - description: Status contains policy runtime data. - properties: - conditions: - items: - description: Condition contains details for one aspect of the current - state of this API Resource. - properties: - lastTransitionTime: - description: |- - lastTransitionTime is the last time the condition transitioned from one status to another. - This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable. - format: date-time - type: string - message: - description: |- - message is a human readable message indicating details about the transition. - This may be an empty string. - maxLength: 32768 - type: string - observedGeneration: - description: |- - observedGeneration represents the .metadata.generation that the condition was set based upon. - For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date - with respect to the current state of the instance. - format: int64 - minimum: 0 - type: integer - reason: - description: |- - reason contains a programmatic identifier indicating the reason for the condition's last transition. - Producers of specific condition types may define expected values and meanings for this field, - and whether the values are considered a guaranteed API. - The value should be a CamelCase string. - This field may not be empty. - maxLength: 1024 - minLength: 1 - pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ - type: string - status: - description: status of the condition, one of True, False, Unknown. - enum: - - "True" - - "False" - - Unknown - type: string - type: - description: type of condition in CamelCase or in foo.example.com/CamelCase. - maxLength: 316 - pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ - type: string - required: - - lastTransitionTime - - message - - reason - - status - - type - type: object - type: array - lastExecutionTime: - format: date-time - type: string - type: object - required: - - spec - type: object - served: true - storage: true - subresources: - status: {} - - additionalPrinterColumns: - - jsonPath: .spec.schedule - name: Schedule - type: string - - jsonPath: .metadata.creationTimestamp - name: Age - type: date - deprecated: true - name: v2beta1 - schema: - openAPIV3Schema: - description: CleanupPolicy defines a rule for resource cleanup. - properties: - apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - type: string - kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - metadata: - type: object - spec: - description: Spec declares policy behaviors. - properties: - conditions: - description: Conditions defines the conditions used to select the - resources which will be cleaned up. - properties: - all: - description: |- - AllConditions enable variable-based conditional rule execution. This is useful for - finer control of when an rule is applied. A condition can reference object data - using JMESPath notation. - Here, all of the conditions need to pass. - items: - properties: - key: - description: Key is the context entry (using JMESPath) for - conditional rule evaluation. - x-kubernetes-preserve-unknown-fields: true - message: - description: Message is an optional display message - type: string - operator: - description: |- - Operator is the conditional operation to perform. Valid operators are: - Equals, NotEquals, In, AnyIn, AllIn, NotIn, AnyNotIn, AllNotIn, GreaterThanOrEquals, - GreaterThan, LessThanOrEquals, LessThan, DurationGreaterThanOrEquals, DurationGreaterThan, - DurationLessThanOrEquals, DurationLessThan - enum: - - Equals - - NotEquals - - AnyIn - - AllIn - - AnyNotIn - - AllNotIn - - GreaterThanOrEquals - - GreaterThan - - LessThanOrEquals - - LessThan - - DurationGreaterThanOrEquals - - DurationGreaterThan - - DurationLessThanOrEquals - - DurationLessThan - type: string - value: - description: |- - Value is the conditional value, or set of values. The values can be fixed set - or can be variables declared using JMESPath. - x-kubernetes-preserve-unknown-fields: true - type: object - type: array - any: - description: |- - AnyConditions enable variable-based conditional rule execution. This is useful for - finer control of when an rule is applied. A condition can reference object data - using JMESPath notation. - Here, at least one of the conditions need to pass. - items: - properties: - key: - description: Key is the context entry (using JMESPath) for - conditional rule evaluation. - x-kubernetes-preserve-unknown-fields: true - message: - description: Message is an optional display message - type: string - operator: - description: |- - Operator is the conditional operation to perform. Valid operators are: - Equals, NotEquals, In, AnyIn, AllIn, NotIn, AnyNotIn, AllNotIn, GreaterThanOrEquals, - GreaterThan, LessThanOrEquals, LessThan, DurationGreaterThanOrEquals, DurationGreaterThan, - DurationLessThanOrEquals, DurationLessThan - enum: - - Equals - - NotEquals - - AnyIn - - AllIn - - AnyNotIn - - AllNotIn - - GreaterThanOrEquals - - GreaterThan - - LessThanOrEquals - - LessThan - - DurationGreaterThanOrEquals - - DurationGreaterThan - - DurationLessThanOrEquals - - DurationLessThan - type: string - value: - description: |- - Value is the conditional value, or set of values. The values can be fixed set - or can be variables declared using JMESPath. - x-kubernetes-preserve-unknown-fields: true - type: object - type: array - type: object - context: - description: Context defines variables and data sources that can be - used during rule execution. - items: - description: |- - ContextEntry adds variables and data sources to a rule Context. Either a - ConfigMap reference or a APILookup must be provided. - oneOf: - - required: - - configMap - - required: - - apiCall - - required: - - imageRegistry - - required: - - variable - - required: - - globalReference - properties: - apiCall: - description: |- - APICall is an HTTP request to the Kubernetes API server, or other JSON web service. - The data returned is stored in the context with the name for the context entry. - properties: - data: - description: |- - The data object specifies the POST data sent to the server. - Only applicable when the method field is set to POST. - items: - description: RequestData contains the HTTP POST data - properties: - key: - description: Key is a unique identifier for the data - value - type: string - value: - description: Value is the data value - x-kubernetes-preserve-unknown-fields: true - required: - - key - - value - type: object - type: array - default: - description: |- - Default is an optional arbitrary JSON object that the context - value is set to, if the apiCall returns error. - x-kubernetes-preserve-unknown-fields: true - jmesPath: - description: |- - JMESPath is an optional JSON Match Expression that can be used to - transform the JSON response returned from the server. For example - a JMESPath of "items | length(@)" applied to the API server response - for the URLPath "/apis/apps/v1/deployments" will return the total count - of deployments across all namespaces. - type: string - method: - default: GET - description: Method is the HTTP request type (GET or POST). - Defaults to GET. - enum: - - GET - - POST - type: string - service: - description: |- - Service is an API call to a JSON web service. - This is used for non-Kubernetes API server calls. - It's mutually exclusive with the URLPath field. - properties: - caBundle: - description: |- - CABundle is a PEM encoded CA bundle which will be used to validate - the server certificate. - type: string - headers: - description: Headers is a list of optional HTTP headers - to be included in the request. - items: - properties: - key: - description: Key is the header key - type: string - value: - description: Value is the header value - type: string - required: - - key - - value - type: object - type: array - url: - description: |- - URL is the JSON web service URL. A typical form is - `https://{service}.{namespace}:{port}/{path}`. - type: string - required: - - url - type: object - urlPath: - description: |- - URLPath is the URL path to be used in the HTTP GET or POST request to the - Kubernetes API server (e.g. "/api/v1/namespaces" or "/apis/apps/v1/deployments"). - The format required is the same format used by the `kubectl get --raw` command. - See https://kyverno.io/docs/writing-policies/external-data-sources/#variables-from-kubernetes-api-server-calls - for details. - It's mutually exclusive with the Service field. - type: string - type: object - configMap: - description: ConfigMap is the ConfigMap reference. - properties: - name: - description: Name is the ConfigMap name. - type: string - namespace: - description: Namespace is the ConfigMap namespace. - type: string - required: - - name - type: object - globalReference: - description: GlobalContextEntryReference is a reference to a - cached global context entry. - properties: - jmesPath: - description: |- - JMESPath is an optional JSON Match Expression that can be used to - transform the JSON response returned from the server. For example - a JMESPath of "items | length(@)" applied to the API server response - for the URLPath "/apis/apps/v1/deployments" will return the total count - of deployments across all namespaces. - type: string - name: - description: Name of the global context entry - type: string - required: - - name - type: object - imageRegistry: - description: |- - ImageRegistry defines requests to an OCI/Docker V2 registry to fetch image - details. - properties: - imageRegistryCredentials: - description: ImageRegistryCredentials provides credentials - that will be used for authentication with registry - properties: - allowInsecureRegistry: - description: AllowInsecureRegistry allows insecure access - to a registry. - type: boolean - providers: - description: |- - Providers specifies a list of OCI Registry names, whose authentication providers are provided. - It can be of one of these values: default,google,azure,amazon,github. - items: - description: ImageRegistryCredentialsProvidersType - provides the list of credential providers required. - enum: - - default - - amazon - - azure - - google - - github - type: string - type: array - secrets: - description: |- - Secrets specifies a list of secrets that are provided for credentials. - Secrets must live in the Kyverno namespace. - items: - type: string - type: array - type: object - jmesPath: - description: |- - JMESPath is an optional JSON Match Expression that can be used to - transform the ImageData struct returned as a result of processing - the image reference. - type: string - reference: - description: |- - Reference is image reference to a container image in the registry. - Example: ghcr.io/kyverno/kyverno:latest - type: string - required: - - reference - type: object - name: - description: Name is the variable name. - type: string - variable: - description: Variable defines an arbitrary JMESPath context - variable that can be defined inline. - properties: - default: - description: |- - Default is an optional arbitrary JSON object that the variable may take if the JMESPath - expression evaluates to nil - x-kubernetes-preserve-unknown-fields: true - jmesPath: - description: |- - JMESPath is an optional JMESPath Expression that can be used to - transform the variable. - type: string - value: - description: Value is any arbitrary JSON object representable - in YAML or JSON form. - x-kubernetes-preserve-unknown-fields: true - type: object - required: - - name - type: object - type: array - deletionPropagationPolicy: - description: DeletionPropagationPolicy defines how resources will - be deleted (Foreground, Background, Orphan). - enum: - - Foreground - - Background - - Orphan - type: string - exclude: - description: |- - ExcludeResources defines when cleanuppolicy should not be applied. The exclude - criteria can include resource information (e.g. kind, name, namespace, labels) - and admission review request information like the name or role. - not: - required: - - any - - all - properties: - all: - description: All allows specifying resources which will be ANDed - items: - description: ResourceFilter allow users to "AND" or "OR" between - resources - properties: - clusterRoles: - description: ClusterRoles is the list of cluster-wide role - names for the user. - items: - type: string - type: array - resources: - description: ResourceDescription contains information about - the resource being created or modified. - not: - required: - - name - - names - properties: - annotations: - additionalProperties: - type: string - description: |- - Annotations is a map of annotations (key-value pairs of type string). Annotation keys - and values support the wildcard characters "*" (matches zero or many characters) and - "?" (matches at least one character). - type: object - kinds: - description: Kinds is a list of resource kinds. - items: - type: string - type: array - name: - description: |- - Name is the name of the resource. The name supports wildcard characters - "*" (matches zero or many characters) and "?" (at least one character). - NOTE: "Name" is being deprecated in favor of "Names". - type: string - names: - description: |- - Names are the names of the resources. Each name supports wildcard characters - "*" (matches zero or many characters) and "?" (at least one character). - items: - type: string - type: array - namespaceSelector: - description: |- - NamespaceSelector is a label selector for the resource namespace. Label keys and values - in `matchLabels` support the wildcard characters `*` (matches zero or many characters) - and `?` (matches one character).Wildcards allows writing label selectors like - ["storage.k8s.io/*": "*"]. Note that using ["*" : "*"] matches any key and value but - does not match an empty label set. - properties: - matchExpressions: - description: matchExpressions is a list of label - selector requirements. The requirements are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key that the - selector applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - namespaces: - description: |- - Namespaces is a list of namespaces names. Each name supports wildcard characters - "*" (matches zero or many characters) and "?" (at least one character). - items: - type: string - type: array - operations: - description: Operations can contain values ["CREATE, - "UPDATE", "CONNECT", "DELETE"], which are used to - match a specific action. - items: - description: AdmissionOperation can have one of the - values CREATE, UPDATE, CONNECT, DELETE, which are - used to match a specific action. - enum: - - CREATE - - CONNECT - - UPDATE - - DELETE - type: string - type: array - selector: - description: |- - Selector is a label selector. Label keys and values in `matchLabels` support the wildcard - characters `*` (matches zero or many characters) and `?` (matches one character). - Wildcards allows writing label selectors like ["storage.k8s.io/*": "*"]. Note that - using ["*" : "*"] matches any key and value but does not match an empty label set. - properties: - matchExpressions: - description: matchExpressions is a list of label - selector requirements. The requirements are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key that the - selector applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - type: object - roles: - description: Roles is the list of namespaced role names - for the user. - items: - type: string - type: array - subjects: - description: Subjects is the list of subject names like - users, user groups, and service accounts. - items: - description: |- - Subject contains a reference to the object or user identities a role binding applies to. This can either hold a direct API object reference, - or a value for non-objects such as user and group names. - properties: - apiGroup: - description: |- - APIGroup holds the API group of the referenced subject. - Defaults to "" for ServiceAccount subjects. - Defaults to "rbac.authorization.k8s.io" for User and Group subjects. - type: string - kind: - description: |- - Kind of object being referenced. Values defined by this API group are "User", "Group", and "ServiceAccount". - If the Authorizer does not recognized the kind value, the Authorizer should report an error. - type: string - name: - description: Name of the object being referenced. - type: string - namespace: - description: |- - Namespace of the referenced object. If the object kind is non-namespace, such as "User" or "Group", and this value is not empty - the Authorizer should report an error. - type: string - required: - - kind - - name - type: object - x-kubernetes-map-type: atomic - type: array - type: object - type: array - any: - description: Any allows specifying resources which will be ORed - items: - description: ResourceFilter allow users to "AND" or "OR" between - resources - properties: - clusterRoles: - description: ClusterRoles is the list of cluster-wide role - names for the user. - items: - type: string - type: array - resources: - description: ResourceDescription contains information about - the resource being created or modified. - not: - required: - - name - - names - properties: - annotations: - additionalProperties: - type: string - description: |- - Annotations is a map of annotations (key-value pairs of type string). Annotation keys - and values support the wildcard characters "*" (matches zero or many characters) and - "?" (matches at least one character). - type: object - kinds: - description: Kinds is a list of resource kinds. - items: - type: string - type: array - name: - description: |- - Name is the name of the resource. The name supports wildcard characters - "*" (matches zero or many characters) and "?" (at least one character). - NOTE: "Name" is being deprecated in favor of "Names". - type: string - names: - description: |- - Names are the names of the resources. Each name supports wildcard characters - "*" (matches zero or many characters) and "?" (at least one character). - items: - type: string - type: array - namespaceSelector: - description: |- - NamespaceSelector is a label selector for the resource namespace. Label keys and values - in `matchLabels` support the wildcard characters `*` (matches zero or many characters) - and `?` (matches one character).Wildcards allows writing label selectors like - ["storage.k8s.io/*": "*"]. Note that using ["*" : "*"] matches any key and value but - does not match an empty label set. - properties: - matchExpressions: - description: matchExpressions is a list of label - selector requirements. The requirements are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key that the - selector applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - namespaces: - description: |- - Namespaces is a list of namespaces names. Each name supports wildcard characters - "*" (matches zero or many characters) and "?" (at least one character). - items: - type: string - type: array - operations: - description: Operations can contain values ["CREATE, - "UPDATE", "CONNECT", "DELETE"], which are used to - match a specific action. - items: - description: AdmissionOperation can have one of the - values CREATE, UPDATE, CONNECT, DELETE, which are - used to match a specific action. - enum: - - CREATE - - CONNECT - - UPDATE - - DELETE - type: string - type: array - selector: - description: |- - Selector is a label selector. Label keys and values in `matchLabels` support the wildcard - characters `*` (matches zero or many characters) and `?` (matches one character). - Wildcards allows writing label selectors like ["storage.k8s.io/*": "*"]. Note that - using ["*" : "*"] matches any key and value but does not match an empty label set. - properties: - matchExpressions: - description: matchExpressions is a list of label - selector requirements. The requirements are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key that the - selector applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - type: object - roles: - description: Roles is the list of namespaced role names - for the user. - items: - type: string - type: array - subjects: - description: Subjects is the list of subject names like - users, user groups, and service accounts. - items: - description: |- - Subject contains a reference to the object or user identities a role binding applies to. This can either hold a direct API object reference, - or a value for non-objects such as user and group names. - properties: - apiGroup: - description: |- - APIGroup holds the API group of the referenced subject. - Defaults to "" for ServiceAccount subjects. - Defaults to "rbac.authorization.k8s.io" for User and Group subjects. - type: string - kind: - description: |- - Kind of object being referenced. Values defined by this API group are "User", "Group", and "ServiceAccount". - If the Authorizer does not recognized the kind value, the Authorizer should report an error. - type: string - name: - description: Name of the object being referenced. - type: string - namespace: - description: |- - Namespace of the referenced object. If the object kind is non-namespace, such as "User" or "Group", and this value is not empty - the Authorizer should report an error. - type: string - required: - - kind - - name - type: object - x-kubernetes-map-type: atomic - type: array - type: object - type: array - type: object - match: - description: |- - MatchResources defines when cleanuppolicy should be applied. The match - criteria can include resource information (e.g. kind, name, namespace, labels) - and admission review request information like the user name or role. - At least one kind is required. - not: - required: - - any - - all - properties: - all: - description: All allows specifying resources which will be ANDed - items: - description: ResourceFilter allow users to "AND" or "OR" between - resources - properties: - clusterRoles: - description: ClusterRoles is the list of cluster-wide role - names for the user. - items: - type: string - type: array - resources: - description: ResourceDescription contains information about - the resource being created or modified. - not: - required: - - name - - names - properties: - annotations: - additionalProperties: - type: string - description: |- - Annotations is a map of annotations (key-value pairs of type string). Annotation keys - and values support the wildcard characters "*" (matches zero or many characters) and - "?" (matches at least one character). - type: object - kinds: - description: Kinds is a list of resource kinds. - items: - type: string - type: array - name: - description: |- - Name is the name of the resource. The name supports wildcard characters - "*" (matches zero or many characters) and "?" (at least one character). - NOTE: "Name" is being deprecated in favor of "Names". - type: string - names: - description: |- - Names are the names of the resources. Each name supports wildcard characters - "*" (matches zero or many characters) and "?" (at least one character). - items: - type: string - type: array - namespaceSelector: - description: |- - NamespaceSelector is a label selector for the resource namespace. Label keys and values - in `matchLabels` support the wildcard characters `*` (matches zero or many characters) - and `?` (matches one character).Wildcards allows writing label selectors like - ["storage.k8s.io/*": "*"]. Note that using ["*" : "*"] matches any key and value but - does not match an empty label set. - properties: - matchExpressions: - description: matchExpressions is a list of label - selector requirements. The requirements are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key that the - selector applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - namespaces: - description: |- - Namespaces is a list of namespaces names. Each name supports wildcard characters - "*" (matches zero or many characters) and "?" (at least one character). - items: - type: string - type: array - operations: - description: Operations can contain values ["CREATE, - "UPDATE", "CONNECT", "DELETE"], which are used to - match a specific action. - items: - description: AdmissionOperation can have one of the - values CREATE, UPDATE, CONNECT, DELETE, which are - used to match a specific action. - enum: - - CREATE - - CONNECT - - UPDATE - - DELETE - type: string - type: array - selector: - description: |- - Selector is a label selector. Label keys and values in `matchLabels` support the wildcard - characters `*` (matches zero or many characters) and `?` (matches one character). - Wildcards allows writing label selectors like ["storage.k8s.io/*": "*"]. Note that - using ["*" : "*"] matches any key and value but does not match an empty label set. - properties: - matchExpressions: - description: matchExpressions is a list of label - selector requirements. The requirements are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key that the - selector applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - type: object - roles: - description: Roles is the list of namespaced role names - for the user. - items: - type: string - type: array - subjects: - description: Subjects is the list of subject names like - users, user groups, and service accounts. - items: - description: |- - Subject contains a reference to the object or user identities a role binding applies to. This can either hold a direct API object reference, - or a value for non-objects such as user and group names. - properties: - apiGroup: - description: |- - APIGroup holds the API group of the referenced subject. - Defaults to "" for ServiceAccount subjects. - Defaults to "rbac.authorization.k8s.io" for User and Group subjects. - type: string - kind: - description: |- - Kind of object being referenced. Values defined by this API group are "User", "Group", and "ServiceAccount". - If the Authorizer does not recognized the kind value, the Authorizer should report an error. - type: string - name: - description: Name of the object being referenced. - type: string - namespace: - description: |- - Namespace of the referenced object. If the object kind is non-namespace, such as "User" or "Group", and this value is not empty - the Authorizer should report an error. - type: string - required: - - kind - - name - type: object - x-kubernetes-map-type: atomic - type: array - type: object - type: array - any: - description: Any allows specifying resources which will be ORed - items: - description: ResourceFilter allow users to "AND" or "OR" between - resources - properties: - clusterRoles: - description: ClusterRoles is the list of cluster-wide role - names for the user. - items: - type: string - type: array - resources: - description: ResourceDescription contains information about - the resource being created or modified. - not: - required: - - name - - names - properties: - annotations: - additionalProperties: - type: string - description: |- - Annotations is a map of annotations (key-value pairs of type string). Annotation keys - and values support the wildcard characters "*" (matches zero or many characters) and - "?" (matches at least one character). - type: object - kinds: - description: Kinds is a list of resource kinds. - items: - type: string - type: array - name: - description: |- - Name is the name of the resource. The name supports wildcard characters - "*" (matches zero or many characters) and "?" (at least one character). - NOTE: "Name" is being deprecated in favor of "Names". - type: string - names: - description: |- - Names are the names of the resources. Each name supports wildcard characters - "*" (matches zero or many characters) and "?" (at least one character). - items: - type: string - type: array - namespaceSelector: - description: |- - NamespaceSelector is a label selector for the resource namespace. Label keys and values - in `matchLabels` support the wildcard characters `*` (matches zero or many characters) - and `?` (matches one character).Wildcards allows writing label selectors like - ["storage.k8s.io/*": "*"]. Note that using ["*" : "*"] matches any key and value but - does not match an empty label set. - properties: - matchExpressions: - description: matchExpressions is a list of label - selector requirements. The requirements are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key that the - selector applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - namespaces: - description: |- - Namespaces is a list of namespaces names. Each name supports wildcard characters - "*" (matches zero or many characters) and "?" (at least one character). - items: - type: string - type: array - operations: - description: Operations can contain values ["CREATE, - "UPDATE", "CONNECT", "DELETE"], which are used to - match a specific action. - items: - description: AdmissionOperation can have one of the - values CREATE, UPDATE, CONNECT, DELETE, which are - used to match a specific action. - enum: - - CREATE - - CONNECT - - UPDATE - - DELETE - type: string - type: array - selector: - description: |- - Selector is a label selector. Label keys and values in `matchLabels` support the wildcard - characters `*` (matches zero or many characters) and `?` (matches one character). - Wildcards allows writing label selectors like ["storage.k8s.io/*": "*"]. Note that - using ["*" : "*"] matches any key and value but does not match an empty label set. - properties: - matchExpressions: - description: matchExpressions is a list of label - selector requirements. The requirements are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key that the - selector applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - type: object - roles: - description: Roles is the list of namespaced role names - for the user. - items: - type: string - type: array - subjects: - description: Subjects is the list of subject names like - users, user groups, and service accounts. - items: - description: |- - Subject contains a reference to the object or user identities a role binding applies to. This can either hold a direct API object reference, - or a value for non-objects such as user and group names. - properties: - apiGroup: - description: |- - APIGroup holds the API group of the referenced subject. - Defaults to "" for ServiceAccount subjects. - Defaults to "rbac.authorization.k8s.io" for User and Group subjects. - type: string - kind: - description: |- - Kind of object being referenced. Values defined by this API group are "User", "Group", and "ServiceAccount". - If the Authorizer does not recognized the kind value, the Authorizer should report an error. - type: string - name: - description: Name of the object being referenced. - type: string - namespace: - description: |- - Namespace of the referenced object. If the object kind is non-namespace, such as "User" or "Group", and this value is not empty - the Authorizer should report an error. - type: string - required: - - kind - - name - type: object - x-kubernetes-map-type: atomic - type: array - type: object - type: array - type: object - schedule: - description: The schedule in Cron format - type: string - required: - - match - - schedule - type: object - status: - description: Status contains policy runtime data. - properties: - conditions: - items: - description: Condition contains details for one aspect of the current - state of this API Resource. - properties: - lastTransitionTime: - description: |- - lastTransitionTime is the last time the condition transitioned from one status to another. - This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable. - format: date-time - type: string - message: - description: |- - message is a human readable message indicating details about the transition. - This may be an empty string. - maxLength: 32768 - type: string - observedGeneration: - description: |- - observedGeneration represents the .metadata.generation that the condition was set based upon. - For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date - with respect to the current state of the instance. - format: int64 - minimum: 0 - type: integer - reason: - description: |- - reason contains a programmatic identifier indicating the reason for the condition's last transition. - Producers of specific condition types may define expected values and meanings for this field, - and whether the values are considered a guaranteed API. - The value should be a CamelCase string. - This field may not be empty. - maxLength: 1024 - minLength: 1 - pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ - type: string - status: - description: status of the condition, one of True, False, Unknown. - enum: - - "True" - - "False" - - Unknown - type: string - type: - description: type of condition in CamelCase or in foo.example.com/CamelCase. - maxLength: 316 - pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ - type: string - required: - - lastTransitionTime - - message - - reason - - status - - type - type: object - type: array - lastExecutionTime: - format: date-time - type: string - type: object - required: - - spec - type: object - served: true - storage: false - subresources: - status: {} ---- -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - labels: - app.kubernetes.io/component: crds - app.kubernetes.io/instance: kyverno - app.kubernetes.io/managed-by: Helm - app.kubernetes.io/part-of: kyverno-crds - app.kubernetes.io/version: 3.5.1 - helm.sh/chart: crds-3.5.1 - annotations: - controller-gen.kubebuilder.io/version: v0.17.3 - name: clustercleanuppolicies.kyverno.io -spec: - group: kyverno.io - names: - categories: - - kyverno - kind: ClusterCleanupPolicy - listKind: ClusterCleanupPolicyList - plural: clustercleanuppolicies - shortNames: - - ccleanpol - singular: clustercleanuppolicy - scope: Cluster - versions: - - additionalPrinterColumns: - - jsonPath: .spec.schedule - name: Schedule - type: string - - jsonPath: .metadata.creationTimestamp - name: Age - type: date - name: v2 - schema: - openAPIV3Schema: - description: ClusterCleanupPolicy defines rule for resource cleanup. - properties: - apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - type: string - kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - metadata: - type: object - spec: - description: Spec declares policy behaviors. - properties: - conditions: - description: Conditions defines the conditions used to select the - resources which will be cleaned up. - properties: - all: - description: |- - AllConditions enable variable-based conditional rule execution. This is useful for - finer control of when an rule is applied. A condition can reference object data - using JMESPath notation. - Here, all of the conditions need to pass. - items: - properties: - key: - description: Key is the context entry (using JMESPath) for - conditional rule evaluation. - x-kubernetes-preserve-unknown-fields: true - message: - description: Message is an optional display message - type: string - operator: - description: |- - Operator is the conditional operation to perform. Valid operators are: - Equals, NotEquals, In, AnyIn, AllIn, NotIn, AnyNotIn, AllNotIn, GreaterThanOrEquals, - GreaterThan, LessThanOrEquals, LessThan, DurationGreaterThanOrEquals, DurationGreaterThan, - DurationLessThanOrEquals, DurationLessThan - enum: - - Equals - - NotEquals - - AnyIn - - AllIn - - AnyNotIn - - AllNotIn - - GreaterThanOrEquals - - GreaterThan - - LessThanOrEquals - - LessThan - - DurationGreaterThanOrEquals - - DurationGreaterThan - - DurationLessThanOrEquals - - DurationLessThan - type: string - value: - description: |- - Value is the conditional value, or set of values. The values can be fixed set - or can be variables declared using JMESPath. - x-kubernetes-preserve-unknown-fields: true - type: object - type: array - any: - description: |- - AnyConditions enable variable-based conditional rule execution. This is useful for - finer control of when an rule is applied. A condition can reference object data - using JMESPath notation. - Here, at least one of the conditions need to pass. - items: - properties: - key: - description: Key is the context entry (using JMESPath) for - conditional rule evaluation. - x-kubernetes-preserve-unknown-fields: true - message: - description: Message is an optional display message - type: string - operator: - description: |- - Operator is the conditional operation to perform. Valid operators are: - Equals, NotEquals, In, AnyIn, AllIn, NotIn, AnyNotIn, AllNotIn, GreaterThanOrEquals, - GreaterThan, LessThanOrEquals, LessThan, DurationGreaterThanOrEquals, DurationGreaterThan, - DurationLessThanOrEquals, DurationLessThan - enum: - - Equals - - NotEquals - - AnyIn - - AllIn - - AnyNotIn - - AllNotIn - - GreaterThanOrEquals - - GreaterThan - - LessThanOrEquals - - LessThan - - DurationGreaterThanOrEquals - - DurationGreaterThan - - DurationLessThanOrEquals - - DurationLessThan - type: string - value: - description: |- - Value is the conditional value, or set of values. The values can be fixed set - or can be variables declared using JMESPath. - x-kubernetes-preserve-unknown-fields: true - type: object - type: array - type: object - context: - description: Context defines variables and data sources that can be - used during rule execution. - items: - description: |- - ContextEntry adds variables and data sources to a rule Context. Either a - ConfigMap reference or a APILookup must be provided. - oneOf: - - required: - - configMap - - required: - - apiCall - - required: - - imageRegistry - - required: - - variable - - required: - - globalReference - properties: - apiCall: - description: |- - APICall is an HTTP request to the Kubernetes API server, or other JSON web service. - The data returned is stored in the context with the name for the context entry. - properties: - data: - description: |- - The data object specifies the POST data sent to the server. - Only applicable when the method field is set to POST. - items: - description: RequestData contains the HTTP POST data - properties: - key: - description: Key is a unique identifier for the data - value - type: string - value: - description: Value is the data value - x-kubernetes-preserve-unknown-fields: true - required: - - key - - value - type: object - type: array - default: - description: |- - Default is an optional arbitrary JSON object that the context - value is set to, if the apiCall returns error. - x-kubernetes-preserve-unknown-fields: true - jmesPath: - description: |- - JMESPath is an optional JSON Match Expression that can be used to - transform the JSON response returned from the server. For example - a JMESPath of "items | length(@)" applied to the API server response - for the URLPath "/apis/apps/v1/deployments" will return the total count - of deployments across all namespaces. - type: string - method: - default: GET - description: Method is the HTTP request type (GET or POST). - Defaults to GET. - enum: - - GET - - POST - type: string - service: - description: |- - Service is an API call to a JSON web service. - This is used for non-Kubernetes API server calls. - It's mutually exclusive with the URLPath field. - properties: - caBundle: - description: |- - CABundle is a PEM encoded CA bundle which will be used to validate - the server certificate. - type: string - headers: - description: Headers is a list of optional HTTP headers - to be included in the request. - items: - properties: - key: - description: Key is the header key - type: string - value: - description: Value is the header value - type: string - required: - - key - - value - type: object - type: array - url: - description: |- - URL is the JSON web service URL. A typical form is - `https://{service}.{namespace}:{port}/{path}`. - type: string - required: - - url - type: object - urlPath: - description: |- - URLPath is the URL path to be used in the HTTP GET or POST request to the - Kubernetes API server (e.g. "/api/v1/namespaces" or "/apis/apps/v1/deployments"). - The format required is the same format used by the `kubectl get --raw` command. - See https://kyverno.io/docs/writing-policies/external-data-sources/#variables-from-kubernetes-api-server-calls - for details. - It's mutually exclusive with the Service field. - type: string - type: object - configMap: - description: ConfigMap is the ConfigMap reference. - properties: - name: - description: Name is the ConfigMap name. - type: string - namespace: - description: Namespace is the ConfigMap namespace. - type: string - required: - - name - type: object - globalReference: - description: GlobalContextEntryReference is a reference to a - cached global context entry. - properties: - jmesPath: - description: |- - JMESPath is an optional JSON Match Expression that can be used to - transform the JSON response returned from the server. For example - a JMESPath of "items | length(@)" applied to the API server response - for the URLPath "/apis/apps/v1/deployments" will return the total count - of deployments across all namespaces. - type: string - name: - description: Name of the global context entry - type: string - required: - - name - type: object - imageRegistry: - description: |- - ImageRegistry defines requests to an OCI/Docker V2 registry to fetch image - details. - properties: - imageRegistryCredentials: - description: ImageRegistryCredentials provides credentials - that will be used for authentication with registry - properties: - allowInsecureRegistry: - description: AllowInsecureRegistry allows insecure access - to a registry. - type: boolean - providers: - description: |- - Providers specifies a list of OCI Registry names, whose authentication providers are provided. - It can be of one of these values: default,google,azure,amazon,github. - items: - description: ImageRegistryCredentialsProvidersType - provides the list of credential providers required. - enum: - - default - - amazon - - azure - - google - - github - type: string - type: array - secrets: - description: |- - Secrets specifies a list of secrets that are provided for credentials. - Secrets must live in the Kyverno namespace. - items: - type: string - type: array - type: object - jmesPath: - description: |- - JMESPath is an optional JSON Match Expression that can be used to - transform the ImageData struct returned as a result of processing - the image reference. - type: string - reference: - description: |- - Reference is image reference to a container image in the registry. - Example: ghcr.io/kyverno/kyverno:latest - type: string - required: - - reference - type: object - name: - description: Name is the variable name. - type: string - variable: - description: Variable defines an arbitrary JMESPath context - variable that can be defined inline. - properties: - default: - description: |- - Default is an optional arbitrary JSON object that the variable may take if the JMESPath - expression evaluates to nil - x-kubernetes-preserve-unknown-fields: true - jmesPath: - description: |- - JMESPath is an optional JMESPath Expression that can be used to - transform the variable. - type: string - value: - description: Value is any arbitrary JSON object representable - in YAML or JSON form. - x-kubernetes-preserve-unknown-fields: true - type: object - required: - - name - type: object - type: array - deletionPropagationPolicy: - description: DeletionPropagationPolicy defines how resources will - be deleted (Foreground, Background, Orphan). - enum: - - Foreground - - Background - - Orphan - type: string - exclude: - description: |- - ExcludeResources defines when cleanuppolicy should not be applied. The exclude - criteria can include resource information (e.g. kind, name, namespace, labels) - and admission review request information like the name or role. - not: - required: - - any - - all - properties: - all: - description: All allows specifying resources which will be ANDed - items: - description: ResourceFilter allow users to "AND" or "OR" between - resources - properties: - clusterRoles: - description: ClusterRoles is the list of cluster-wide role - names for the user. - items: - type: string - type: array - resources: - description: ResourceDescription contains information about - the resource being created or modified. - not: - required: - - name - - names - properties: - annotations: - additionalProperties: - type: string - description: |- - Annotations is a map of annotations (key-value pairs of type string). Annotation keys - and values support the wildcard characters "*" (matches zero or many characters) and - "?" (matches at least one character). - type: object - kinds: - description: Kinds is a list of resource kinds. - items: - type: string - type: array - name: - description: |- - Name is the name of the resource. The name supports wildcard characters - "*" (matches zero or many characters) and "?" (at least one character). - NOTE: "Name" is being deprecated in favor of "Names". - type: string - names: - description: |- - Names are the names of the resources. Each name supports wildcard characters - "*" (matches zero or many characters) and "?" (at least one character). - items: - type: string - type: array - namespaceSelector: - description: |- - NamespaceSelector is a label selector for the resource namespace. Label keys and values - in `matchLabels` support the wildcard characters `*` (matches zero or many characters) - and `?` (matches one character).Wildcards allows writing label selectors like - ["storage.k8s.io/*": "*"]. Note that using ["*" : "*"] matches any key and value but - does not match an empty label set. - properties: - matchExpressions: - description: matchExpressions is a list of label - selector requirements. The requirements are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key that the - selector applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - namespaces: - description: |- - Namespaces is a list of namespaces names. Each name supports wildcard characters - "*" (matches zero or many characters) and "?" (at least one character). - items: - type: string - type: array - operations: - description: Operations can contain values ["CREATE, - "UPDATE", "CONNECT", "DELETE"], which are used to - match a specific action. - items: - description: AdmissionOperation can have one of the - values CREATE, UPDATE, CONNECT, DELETE, which are - used to match a specific action. - enum: - - CREATE - - CONNECT - - UPDATE - - DELETE - type: string - type: array - selector: - description: |- - Selector is a label selector. Label keys and values in `matchLabels` support the wildcard - characters `*` (matches zero or many characters) and `?` (matches one character). - Wildcards allows writing label selectors like ["storage.k8s.io/*": "*"]. Note that - using ["*" : "*"] matches any key and value but does not match an empty label set. - properties: - matchExpressions: - description: matchExpressions is a list of label - selector requirements. The requirements are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key that the - selector applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - type: object - roles: - description: Roles is the list of namespaced role names - for the user. - items: - type: string - type: array - subjects: - description: Subjects is the list of subject names like - users, user groups, and service accounts. - items: - description: |- - Subject contains a reference to the object or user identities a role binding applies to. This can either hold a direct API object reference, - or a value for non-objects such as user and group names. - properties: - apiGroup: - description: |- - APIGroup holds the API group of the referenced subject. - Defaults to "" for ServiceAccount subjects. - Defaults to "rbac.authorization.k8s.io" for User and Group subjects. - type: string - kind: - description: |- - Kind of object being referenced. Values defined by this API group are "User", "Group", and "ServiceAccount". - If the Authorizer does not recognized the kind value, the Authorizer should report an error. - type: string - name: - description: Name of the object being referenced. - type: string - namespace: - description: |- - Namespace of the referenced object. If the object kind is non-namespace, such as "User" or "Group", and this value is not empty - the Authorizer should report an error. - type: string - required: - - kind - - name - type: object - x-kubernetes-map-type: atomic - type: array - type: object - type: array - any: - description: Any allows specifying resources which will be ORed - items: - description: ResourceFilter allow users to "AND" or "OR" between - resources - properties: - clusterRoles: - description: ClusterRoles is the list of cluster-wide role - names for the user. - items: - type: string - type: array - resources: - description: ResourceDescription contains information about - the resource being created or modified. - not: - required: - - name - - names - properties: - annotations: - additionalProperties: - type: string - description: |- - Annotations is a map of annotations (key-value pairs of type string). Annotation keys - and values support the wildcard characters "*" (matches zero or many characters) and - "?" (matches at least one character). - type: object - kinds: - description: Kinds is a list of resource kinds. - items: - type: string - type: array - name: - description: |- - Name is the name of the resource. The name supports wildcard characters - "*" (matches zero or many characters) and "?" (at least one character). - NOTE: "Name" is being deprecated in favor of "Names". - type: string - names: - description: |- - Names are the names of the resources. Each name supports wildcard characters - "*" (matches zero or many characters) and "?" (at least one character). - items: - type: string - type: array - namespaceSelector: - description: |- - NamespaceSelector is a label selector for the resource namespace. Label keys and values - in `matchLabels` support the wildcard characters `*` (matches zero or many characters) - and `?` (matches one character).Wildcards allows writing label selectors like - ["storage.k8s.io/*": "*"]. Note that using ["*" : "*"] matches any key and value but - does not match an empty label set. - properties: - matchExpressions: - description: matchExpressions is a list of label - selector requirements. The requirements are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key that the - selector applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - namespaces: - description: |- - Namespaces is a list of namespaces names. Each name supports wildcard characters - "*" (matches zero or many characters) and "?" (at least one character). - items: - type: string - type: array - operations: - description: Operations can contain values ["CREATE, - "UPDATE", "CONNECT", "DELETE"], which are used to - match a specific action. - items: - description: AdmissionOperation can have one of the - values CREATE, UPDATE, CONNECT, DELETE, which are - used to match a specific action. - enum: - - CREATE - - CONNECT - - UPDATE - - DELETE - type: string - type: array - selector: - description: |- - Selector is a label selector. Label keys and values in `matchLabels` support the wildcard - characters `*` (matches zero or many characters) and `?` (matches one character). - Wildcards allows writing label selectors like ["storage.k8s.io/*": "*"]. Note that - using ["*" : "*"] matches any key and value but does not match an empty label set. - properties: - matchExpressions: - description: matchExpressions is a list of label - selector requirements. The requirements are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key that the - selector applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - type: object - roles: - description: Roles is the list of namespaced role names - for the user. - items: - type: string - type: array - subjects: - description: Subjects is the list of subject names like - users, user groups, and service accounts. - items: - description: |- - Subject contains a reference to the object or user identities a role binding applies to. This can either hold a direct API object reference, - or a value for non-objects such as user and group names. - properties: - apiGroup: - description: |- - APIGroup holds the API group of the referenced subject. - Defaults to "" for ServiceAccount subjects. - Defaults to "rbac.authorization.k8s.io" for User and Group subjects. - type: string - kind: - description: |- - Kind of object being referenced. Values defined by this API group are "User", "Group", and "ServiceAccount". - If the Authorizer does not recognized the kind value, the Authorizer should report an error. - type: string - name: - description: Name of the object being referenced. - type: string - namespace: - description: |- - Namespace of the referenced object. If the object kind is non-namespace, such as "User" or "Group", and this value is not empty - the Authorizer should report an error. - type: string - required: - - kind - - name - type: object - x-kubernetes-map-type: atomic - type: array - type: object - type: array - type: object - match: - description: |- - MatchResources defines when cleanuppolicy should be applied. The match - criteria can include resource information (e.g. kind, name, namespace, labels) - and admission review request information like the user name or role. - At least one kind is required. - not: - required: - - any - - all - properties: - all: - description: All allows specifying resources which will be ANDed - items: - description: ResourceFilter allow users to "AND" or "OR" between - resources - properties: - clusterRoles: - description: ClusterRoles is the list of cluster-wide role - names for the user. - items: - type: string - type: array - resources: - description: ResourceDescription contains information about - the resource being created or modified. - not: - required: - - name - - names - properties: - annotations: - additionalProperties: - type: string - description: |- - Annotations is a map of annotations (key-value pairs of type string). Annotation keys - and values support the wildcard characters "*" (matches zero or many characters) and - "?" (matches at least one character). - type: object - kinds: - description: Kinds is a list of resource kinds. - items: - type: string - type: array - name: - description: |- - Name is the name of the resource. The name supports wildcard characters - "*" (matches zero or many characters) and "?" (at least one character). - NOTE: "Name" is being deprecated in favor of "Names". - type: string - names: - description: |- - Names are the names of the resources. Each name supports wildcard characters - "*" (matches zero or many characters) and "?" (at least one character). - items: - type: string - type: array - namespaceSelector: - description: |- - NamespaceSelector is a label selector for the resource namespace. Label keys and values - in `matchLabels` support the wildcard characters `*` (matches zero or many characters) - and `?` (matches one character).Wildcards allows writing label selectors like - ["storage.k8s.io/*": "*"]. Note that using ["*" : "*"] matches any key and value but - does not match an empty label set. - properties: - matchExpressions: - description: matchExpressions is a list of label - selector requirements. The requirements are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key that the - selector applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - namespaces: - description: |- - Namespaces is a list of namespaces names. Each name supports wildcard characters - "*" (matches zero or many characters) and "?" (at least one character). - items: - type: string - type: array - operations: - description: Operations can contain values ["CREATE, - "UPDATE", "CONNECT", "DELETE"], which are used to - match a specific action. - items: - description: AdmissionOperation can have one of the - values CREATE, UPDATE, CONNECT, DELETE, which are - used to match a specific action. - enum: - - CREATE - - CONNECT - - UPDATE - - DELETE - type: string - type: array - selector: - description: |- - Selector is a label selector. Label keys and values in `matchLabels` support the wildcard - characters `*` (matches zero or many characters) and `?` (matches one character). - Wildcards allows writing label selectors like ["storage.k8s.io/*": "*"]. Note that - using ["*" : "*"] matches any key and value but does not match an empty label set. - properties: - matchExpressions: - description: matchExpressions is a list of label - selector requirements. The requirements are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key that the - selector applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - type: object - roles: - description: Roles is the list of namespaced role names - for the user. - items: - type: string - type: array - subjects: - description: Subjects is the list of subject names like - users, user groups, and service accounts. - items: - description: |- - Subject contains a reference to the object or user identities a role binding applies to. This can either hold a direct API object reference, - or a value for non-objects such as user and group names. - properties: - apiGroup: - description: |- - APIGroup holds the API group of the referenced subject. - Defaults to "" for ServiceAccount subjects. - Defaults to "rbac.authorization.k8s.io" for User and Group subjects. - type: string - kind: - description: |- - Kind of object being referenced. Values defined by this API group are "User", "Group", and "ServiceAccount". - If the Authorizer does not recognized the kind value, the Authorizer should report an error. - type: string - name: - description: Name of the object being referenced. - type: string - namespace: - description: |- - Namespace of the referenced object. If the object kind is non-namespace, such as "User" or "Group", and this value is not empty - the Authorizer should report an error. - type: string - required: - - kind - - name - type: object - x-kubernetes-map-type: atomic - type: array - type: object - type: array - any: - description: Any allows specifying resources which will be ORed - items: - description: ResourceFilter allow users to "AND" or "OR" between - resources - properties: - clusterRoles: - description: ClusterRoles is the list of cluster-wide role - names for the user. - items: - type: string - type: array - resources: - description: ResourceDescription contains information about - the resource being created or modified. - not: - required: - - name - - names - properties: - annotations: - additionalProperties: - type: string - description: |- - Annotations is a map of annotations (key-value pairs of type string). Annotation keys - and values support the wildcard characters "*" (matches zero or many characters) and - "?" (matches at least one character). - type: object - kinds: - description: Kinds is a list of resource kinds. - items: - type: string - type: array - name: - description: |- - Name is the name of the resource. The name supports wildcard characters - "*" (matches zero or many characters) and "?" (at least one character). - NOTE: "Name" is being deprecated in favor of "Names". - type: string - names: - description: |- - Names are the names of the resources. Each name supports wildcard characters - "*" (matches zero or many characters) and "?" (at least one character). - items: - type: string - type: array - namespaceSelector: - description: |- - NamespaceSelector is a label selector for the resource namespace. Label keys and values - in `matchLabels` support the wildcard characters `*` (matches zero or many characters) - and `?` (matches one character).Wildcards allows writing label selectors like - ["storage.k8s.io/*": "*"]. Note that using ["*" : "*"] matches any key and value but - does not match an empty label set. - properties: - matchExpressions: - description: matchExpressions is a list of label - selector requirements. The requirements are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key that the - selector applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - namespaces: - description: |- - Namespaces is a list of namespaces names. Each name supports wildcard characters - "*" (matches zero or many characters) and "?" (at least one character). - items: - type: string - type: array - operations: - description: Operations can contain values ["CREATE, - "UPDATE", "CONNECT", "DELETE"], which are used to - match a specific action. - items: - description: AdmissionOperation can have one of the - values CREATE, UPDATE, CONNECT, DELETE, which are - used to match a specific action. - enum: - - CREATE - - CONNECT - - UPDATE - - DELETE - type: string - type: array - selector: - description: |- - Selector is a label selector. Label keys and values in `matchLabels` support the wildcard - characters `*` (matches zero or many characters) and `?` (matches one character). - Wildcards allows writing label selectors like ["storage.k8s.io/*": "*"]. Note that - using ["*" : "*"] matches any key and value but does not match an empty label set. - properties: - matchExpressions: - description: matchExpressions is a list of label - selector requirements. The requirements are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key that the - selector applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - type: object - roles: - description: Roles is the list of namespaced role names - for the user. - items: - type: string - type: array - subjects: - description: Subjects is the list of subject names like - users, user groups, and service accounts. - items: - description: |- - Subject contains a reference to the object or user identities a role binding applies to. This can either hold a direct API object reference, - or a value for non-objects such as user and group names. - properties: - apiGroup: - description: |- - APIGroup holds the API group of the referenced subject. - Defaults to "" for ServiceAccount subjects. - Defaults to "rbac.authorization.k8s.io" for User and Group subjects. - type: string - kind: - description: |- - Kind of object being referenced. Values defined by this API group are "User", "Group", and "ServiceAccount". - If the Authorizer does not recognized the kind value, the Authorizer should report an error. - type: string - name: - description: Name of the object being referenced. - type: string - namespace: - description: |- - Namespace of the referenced object. If the object kind is non-namespace, such as "User" or "Group", and this value is not empty - the Authorizer should report an error. - type: string - required: - - kind - - name - type: object - x-kubernetes-map-type: atomic - type: array - type: object - type: array - type: object - schedule: - description: The schedule in Cron format - type: string - required: - - match - - schedule - type: object - status: - description: Status contains policy runtime data. - properties: - conditions: - items: - description: Condition contains details for one aspect of the current - state of this API Resource. - properties: - lastTransitionTime: - description: |- - lastTransitionTime is the last time the condition transitioned from one status to another. - This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable. - format: date-time - type: string - message: - description: |- - message is a human readable message indicating details about the transition. - This may be an empty string. - maxLength: 32768 - type: string - observedGeneration: - description: |- - observedGeneration represents the .metadata.generation that the condition was set based upon. - For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date - with respect to the current state of the instance. - format: int64 - minimum: 0 - type: integer - reason: - description: |- - reason contains a programmatic identifier indicating the reason for the condition's last transition. - Producers of specific condition types may define expected values and meanings for this field, - and whether the values are considered a guaranteed API. - The value should be a CamelCase string. - This field may not be empty. - maxLength: 1024 - minLength: 1 - pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ - type: string - status: - description: status of the condition, one of True, False, Unknown. - enum: - - "True" - - "False" - - Unknown - type: string - type: - description: type of condition in CamelCase or in foo.example.com/CamelCase. - maxLength: 316 - pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ - type: string - required: - - lastTransitionTime - - message - - reason - - status - - type - type: object - type: array - lastExecutionTime: - format: date-time - type: string - type: object - required: - - spec - type: object - served: true - storage: true - subresources: - status: {} - - additionalPrinterColumns: - - jsonPath: .spec.schedule - name: Schedule - type: string - - jsonPath: .metadata.creationTimestamp - name: Age - type: date - deprecated: true - name: v2beta1 - schema: - openAPIV3Schema: - description: ClusterCleanupPolicy defines rule for resource cleanup. - properties: - apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - type: string - kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - metadata: - type: object - spec: - description: Spec declares policy behaviors. - properties: - conditions: - description: Conditions defines the conditions used to select the - resources which will be cleaned up. - properties: - all: - description: |- - AllConditions enable variable-based conditional rule execution. This is useful for - finer control of when an rule is applied. A condition can reference object data - using JMESPath notation. - Here, all of the conditions need to pass. - items: - properties: - key: - description: Key is the context entry (using JMESPath) for - conditional rule evaluation. - x-kubernetes-preserve-unknown-fields: true - message: - description: Message is an optional display message - type: string - operator: - description: |- - Operator is the conditional operation to perform. Valid operators are: - Equals, NotEquals, In, AnyIn, AllIn, NotIn, AnyNotIn, AllNotIn, GreaterThanOrEquals, - GreaterThan, LessThanOrEquals, LessThan, DurationGreaterThanOrEquals, DurationGreaterThan, - DurationLessThanOrEquals, DurationLessThan - enum: - - Equals - - NotEquals - - AnyIn - - AllIn - - AnyNotIn - - AllNotIn - - GreaterThanOrEquals - - GreaterThan - - LessThanOrEquals - - LessThan - - DurationGreaterThanOrEquals - - DurationGreaterThan - - DurationLessThanOrEquals - - DurationLessThan - type: string - value: - description: |- - Value is the conditional value, or set of values. The values can be fixed set - or can be variables declared using JMESPath. - x-kubernetes-preserve-unknown-fields: true - type: object - type: array - any: - description: |- - AnyConditions enable variable-based conditional rule execution. This is useful for - finer control of when an rule is applied. A condition can reference object data - using JMESPath notation. - Here, at least one of the conditions need to pass. - items: - properties: - key: - description: Key is the context entry (using JMESPath) for - conditional rule evaluation. - x-kubernetes-preserve-unknown-fields: true - message: - description: Message is an optional display message - type: string - operator: - description: |- - Operator is the conditional operation to perform. Valid operators are: - Equals, NotEquals, In, AnyIn, AllIn, NotIn, AnyNotIn, AllNotIn, GreaterThanOrEquals, - GreaterThan, LessThanOrEquals, LessThan, DurationGreaterThanOrEquals, DurationGreaterThan, - DurationLessThanOrEquals, DurationLessThan - enum: - - Equals - - NotEquals - - AnyIn - - AllIn - - AnyNotIn - - AllNotIn - - GreaterThanOrEquals - - GreaterThan - - LessThanOrEquals - - LessThan - - DurationGreaterThanOrEquals - - DurationGreaterThan - - DurationLessThanOrEquals - - DurationLessThan - type: string - value: - description: |- - Value is the conditional value, or set of values. The values can be fixed set - or can be variables declared using JMESPath. - x-kubernetes-preserve-unknown-fields: true - type: object - type: array - type: object - context: - description: Context defines variables and data sources that can be - used during rule execution. - items: - description: |- - ContextEntry adds variables and data sources to a rule Context. Either a - ConfigMap reference or a APILookup must be provided. - oneOf: - - required: - - configMap - - required: - - apiCall - - required: - - imageRegistry - - required: - - variable - - required: - - globalReference - properties: - apiCall: - description: |- - APICall is an HTTP request to the Kubernetes API server, or other JSON web service. - The data returned is stored in the context with the name for the context entry. - properties: - data: - description: |- - The data object specifies the POST data sent to the server. - Only applicable when the method field is set to POST. - items: - description: RequestData contains the HTTP POST data - properties: - key: - description: Key is a unique identifier for the data - value - type: string - value: - description: Value is the data value - x-kubernetes-preserve-unknown-fields: true - required: - - key - - value - type: object - type: array - default: - description: |- - Default is an optional arbitrary JSON object that the context - value is set to, if the apiCall returns error. - x-kubernetes-preserve-unknown-fields: true - jmesPath: - description: |- - JMESPath is an optional JSON Match Expression that can be used to - transform the JSON response returned from the server. For example - a JMESPath of "items | length(@)" applied to the API server response - for the URLPath "/apis/apps/v1/deployments" will return the total count - of deployments across all namespaces. - type: string - method: - default: GET - description: Method is the HTTP request type (GET or POST). - Defaults to GET. - enum: - - GET - - POST - type: string - service: - description: |- - Service is an API call to a JSON web service. - This is used for non-Kubernetes API server calls. - It's mutually exclusive with the URLPath field. - properties: - caBundle: - description: |- - CABundle is a PEM encoded CA bundle which will be used to validate - the server certificate. - type: string - headers: - description: Headers is a list of optional HTTP headers - to be included in the request. - items: - properties: - key: - description: Key is the header key - type: string - value: - description: Value is the header value - type: string - required: - - key - - value - type: object - type: array - url: - description: |- - URL is the JSON web service URL. A typical form is - `https://{service}.{namespace}:{port}/{path}`. - type: string - required: - - url - type: object - urlPath: - description: |- - URLPath is the URL path to be used in the HTTP GET or POST request to the - Kubernetes API server (e.g. "/api/v1/namespaces" or "/apis/apps/v1/deployments"). - The format required is the same format used by the `kubectl get --raw` command. - See https://kyverno.io/docs/writing-policies/external-data-sources/#variables-from-kubernetes-api-server-calls - for details. - It's mutually exclusive with the Service field. - type: string - type: object - configMap: - description: ConfigMap is the ConfigMap reference. - properties: - name: - description: Name is the ConfigMap name. - type: string - namespace: - description: Namespace is the ConfigMap namespace. - type: string - required: - - name - type: object - globalReference: - description: GlobalContextEntryReference is a reference to a - cached global context entry. - properties: - jmesPath: - description: |- - JMESPath is an optional JSON Match Expression that can be used to - transform the JSON response returned from the server. For example - a JMESPath of "items | length(@)" applied to the API server response - for the URLPath "/apis/apps/v1/deployments" will return the total count - of deployments across all namespaces. - type: string - name: - description: Name of the global context entry - type: string - required: - - name - type: object - imageRegistry: - description: |- - ImageRegistry defines requests to an OCI/Docker V2 registry to fetch image - details. - properties: - imageRegistryCredentials: - description: ImageRegistryCredentials provides credentials - that will be used for authentication with registry - properties: - allowInsecureRegistry: - description: AllowInsecureRegistry allows insecure access - to a registry. - type: boolean - providers: - description: |- - Providers specifies a list of OCI Registry names, whose authentication providers are provided. - It can be of one of these values: default,google,azure,amazon,github. - items: - description: ImageRegistryCredentialsProvidersType - provides the list of credential providers required. - enum: - - default - - amazon - - azure - - google - - github - type: string - type: array - secrets: - description: |- - Secrets specifies a list of secrets that are provided for credentials. - Secrets must live in the Kyverno namespace. - items: - type: string - type: array - type: object - jmesPath: - description: |- - JMESPath is an optional JSON Match Expression that can be used to - transform the ImageData struct returned as a result of processing - the image reference. - type: string - reference: - description: |- - Reference is image reference to a container image in the registry. - Example: ghcr.io/kyverno/kyverno:latest - type: string - required: - - reference - type: object - name: - description: Name is the variable name. - type: string - variable: - description: Variable defines an arbitrary JMESPath context - variable that can be defined inline. - properties: - default: - description: |- - Default is an optional arbitrary JSON object that the variable may take if the JMESPath - expression evaluates to nil - x-kubernetes-preserve-unknown-fields: true - jmesPath: - description: |- - JMESPath is an optional JMESPath Expression that can be used to - transform the variable. - type: string - value: - description: Value is any arbitrary JSON object representable - in YAML or JSON form. - x-kubernetes-preserve-unknown-fields: true - type: object - required: - - name - type: object - type: array - deletionPropagationPolicy: - description: DeletionPropagationPolicy defines how resources will - be deleted (Foreground, Background, Orphan). - enum: - - Foreground - - Background - - Orphan - type: string - exclude: - description: |- - ExcludeResources defines when cleanuppolicy should not be applied. The exclude - criteria can include resource information (e.g. kind, name, namespace, labels) - and admission review request information like the name or role. - not: - required: - - any - - all - properties: - all: - description: All allows specifying resources which will be ANDed - items: - description: ResourceFilter allow users to "AND" or "OR" between - resources - properties: - clusterRoles: - description: ClusterRoles is the list of cluster-wide role - names for the user. - items: - type: string - type: array - resources: - description: ResourceDescription contains information about - the resource being created or modified. - not: - required: - - name - - names - properties: - annotations: - additionalProperties: - type: string - description: |- - Annotations is a map of annotations (key-value pairs of type string). Annotation keys - and values support the wildcard characters "*" (matches zero or many characters) and - "?" (matches at least one character). - type: object - kinds: - description: Kinds is a list of resource kinds. - items: - type: string - type: array - name: - description: |- - Name is the name of the resource. The name supports wildcard characters - "*" (matches zero or many characters) and "?" (at least one character). - NOTE: "Name" is being deprecated in favor of "Names". - type: string - names: - description: |- - Names are the names of the resources. Each name supports wildcard characters - "*" (matches zero or many characters) and "?" (at least one character). - items: - type: string - type: array - namespaceSelector: - description: |- - NamespaceSelector is a label selector for the resource namespace. Label keys and values - in `matchLabels` support the wildcard characters `*` (matches zero or many characters) - and `?` (matches one character).Wildcards allows writing label selectors like - ["storage.k8s.io/*": "*"]. Note that using ["*" : "*"] matches any key and value but - does not match an empty label set. - properties: - matchExpressions: - description: matchExpressions is a list of label - selector requirements. The requirements are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key that the - selector applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - namespaces: - description: |- - Namespaces is a list of namespaces names. Each name supports wildcard characters - "*" (matches zero or many characters) and "?" (at least one character). - items: - type: string - type: array - operations: - description: Operations can contain values ["CREATE, - "UPDATE", "CONNECT", "DELETE"], which are used to - match a specific action. - items: - description: AdmissionOperation can have one of the - values CREATE, UPDATE, CONNECT, DELETE, which are - used to match a specific action. - enum: - - CREATE - - CONNECT - - UPDATE - - DELETE - type: string - type: array - selector: - description: |- - Selector is a label selector. Label keys and values in `matchLabels` support the wildcard - characters `*` (matches zero or many characters) and `?` (matches one character). - Wildcards allows writing label selectors like ["storage.k8s.io/*": "*"]. Note that - using ["*" : "*"] matches any key and value but does not match an empty label set. - properties: - matchExpressions: - description: matchExpressions is a list of label - selector requirements. The requirements are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key that the - selector applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - type: object - roles: - description: Roles is the list of namespaced role names - for the user. - items: - type: string - type: array - subjects: - description: Subjects is the list of subject names like - users, user groups, and service accounts. - items: - description: |- - Subject contains a reference to the object or user identities a role binding applies to. This can either hold a direct API object reference, - or a value for non-objects such as user and group names. - properties: - apiGroup: - description: |- - APIGroup holds the API group of the referenced subject. - Defaults to "" for ServiceAccount subjects. - Defaults to "rbac.authorization.k8s.io" for User and Group subjects. - type: string - kind: - description: |- - Kind of object being referenced. Values defined by this API group are "User", "Group", and "ServiceAccount". - If the Authorizer does not recognized the kind value, the Authorizer should report an error. - type: string - name: - description: Name of the object being referenced. - type: string - namespace: - description: |- - Namespace of the referenced object. If the object kind is non-namespace, such as "User" or "Group", and this value is not empty - the Authorizer should report an error. - type: string - required: - - kind - - name - type: object - x-kubernetes-map-type: atomic - type: array - type: object - type: array - any: - description: Any allows specifying resources which will be ORed - items: - description: ResourceFilter allow users to "AND" or "OR" between - resources - properties: - clusterRoles: - description: ClusterRoles is the list of cluster-wide role - names for the user. - items: - type: string - type: array - resources: - description: ResourceDescription contains information about - the resource being created or modified. - not: - required: - - name - - names - properties: - annotations: - additionalProperties: - type: string - description: |- - Annotations is a map of annotations (key-value pairs of type string). Annotation keys - and values support the wildcard characters "*" (matches zero or many characters) and - "?" (matches at least one character). - type: object - kinds: - description: Kinds is a list of resource kinds. - items: - type: string - type: array - name: - description: |- - Name is the name of the resource. The name supports wildcard characters - "*" (matches zero or many characters) and "?" (at least one character). - NOTE: "Name" is being deprecated in favor of "Names". - type: string - names: - description: |- - Names are the names of the resources. Each name supports wildcard characters - "*" (matches zero or many characters) and "?" (at least one character). - items: - type: string - type: array - namespaceSelector: - description: |- - NamespaceSelector is a label selector for the resource namespace. Label keys and values - in `matchLabels` support the wildcard characters `*` (matches zero or many characters) - and `?` (matches one character).Wildcards allows writing label selectors like - ["storage.k8s.io/*": "*"]. Note that using ["*" : "*"] matches any key and value but - does not match an empty label set. - properties: - matchExpressions: - description: matchExpressions is a list of label - selector requirements. The requirements are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key that the - selector applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - namespaces: - description: |- - Namespaces is a list of namespaces names. Each name supports wildcard characters - "*" (matches zero or many characters) and "?" (at least one character). - items: - type: string - type: array - operations: - description: Operations can contain values ["CREATE, - "UPDATE", "CONNECT", "DELETE"], which are used to - match a specific action. - items: - description: AdmissionOperation can have one of the - values CREATE, UPDATE, CONNECT, DELETE, which are - used to match a specific action. - enum: - - CREATE - - CONNECT - - UPDATE - - DELETE - type: string - type: array - selector: - description: |- - Selector is a label selector. Label keys and values in `matchLabels` support the wildcard - characters `*` (matches zero or many characters) and `?` (matches one character). - Wildcards allows writing label selectors like ["storage.k8s.io/*": "*"]. Note that - using ["*" : "*"] matches any key and value but does not match an empty label set. - properties: - matchExpressions: - description: matchExpressions is a list of label - selector requirements. The requirements are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key that the - selector applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - type: object - roles: - description: Roles is the list of namespaced role names - for the user. - items: - type: string - type: array - subjects: - description: Subjects is the list of subject names like - users, user groups, and service accounts. - items: - description: |- - Subject contains a reference to the object or user identities a role binding applies to. This can either hold a direct API object reference, - or a value for non-objects such as user and group names. - properties: - apiGroup: - description: |- - APIGroup holds the API group of the referenced subject. - Defaults to "" for ServiceAccount subjects. - Defaults to "rbac.authorization.k8s.io" for User and Group subjects. - type: string - kind: - description: |- - Kind of object being referenced. Values defined by this API group are "User", "Group", and "ServiceAccount". - If the Authorizer does not recognized the kind value, the Authorizer should report an error. - type: string - name: - description: Name of the object being referenced. - type: string - namespace: - description: |- - Namespace of the referenced object. If the object kind is non-namespace, such as "User" or "Group", and this value is not empty - the Authorizer should report an error. - type: string - required: - - kind - - name - type: object - x-kubernetes-map-type: atomic - type: array - type: object - type: array - type: object - match: - description: |- - MatchResources defines when cleanuppolicy should be applied. The match - criteria can include resource information (e.g. kind, name, namespace, labels) - and admission review request information like the user name or role. - At least one kind is required. - not: - required: - - any - - all - properties: - all: - description: All allows specifying resources which will be ANDed - items: - description: ResourceFilter allow users to "AND" or "OR" between - resources - properties: - clusterRoles: - description: ClusterRoles is the list of cluster-wide role - names for the user. - items: - type: string - type: array - resources: - description: ResourceDescription contains information about - the resource being created or modified. - not: - required: - - name - - names - properties: - annotations: - additionalProperties: - type: string - description: |- - Annotations is a map of annotations (key-value pairs of type string). Annotation keys - and values support the wildcard characters "*" (matches zero or many characters) and - "?" (matches at least one character). - type: object - kinds: - description: Kinds is a list of resource kinds. - items: - type: string - type: array - name: - description: |- - Name is the name of the resource. The name supports wildcard characters - "*" (matches zero or many characters) and "?" (at least one character). - NOTE: "Name" is being deprecated in favor of "Names". - type: string - names: - description: |- - Names are the names of the resources. Each name supports wildcard characters - "*" (matches zero or many characters) and "?" (at least one character). - items: - type: string - type: array - namespaceSelector: - description: |- - NamespaceSelector is a label selector for the resource namespace. Label keys and values - in `matchLabels` support the wildcard characters `*` (matches zero or many characters) - and `?` (matches one character).Wildcards allows writing label selectors like - ["storage.k8s.io/*": "*"]. Note that using ["*" : "*"] matches any key and value but - does not match an empty label set. - properties: - matchExpressions: - description: matchExpressions is a list of label - selector requirements. The requirements are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key that the - selector applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - namespaces: - description: |- - Namespaces is a list of namespaces names. Each name supports wildcard characters - "*" (matches zero or many characters) and "?" (at least one character). - items: - type: string - type: array - operations: - description: Operations can contain values ["CREATE, - "UPDATE", "CONNECT", "DELETE"], which are used to - match a specific action. - items: - description: AdmissionOperation can have one of the - values CREATE, UPDATE, CONNECT, DELETE, which are - used to match a specific action. - enum: - - CREATE - - CONNECT - - UPDATE - - DELETE - type: string - type: array - selector: - description: |- - Selector is a label selector. Label keys and values in `matchLabels` support the wildcard - characters `*` (matches zero or many characters) and `?` (matches one character). - Wildcards allows writing label selectors like ["storage.k8s.io/*": "*"]. Note that - using ["*" : "*"] matches any key and value but does not match an empty label set. - properties: - matchExpressions: - description: matchExpressions is a list of label - selector requirements. The requirements are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key that the - selector applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - type: object - roles: - description: Roles is the list of namespaced role names - for the user. - items: - type: string - type: array - subjects: - description: Subjects is the list of subject names like - users, user groups, and service accounts. - items: - description: |- - Subject contains a reference to the object or user identities a role binding applies to. This can either hold a direct API object reference, - or a value for non-objects such as user and group names. - properties: - apiGroup: - description: |- - APIGroup holds the API group of the referenced subject. - Defaults to "" for ServiceAccount subjects. - Defaults to "rbac.authorization.k8s.io" for User and Group subjects. - type: string - kind: - description: |- - Kind of object being referenced. Values defined by this API group are "User", "Group", and "ServiceAccount". - If the Authorizer does not recognized the kind value, the Authorizer should report an error. - type: string - name: - description: Name of the object being referenced. - type: string - namespace: - description: |- - Namespace of the referenced object. If the object kind is non-namespace, such as "User" or "Group", and this value is not empty - the Authorizer should report an error. - type: string - required: - - kind - - name - type: object - x-kubernetes-map-type: atomic - type: array - type: object - type: array - any: - description: Any allows specifying resources which will be ORed - items: - description: ResourceFilter allow users to "AND" or "OR" between - resources - properties: - clusterRoles: - description: ClusterRoles is the list of cluster-wide role - names for the user. - items: - type: string - type: array - resources: - description: ResourceDescription contains information about - the resource being created or modified. - not: - required: - - name - - names - properties: - annotations: - additionalProperties: - type: string - description: |- - Annotations is a map of annotations (key-value pairs of type string). Annotation keys - and values support the wildcard characters "*" (matches zero or many characters) and - "?" (matches at least one character). - type: object - kinds: - description: Kinds is a list of resource kinds. - items: - type: string - type: array - name: - description: |- - Name is the name of the resource. The name supports wildcard characters - "*" (matches zero or many characters) and "?" (at least one character). - NOTE: "Name" is being deprecated in favor of "Names". - type: string - names: - description: |- - Names are the names of the resources. Each name supports wildcard characters - "*" (matches zero or many characters) and "?" (at least one character). - items: - type: string - type: array - namespaceSelector: - description: |- - NamespaceSelector is a label selector for the resource namespace. Label keys and values - in `matchLabels` support the wildcard characters `*` (matches zero or many characters) - and `?` (matches one character).Wildcards allows writing label selectors like - ["storage.k8s.io/*": "*"]. Note that using ["*" : "*"] matches any key and value but - does not match an empty label set. - properties: - matchExpressions: - description: matchExpressions is a list of label - selector requirements. The requirements are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key that the - selector applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - namespaces: - description: |- - Namespaces is a list of namespaces names. Each name supports wildcard characters - "*" (matches zero or many characters) and "?" (at least one character). - items: - type: string - type: array - operations: - description: Operations can contain values ["CREATE, - "UPDATE", "CONNECT", "DELETE"], which are used to - match a specific action. - items: - description: AdmissionOperation can have one of the - values CREATE, UPDATE, CONNECT, DELETE, which are - used to match a specific action. - enum: - - CREATE - - CONNECT - - UPDATE - - DELETE - type: string - type: array - selector: - description: |- - Selector is a label selector. Label keys and values in `matchLabels` support the wildcard - characters `*` (matches zero or many characters) and `?` (matches one character). - Wildcards allows writing label selectors like ["storage.k8s.io/*": "*"]. Note that - using ["*" : "*"] matches any key and value but does not match an empty label set. - properties: - matchExpressions: - description: matchExpressions is a list of label - selector requirements. The requirements are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key that the - selector applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - type: object - roles: - description: Roles is the list of namespaced role names - for the user. - items: - type: string - type: array - subjects: - description: Subjects is the list of subject names like - users, user groups, and service accounts. - items: - description: |- - Subject contains a reference to the object or user identities a role binding applies to. This can either hold a direct API object reference, - or a value for non-objects such as user and group names. - properties: - apiGroup: - description: |- - APIGroup holds the API group of the referenced subject. - Defaults to "" for ServiceAccount subjects. - Defaults to "rbac.authorization.k8s.io" for User and Group subjects. - type: string - kind: - description: |- - Kind of object being referenced. Values defined by this API group are "User", "Group", and "ServiceAccount". - If the Authorizer does not recognized the kind value, the Authorizer should report an error. - type: string - name: - description: Name of the object being referenced. - type: string - namespace: - description: |- - Namespace of the referenced object. If the object kind is non-namespace, such as "User" or "Group", and this value is not empty - the Authorizer should report an error. - type: string - required: - - kind - - name - type: object - x-kubernetes-map-type: atomic - type: array - type: object - type: array - type: object - schedule: - description: The schedule in Cron format - type: string - required: - - match - - schedule - type: object - status: - description: Status contains policy runtime data. - properties: - conditions: - items: - description: Condition contains details for one aspect of the current - state of this API Resource. - properties: - lastTransitionTime: - description: |- - lastTransitionTime is the last time the condition transitioned from one status to another. - This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable. - format: date-time - type: string - message: - description: |- - message is a human readable message indicating details about the transition. - This may be an empty string. - maxLength: 32768 - type: string - observedGeneration: - description: |- - observedGeneration represents the .metadata.generation that the condition was set based upon. - For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date - with respect to the current state of the instance. - format: int64 - minimum: 0 - type: integer - reason: - description: |- - reason contains a programmatic identifier indicating the reason for the condition's last transition. - Producers of specific condition types may define expected values and meanings for this field, - and whether the values are considered a guaranteed API. - The value should be a CamelCase string. - This field may not be empty. - maxLength: 1024 - minLength: 1 - pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ - type: string - status: - description: status of the condition, one of True, False, Unknown. - enum: - - "True" - - "False" - - Unknown - type: string - type: - description: type of condition in CamelCase or in foo.example.com/CamelCase. - maxLength: 316 - pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ - type: string - required: - - lastTransitionTime - - message - - reason - - status - - type - type: object - type: array - lastExecutionTime: - format: date-time - type: string - type: object - required: - - spec - type: object - served: true - storage: false - subresources: - status: {} ---- -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - labels: - app.kubernetes.io/component: crds - app.kubernetes.io/instance: kyverno - app.kubernetes.io/managed-by: Helm - app.kubernetes.io/part-of: kyverno-crds - app.kubernetes.io/version: 3.5.1 - helm.sh/chart: crds-3.5.1 - annotations: - controller-gen.kubebuilder.io/version: v0.17.3 - name: clusterpolicies.kyverno.io -spec: - group: kyverno.io - names: - categories: - - kyverno - kind: ClusterPolicy - listKind: ClusterPolicyList - plural: clusterpolicies - shortNames: - - cpol - singular: clusterpolicy - scope: Cluster - versions: - - additionalPrinterColumns: - - jsonPath: .spec.admission - name: ADMISSION - type: boolean - - jsonPath: .spec.background - name: BACKGROUND - type: boolean - - jsonPath: .status.conditions[?(@.type == "Ready")].status - name: READY - type: string - - jsonPath: .metadata.creationTimestamp - name: AGE - type: date - - jsonPath: .spec.failurePolicy - name: FAILURE POLICY - priority: 1 - type: string - - jsonPath: .status.rulecount.validate - name: VALIDATE - priority: 1 - type: integer - - jsonPath: .status.rulecount.mutate - name: MUTATE - priority: 1 - type: integer - - jsonPath: .status.rulecount.generate - name: GENERATE - priority: 1 - type: integer - - jsonPath: .status.rulecount.verifyimages - name: VERIFY IMAGES - priority: 1 - type: integer - - jsonPath: .status.conditions[?(@.type == "Ready")].message - name: MESSAGE - type: string - name: v1 - schema: - openAPIV3Schema: - description: ClusterPolicy declares validation, mutation, and generation behaviors - for matching resources. - properties: - apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - type: string - kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - metadata: - type: object - spec: - description: Spec declares policy behaviors. - properties: - admission: - default: true - description: |- - Admission controls if rules are applied during admission. - Optional. Default value is "true". - type: boolean - applyRules: - description: |- - ApplyRules controls how rules in a policy are applied. Rule are processed in - the order of declaration. When set to `One` processing stops after a rule has - been applied i.e. the rule matches and results in a pass, fail, or error. When - set to `All` all rules in the policy are processed. The default is `All`. - enum: - - All - - One - type: string - background: - default: true - description: |- - Background controls if rules are applied to existing resources during a background scan. - Optional. Default value is "true". The value must be set to "false" if the policy rule - uses variables that are only available in the admission review request (e.g. user name). - type: boolean - emitWarning: - default: false - description: |- - EmitWarning enables API response warnings for mutate policy rules or validate policy rules with validationFailureAction set to Audit. - Enabling this option will extend admission request processing times. The default value is "false". - type: boolean - failurePolicy: - description: Deprecated, use failurePolicy under the webhookConfiguration - instead. - enum: - - Ignore - - Fail - type: string - generateExisting: - description: Deprecated, use generateExisting under the generate rule - instead - type: boolean - generateExistingOnPolicyUpdate: - description: Deprecated, use generateExisting instead - type: boolean - mutateExistingOnPolicyUpdate: - description: Deprecated, use mutateExistingOnPolicyUpdate under the - mutate rule instead - type: boolean - rules: - description: |- - Rules is a list of Rule instances. A Policy contains multiple rules and - each rule can validate, mutate, or generate resources. - items: - description: |- - Rule defines a validation, mutation, or generation control for matching resources. - Each rules contains a match declaration to select resources, and an optional exclude - declaration to specify which resources to exclude. - properties: - celPreconditions: - description: |- - CELPreconditions are used to determine if a policy rule should be applied by evaluating a - set of CEL conditions. It can only be used with the validate.cel subrule - items: - description: MatchCondition represents a condition which must - by fulfilled for a request to be sent to a webhook. - properties: - expression: - description: |- - Expression represents the expression which will be evaluated by CEL. Must evaluate to bool. - CEL expressions have access to the contents of the AdmissionRequest and Authorizer, organized into CEL variables: - - 'object' - The object from the incoming request. The value is null for DELETE requests. - 'oldObject' - The existing object. The value is null for CREATE requests. - 'request' - Attributes of the admission request(/pkg/apis/admission/types.go#AdmissionRequest). - 'authorizer' - A CEL Authorizer. May be used to perform authorization checks for the principal (user or service account) of the request. - See https://pkg.go.dev/k8s.io/apiserver/pkg/cel/library#Authz - 'authorizer.requestResource' - A CEL ResourceCheck constructed from the 'authorizer' and configured with the - request resource. - Documentation on CEL: https://kubernetes.io/docs/reference/using-api/cel/ - - Required. - type: string - name: - description: |- - Name is an identifier for this match condition, used for strategic merging of MatchConditions, - as well as providing an identifier for logging purposes. A good name should be descriptive of - the associated expression. - Name must be a qualified name consisting of alphanumeric characters, '-', '_' or '.', and - must start and end with an alphanumeric character (e.g. 'MyName', or 'my.name', or - '123-abc', regex used for validation is '([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9]') with an - optional DNS subdomain prefix and '/' (e.g. 'example.com/MyName') - - Required. - type: string - required: - - expression - - name - type: object - type: array - context: - description: Context defines variables and data sources that - can be used during rule execution. - items: - description: |- - ContextEntry adds variables and data sources to a rule Context. Either a - ConfigMap reference or a APILookup must be provided. - oneOf: - - required: - - configMap - - required: - - apiCall - - required: - - imageRegistry - - required: - - variable - - required: - - globalReference - properties: - apiCall: - description: |- - APICall is an HTTP request to the Kubernetes API server, or other JSON web service. - The data returned is stored in the context with the name for the context entry. - properties: - data: - description: |- - The data object specifies the POST data sent to the server. - Only applicable when the method field is set to POST. - items: - description: RequestData contains the HTTP POST - data - properties: - key: - description: Key is a unique identifier for - the data value - type: string - value: - description: Value is the data value - x-kubernetes-preserve-unknown-fields: true - required: - - key - - value - type: object - type: array - default: - description: |- - Default is an optional arbitrary JSON object that the context - value is set to, if the apiCall returns error. - x-kubernetes-preserve-unknown-fields: true - jmesPath: - description: |- - JMESPath is an optional JSON Match Expression that can be used to - transform the JSON response returned from the server. For example - a JMESPath of "items | length(@)" applied to the API server response - for the URLPath "/apis/apps/v1/deployments" will return the total count - of deployments across all namespaces. - type: string - method: - default: GET - description: Method is the HTTP request type (GET - or POST). Defaults to GET. - enum: - - GET - - POST - type: string - service: - description: |- - Service is an API call to a JSON web service. - This is used for non-Kubernetes API server calls. - It's mutually exclusive with the URLPath field. - properties: - caBundle: - description: |- - CABundle is a PEM encoded CA bundle which will be used to validate - the server certificate. - type: string - headers: - description: Headers is a list of optional HTTP - headers to be included in the request. - items: - properties: - key: - description: Key is the header key - type: string - value: - description: Value is the header value - type: string - required: - - key - - value - type: object - type: array - url: - description: |- - URL is the JSON web service URL. A typical form is - `https://{service}.{namespace}:{port}/{path}`. - type: string - required: - - url - type: object - urlPath: - description: |- - URLPath is the URL path to be used in the HTTP GET or POST request to the - Kubernetes API server (e.g. "/api/v1/namespaces" or "/apis/apps/v1/deployments"). - The format required is the same format used by the `kubectl get --raw` command. - See https://kyverno.io/docs/writing-policies/external-data-sources/#variables-from-kubernetes-api-server-calls - for details. - It's mutually exclusive with the Service field. - type: string - type: object - configMap: - description: ConfigMap is the ConfigMap reference. - properties: - name: - description: Name is the ConfigMap name. - type: string - namespace: - description: Namespace is the ConfigMap namespace. - type: string - required: - - name - type: object - globalReference: - description: GlobalContextEntryReference is a reference - to a cached global context entry. - properties: - jmesPath: - description: |- - JMESPath is an optional JSON Match Expression that can be used to - transform the JSON response returned from the server. For example - a JMESPath of "items | length(@)" applied to the API server response - for the URLPath "/apis/apps/v1/deployments" will return the total count - of deployments across all namespaces. - type: string - name: - description: Name of the global context entry - type: string - required: - - name - type: object - imageRegistry: - description: |- - ImageRegistry defines requests to an OCI/Docker V2 registry to fetch image - details. - properties: - imageRegistryCredentials: - description: ImageRegistryCredentials provides credentials - that will be used for authentication with registry - properties: - allowInsecureRegistry: - description: AllowInsecureRegistry allows insecure - access to a registry. - type: boolean - providers: - description: |- - Providers specifies a list of OCI Registry names, whose authentication providers are provided. - It can be of one of these values: default,google,azure,amazon,github. - items: - description: ImageRegistryCredentialsProvidersType - provides the list of credential providers - required. - enum: - - default - - amazon - - azure - - google - - github - type: string - type: array - secrets: - description: |- - Secrets specifies a list of secrets that are provided for credentials. - Secrets must live in the Kyverno namespace. - items: - type: string - type: array - type: object - jmesPath: - description: |- - JMESPath is an optional JSON Match Expression that can be used to - transform the ImageData struct returned as a result of processing - the image reference. - type: string - reference: - description: |- - Reference is image reference to a container image in the registry. - Example: ghcr.io/kyverno/kyverno:latest - type: string - required: - - reference - type: object - name: - description: Name is the variable name. - type: string - variable: - description: Variable defines an arbitrary JMESPath context - variable that can be defined inline. - properties: - default: - description: |- - Default is an optional arbitrary JSON object that the variable may take if the JMESPath - expression evaluates to nil - x-kubernetes-preserve-unknown-fields: true - jmesPath: - description: |- - JMESPath is an optional JMESPath Expression that can be used to - transform the variable. - type: string - value: - description: Value is any arbitrary JSON object representable - in YAML or JSON form. - x-kubernetes-preserve-unknown-fields: true - type: object - required: - - name - type: object - type: array - exclude: - description: |- - ExcludeResources defines when this policy rule should not be applied. The exclude - criteria can include resource information (e.g. kind, name, namespace, labels) - and admission review request information like the name or role. - not: - required: - - any - - all - properties: - all: - description: All allows specifying resources which will - be ANDed - items: - description: ResourceFilter allow users to "AND" or "OR" - between resources - properties: - clusterRoles: - description: ClusterRoles is the list of cluster-wide - role names for the user. - items: - type: string - type: array - resources: - description: ResourceDescription contains information - about the resource being created or modified. - not: - required: - - name - - names - properties: - annotations: - additionalProperties: - type: string - description: |- - Annotations is a map of annotations (key-value pairs of type string). Annotation keys - and values support the wildcard characters "*" (matches zero or many characters) and - "?" (matches at least one character). - type: object - kinds: - description: Kinds is a list of resource kinds. - items: - type: string - type: array - name: - description: |- - Name is the name of the resource. The name supports wildcard characters - "*" (matches zero or many characters) and "?" (at least one character). - NOTE: "Name" is being deprecated in favor of "Names". - type: string - names: - description: |- - Names are the names of the resources. Each name supports wildcard characters - "*" (matches zero or many characters) and "?" (at least one character). - items: - type: string - type: array - namespaceSelector: - description: |- - NamespaceSelector is a label selector for the resource namespace. Label keys and values - in `matchLabels` support the wildcard characters `*` (matches zero or many characters) - and `?` (matches one character).Wildcards allows writing label selectors like - ["storage.k8s.io/*": "*"]. Note that using ["*" : "*"] matches any key and value but - does not match an empty label set. - properties: - matchExpressions: - description: matchExpressions is a list of - label selector requirements. The requirements - are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key that - the selector applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - namespaces: - description: |- - Namespaces is a list of namespaces names. Each name supports wildcard characters - "*" (matches zero or many characters) and "?" (at least one character). - items: - type: string - type: array - operations: - description: Operations can contain values ["CREATE, - "UPDATE", "CONNECT", "DELETE"], which are used - to match a specific action. - items: - description: AdmissionOperation can have one - of the values CREATE, UPDATE, CONNECT, DELETE, - which are used to match a specific action. - enum: - - CREATE - - CONNECT - - UPDATE - - DELETE - type: string - type: array - selector: - description: |- - Selector is a label selector. Label keys and values in `matchLabels` support the wildcard - characters `*` (matches zero or many characters) and `?` (matches one character). - Wildcards allows writing label selectors like ["storage.k8s.io/*": "*"]. Note that - using ["*" : "*"] matches any key and value but does not match an empty label set. - properties: - matchExpressions: - description: matchExpressions is a list of - label selector requirements. The requirements - are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key that - the selector applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - type: object - roles: - description: Roles is the list of namespaced role - names for the user. - items: - type: string - type: array - subjects: - description: Subjects is the list of subject names - like users, user groups, and service accounts. - items: - description: |- - Subject contains a reference to the object or user identities a role binding applies to. This can either hold a direct API object reference, - or a value for non-objects such as user and group names. - properties: - apiGroup: - description: |- - APIGroup holds the API group of the referenced subject. - Defaults to "" for ServiceAccount subjects. - Defaults to "rbac.authorization.k8s.io" for User and Group subjects. - type: string - kind: - description: |- - Kind of object being referenced. Values defined by this API group are "User", "Group", and "ServiceAccount". - If the Authorizer does not recognized the kind value, the Authorizer should report an error. - type: string - name: - description: Name of the object being referenced. - type: string - namespace: - description: |- - Namespace of the referenced object. If the object kind is non-namespace, such as "User" or "Group", and this value is not empty - the Authorizer should report an error. - type: string - required: - - kind - - name - type: object - x-kubernetes-map-type: atomic - type: array - type: object - type: array - any: - description: Any allows specifying resources which will - be ORed - items: - description: ResourceFilter allow users to "AND" or "OR" - between resources - properties: - clusterRoles: - description: ClusterRoles is the list of cluster-wide - role names for the user. - items: - type: string - type: array - resources: - description: ResourceDescription contains information - about the resource being created or modified. - not: - required: - - name - - names - properties: - annotations: - additionalProperties: - type: string - description: |- - Annotations is a map of annotations (key-value pairs of type string). Annotation keys - and values support the wildcard characters "*" (matches zero or many characters) and - "?" (matches at least one character). - type: object - kinds: - description: Kinds is a list of resource kinds. - items: - type: string - type: array - name: - description: |- - Name is the name of the resource. The name supports wildcard characters - "*" (matches zero or many characters) and "?" (at least one character). - NOTE: "Name" is being deprecated in favor of "Names". - type: string - names: - description: |- - Names are the names of the resources. Each name supports wildcard characters - "*" (matches zero or many characters) and "?" (at least one character). - items: - type: string - type: array - namespaceSelector: - description: |- - NamespaceSelector is a label selector for the resource namespace. Label keys and values - in `matchLabels` support the wildcard characters `*` (matches zero or many characters) - and `?` (matches one character).Wildcards allows writing label selectors like - ["storage.k8s.io/*": "*"]. Note that using ["*" : "*"] matches any key and value but - does not match an empty label set. - properties: - matchExpressions: - description: matchExpressions is a list of - label selector requirements. The requirements - are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key that - the selector applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - namespaces: - description: |- - Namespaces is a list of namespaces names. Each name supports wildcard characters - "*" (matches zero or many characters) and "?" (at least one character). - items: - type: string - type: array - operations: - description: Operations can contain values ["CREATE, - "UPDATE", "CONNECT", "DELETE"], which are used - to match a specific action. - items: - description: AdmissionOperation can have one - of the values CREATE, UPDATE, CONNECT, DELETE, - which are used to match a specific action. - enum: - - CREATE - - CONNECT - - UPDATE - - DELETE - type: string - type: array - selector: - description: |- - Selector is a label selector. Label keys and values in `matchLabels` support the wildcard - characters `*` (matches zero or many characters) and `?` (matches one character). - Wildcards allows writing label selectors like ["storage.k8s.io/*": "*"]. Note that - using ["*" : "*"] matches any key and value but does not match an empty label set. - properties: - matchExpressions: - description: matchExpressions is a list of - label selector requirements. The requirements - are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key that - the selector applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - type: object - roles: - description: Roles is the list of namespaced role - names for the user. - items: - type: string - type: array - subjects: - description: Subjects is the list of subject names - like users, user groups, and service accounts. - items: - description: |- - Subject contains a reference to the object or user identities a role binding applies to. This can either hold a direct API object reference, - or a value for non-objects such as user and group names. - properties: - apiGroup: - description: |- - APIGroup holds the API group of the referenced subject. - Defaults to "" for ServiceAccount subjects. - Defaults to "rbac.authorization.k8s.io" for User and Group subjects. - type: string - kind: - description: |- - Kind of object being referenced. Values defined by this API group are "User", "Group", and "ServiceAccount". - If the Authorizer does not recognized the kind value, the Authorizer should report an error. - type: string - name: - description: Name of the object being referenced. - type: string - namespace: - description: |- - Namespace of the referenced object. If the object kind is non-namespace, such as "User" or "Group", and this value is not empty - the Authorizer should report an error. - type: string - required: - - kind - - name - type: object - x-kubernetes-map-type: atomic - type: array - type: object - type: array - clusterRoles: - description: ClusterRoles is the list of cluster-wide role - names for the user. - items: - type: string - type: array - resources: - description: |- - ResourceDescription contains information about the resource being created or modified. - Requires at least one tag to be specified when under MatchResources. - Specifying ResourceDescription directly under match is being deprecated. - Please specify under "any" or "all" instead. - not: - required: - - name - - names - properties: - annotations: - additionalProperties: - type: string - description: |- - Annotations is a map of annotations (key-value pairs of type string). Annotation keys - and values support the wildcard characters "*" (matches zero or many characters) and - "?" (matches at least one character). - type: object - kinds: - description: Kinds is a list of resource kinds. - items: - type: string - type: array - name: - description: |- - Name is the name of the resource. The name supports wildcard characters - "*" (matches zero or many characters) and "?" (at least one character). - NOTE: "Name" is being deprecated in favor of "Names". - type: string - names: - description: |- - Names are the names of the resources. Each name supports wildcard characters - "*" (matches zero or many characters) and "?" (at least one character). - items: - type: string - type: array - namespaceSelector: - description: |- - NamespaceSelector is a label selector for the resource namespace. Label keys and values - in `matchLabels` support the wildcard characters `*` (matches zero or many characters) - and `?` (matches one character).Wildcards allows writing label selectors like - ["storage.k8s.io/*": "*"]. Note that using ["*" : "*"] matches any key and value but - does not match an empty label set. - properties: - matchExpressions: - description: matchExpressions is a list of label - selector requirements. The requirements are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key that the - selector applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - namespaces: - description: |- - Namespaces is a list of namespaces names. Each name supports wildcard characters - "*" (matches zero or many characters) and "?" (at least one character). - items: - type: string - type: array - operations: - description: Operations can contain values ["CREATE, - "UPDATE", "CONNECT", "DELETE"], which are used to - match a specific action. - items: - description: AdmissionOperation can have one of the - values CREATE, UPDATE, CONNECT, DELETE, which are - used to match a specific action. - enum: - - CREATE - - CONNECT - - UPDATE - - DELETE - type: string - type: array - selector: - description: |- - Selector is a label selector. Label keys and values in `matchLabels` support the wildcard - characters `*` (matches zero or many characters) and `?` (matches one character). - Wildcards allows writing label selectors like ["storage.k8s.io/*": "*"]. Note that - using ["*" : "*"] matches any key and value but does not match an empty label set. - properties: - matchExpressions: - description: matchExpressions is a list of label - selector requirements. The requirements are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key that the - selector applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - type: object - roles: - description: Roles is the list of namespaced role names - for the user. - items: - type: string - type: array - subjects: - description: Subjects is the list of subject names like - users, user groups, and service accounts. - items: - description: |- - Subject contains a reference to the object or user identities a role binding applies to. This can either hold a direct API object reference, - or a value for non-objects such as user and group names. - properties: - apiGroup: - description: |- - APIGroup holds the API group of the referenced subject. - Defaults to "" for ServiceAccount subjects. - Defaults to "rbac.authorization.k8s.io" for User and Group subjects. - type: string - kind: - description: |- - Kind of object being referenced. Values defined by this API group are "User", "Group", and "ServiceAccount". - If the Authorizer does not recognized the kind value, the Authorizer should report an error. - type: string - name: - description: Name of the object being referenced. - type: string - namespace: - description: |- - Namespace of the referenced object. If the object kind is non-namespace, such as "User" or "Group", and this value is not empty - the Authorizer should report an error. - type: string - required: - - kind - - name - type: object - x-kubernetes-map-type: atomic - type: array - type: object - generate: - description: Generation is used to create new resources. - properties: - apiVersion: - description: APIVersion specifies resource apiVersion. - type: string - clone: - description: |- - Clone specifies the source resource used to populate each generated resource. - At most one of Data or Clone can be specified. If neither are provided, the generated - resource will be created with default data only. - properties: - name: - description: Name specifies name of the resource. - type: string - namespace: - description: Namespace specifies source resource namespace. - type: string - type: object - cloneList: - description: CloneList specifies the list of source resource - used to populate each generated resource. - properties: - kinds: - description: Kinds is a list of resource kinds. - items: - type: string - type: array - namespace: - description: Namespace specifies source resource namespace. - type: string - selector: - description: |- - Selector is a label selector. Label keys and values in `matchLabels`. - wildcard characters are not supported. - properties: - matchExpressions: - description: matchExpressions is a list of label - selector requirements. The requirements are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key that the - selector applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - type: object - data: - description: |- - Data provides the resource declaration used to populate each generated resource. - At most one of Data or Clone must be specified. If neither are provided, the generated - resource will be created with default data only. - x-kubernetes-preserve-unknown-fields: true - foreach: - description: ForEach applies generate rules to a list of - sub-elements by creating a context for each entry in the - list and looping over it to apply the specified logic. - items: - properties: - apiVersion: - description: APIVersion specifies resource apiVersion. - type: string - clone: - description: |- - Clone specifies the source resource used to populate each generated resource. - At most one of Data or Clone can be specified. If neither are provided, the generated - resource will be created with default data only. - properties: - name: - description: Name specifies name of the resource. - type: string - namespace: - description: Namespace specifies source resource - namespace. - type: string - type: object - cloneList: - description: CloneList specifies the list of source - resource used to populate each generated resource. - properties: - kinds: - description: Kinds is a list of resource kinds. - items: - type: string - type: array - namespace: - description: Namespace specifies source resource - namespace. - type: string - selector: - description: |- - Selector is a label selector. Label keys and values in `matchLabels`. - wildcard characters are not supported. - properties: - matchExpressions: - description: matchExpressions is a list of - label selector requirements. The requirements - are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key that - the selector applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - type: object - context: - description: Context defines variables and data sources - that can be used during rule execution. - items: - description: |- - ContextEntry adds variables and data sources to a rule Context. Either a - ConfigMap reference or a APILookup must be provided. - oneOf: - - required: - - configMap - - required: - - apiCall - - required: - - imageRegistry - - required: - - variable - - required: - - globalReference - properties: - apiCall: - description: |- - APICall is an HTTP request to the Kubernetes API server, or other JSON web service. - The data returned is stored in the context with the name for the context entry. - properties: - data: - description: |- - The data object specifies the POST data sent to the server. - Only applicable when the method field is set to POST. - items: - description: RequestData contains the - HTTP POST data - properties: - key: - description: Key is a unique identifier - for the data value - type: string - value: - description: Value is the data value - x-kubernetes-preserve-unknown-fields: true - required: - - key - - value - type: object - type: array - default: - description: |- - Default is an optional arbitrary JSON object that the context - value is set to, if the apiCall returns error. - x-kubernetes-preserve-unknown-fields: true - jmesPath: - description: |- - JMESPath is an optional JSON Match Expression that can be used to - transform the JSON response returned from the server. For example - a JMESPath of "items | length(@)" applied to the API server response - for the URLPath "/apis/apps/v1/deployments" will return the total count - of deployments across all namespaces. - type: string - method: - default: GET - description: Method is the HTTP request - type (GET or POST). Defaults to GET. - enum: - - GET - - POST - type: string - service: - description: |- - Service is an API call to a JSON web service. - This is used for non-Kubernetes API server calls. - It's mutually exclusive with the URLPath field. - properties: - caBundle: - description: |- - CABundle is a PEM encoded CA bundle which will be used to validate - the server certificate. - type: string - headers: - description: Headers is a list of optional - HTTP headers to be included in the - request. - items: - properties: - key: - description: Key is the header - key - type: string - value: - description: Value is the header - value - type: string - required: - - key - - value - type: object - type: array - url: - description: |- - URL is the JSON web service URL. A typical form is - `https://{service}.{namespace}:{port}/{path}`. - type: string - required: - - url - type: object - urlPath: - description: |- - URLPath is the URL path to be used in the HTTP GET or POST request to the - Kubernetes API server (e.g. "/api/v1/namespaces" or "/apis/apps/v1/deployments"). - The format required is the same format used by the `kubectl get --raw` command. - See https://kyverno.io/docs/writing-policies/external-data-sources/#variables-from-kubernetes-api-server-calls - for details. - It's mutually exclusive with the Service field. - type: string - type: object - configMap: - description: ConfigMap is the ConfigMap reference. - properties: - name: - description: Name is the ConfigMap name. - type: string - namespace: - description: Namespace is the ConfigMap - namespace. - type: string - required: - - name - type: object - globalReference: - description: GlobalContextEntryReference is - a reference to a cached global context entry. - properties: - jmesPath: - description: |- - JMESPath is an optional JSON Match Expression that can be used to - transform the JSON response returned from the server. For example - a JMESPath of "items | length(@)" applied to the API server response - for the URLPath "/apis/apps/v1/deployments" will return the total count - of deployments across all namespaces. - type: string - name: - description: Name of the global context - entry - type: string - required: - - name - type: object - imageRegistry: - description: |- - ImageRegistry defines requests to an OCI/Docker V2 registry to fetch image - details. - properties: - imageRegistryCredentials: - description: ImageRegistryCredentials provides - credentials that will be used for authentication - with registry - properties: - allowInsecureRegistry: - description: AllowInsecureRegistry allows - insecure access to a registry. - type: boolean - providers: - description: |- - Providers specifies a list of OCI Registry names, whose authentication providers are provided. - It can be of one of these values: default,google,azure,amazon,github. - items: - description: ImageRegistryCredentialsProvidersType - provides the list of credential - providers required. - enum: - - default - - amazon - - azure - - google - - github - type: string - type: array - secrets: - description: |- - Secrets specifies a list of secrets that are provided for credentials. - Secrets must live in the Kyverno namespace. - items: - type: string - type: array - type: object - jmesPath: - description: |- - JMESPath is an optional JSON Match Expression that can be used to - transform the ImageData struct returned as a result of processing - the image reference. - type: string - reference: - description: |- - Reference is image reference to a container image in the registry. - Example: ghcr.io/kyverno/kyverno:latest - type: string - required: - - reference - type: object - name: - description: Name is the variable name. - type: string - variable: - description: Variable defines an arbitrary JMESPath - context variable that can be defined inline. - properties: - default: - description: |- - Default is an optional arbitrary JSON object that the variable may take if the JMESPath - expression evaluates to nil - x-kubernetes-preserve-unknown-fields: true - jmesPath: - description: |- - JMESPath is an optional JMESPath Expression that can be used to - transform the variable. - type: string - value: - description: Value is any arbitrary JSON - object representable in YAML or JSON form. - x-kubernetes-preserve-unknown-fields: true - type: object - required: - - name - type: object - type: array - data: - description: |- - Data provides the resource declaration used to populate each generated resource. - At most one of Data or Clone must be specified. If neither are provided, the generated - resource will be created with default data only. - x-kubernetes-preserve-unknown-fields: true - kind: - description: Kind specifies resource kind. - type: string - list: - description: |- - List specifies a JMESPath expression that results in one or more elements - to which the validation logic is applied. - type: string - name: - description: Name specifies the resource name. - type: string - namespace: - description: Namespace specifies resource namespace. - type: string - preconditions: - description: |- - AnyAllConditions are used to determine if a policy rule should be applied by evaluating a - set of conditions. The declaration can contain nested `any` or `all` statements. - See: https://kyverno.io/docs/writing-policies/preconditions/ - properties: - all: - description: |- - AllConditions enable variable-based conditional rule execution. This is useful for - finer control of when an rule is applied. A condition can reference object data - using JMESPath notation. - Here, all of the conditions need to pass - items: - description: Condition defines variable-based - conditional criteria for rule execution. - properties: - key: - description: Key is the context entry (using - JMESPath) for conditional rule evaluation. - x-kubernetes-preserve-unknown-fields: true - message: - description: Message is an optional display - message - type: string - operator: - description: |- - Operator is the conditional operation to perform. Valid operators are: - Equals, NotEquals, In, AnyIn, AllIn, NotIn, AnyNotIn, AllNotIn, GreaterThanOrEquals, - GreaterThan, LessThanOrEquals, LessThan, DurationGreaterThanOrEquals, DurationGreaterThan, - DurationLessThanOrEquals, DurationLessThan - enum: - - Equals - - NotEquals - - In - - AnyIn - - AllIn - - NotIn - - AnyNotIn - - AllNotIn - - GreaterThanOrEquals - - GreaterThan - - LessThanOrEquals - - LessThan - - DurationGreaterThanOrEquals - - DurationGreaterThan - - DurationLessThanOrEquals - - DurationLessThan - type: string - value: - description: |- - Value is the conditional value, or set of values. The values can be fixed set - or can be variables declared using JMESPath. - x-kubernetes-preserve-unknown-fields: true - type: object - type: array - any: - description: |- - AnyConditions enable variable-based conditional rule execution. This is useful for - finer control of when an rule is applied. A condition can reference object data - using JMESPath notation. - Here, at least one of the conditions need to pass - items: - description: Condition defines variable-based - conditional criteria for rule execution. - properties: - key: - description: Key is the context entry (using - JMESPath) for conditional rule evaluation. - x-kubernetes-preserve-unknown-fields: true - message: - description: Message is an optional display - message - type: string - operator: - description: |- - Operator is the conditional operation to perform. Valid operators are: - Equals, NotEquals, In, AnyIn, AllIn, NotIn, AnyNotIn, AllNotIn, GreaterThanOrEquals, - GreaterThan, LessThanOrEquals, LessThan, DurationGreaterThanOrEquals, DurationGreaterThan, - DurationLessThanOrEquals, DurationLessThan - enum: - - Equals - - NotEquals - - In - - AnyIn - - AllIn - - NotIn - - AnyNotIn - - AllNotIn - - GreaterThanOrEquals - - GreaterThan - - LessThanOrEquals - - LessThan - - DurationGreaterThanOrEquals - - DurationGreaterThan - - DurationLessThanOrEquals - - DurationLessThan - type: string - value: - description: |- - Value is the conditional value, or set of values. The values can be fixed set - or can be variables declared using JMESPath. - x-kubernetes-preserve-unknown-fields: true - type: object - type: array - type: object - x-kubernetes-preserve-unknown-fields: true - uid: - description: UID specifies the resource uid. - type: string - type: object - type: array - generateExisting: - description: |- - GenerateExisting controls whether to trigger the rule in existing resources - If is set to "true" the rule will be triggered and applied to existing matched resources. - type: boolean - kind: - description: Kind specifies resource kind. - type: string - name: - description: Name specifies the resource name. - type: string - namespace: - description: Namespace specifies resource namespace. - type: string - orphanDownstreamOnPolicyDelete: - description: |- - OrphanDownstreamOnPolicyDelete controls whether generated resources should be deleted when the rule that generated - them is deleted with synchronization enabled. This option is only applicable to generate rules of the data type. - See https://kyverno.io/docs/writing-policies/generate/#data-examples. - Defaults to "false" if not specified. - type: boolean - synchronize: - description: |- - Synchronize controls if generated resources should be kept in-sync with their source resource. - If Synchronize is set to "true" changes to generated resources will be overwritten with resource - data from Data or the resource specified in the Clone declaration. - Optional. Defaults to "false" if not specified. - type: boolean - uid: - description: UID specifies the resource uid. - type: string - type: object - imageExtractors: - additionalProperties: - items: - properties: - jmesPath: - description: |- - JMESPath is an optional JMESPath expression to apply to the image value. - This is useful when the extracted image begins with a prefix like 'docker://'. - The 'trim_prefix' function may be used to trim the prefix: trim_prefix(@, 'docker://'). - Note - Image digest mutation may not be used when applying a JMESPAth to an image. - type: string - key: - description: |- - Key is an optional name of the field within 'path' that will be used to uniquely identify an image. - Note - this field MUST be unique. - type: string - name: - description: |- - Name is the entry the image will be available under 'images.' in the context. - If this field is not defined, image entries will appear under 'images.custom'. - type: string - path: - description: |- - Path is the path to the object containing the image field in a custom resource. - It should be slash-separated. Each slash-separated key must be a valid YAML key or a wildcard '*'. - Wildcard keys are expanded in case of arrays or objects. - type: string - value: - description: |- - Value is an optional name of the field within 'path' that points to the image URI. - This is useful when a custom 'key' is also defined. - type: string - required: - - path - type: object - type: array - description: |- - ImageExtractors defines a mapping from kinds to ImageExtractorConfigs. - This config is only valid for verifyImages rules. - type: object - match: - description: |- - MatchResources defines when this policy rule should be applied. The match - criteria can include resource information (e.g. kind, name, namespace, labels) - and admission review request information like the user name or role. - At least one kind is required. - not: - required: - - any - - all - properties: - all: - description: All allows specifying resources which will - be ANDed - items: - description: ResourceFilter allow users to "AND" or "OR" - between resources - properties: - clusterRoles: - description: ClusterRoles is the list of cluster-wide - role names for the user. - items: - type: string - type: array - resources: - description: ResourceDescription contains information - about the resource being created or modified. - not: - required: - - name - - names - properties: - annotations: - additionalProperties: - type: string - description: |- - Annotations is a map of annotations (key-value pairs of type string). Annotation keys - and values support the wildcard characters "*" (matches zero or many characters) and - "?" (matches at least one character). - type: object - kinds: - description: Kinds is a list of resource kinds. - items: - type: string - type: array - name: - description: |- - Name is the name of the resource. The name supports wildcard characters - "*" (matches zero or many characters) and "?" (at least one character). - NOTE: "Name" is being deprecated in favor of "Names". - type: string - names: - description: |- - Names are the names of the resources. Each name supports wildcard characters - "*" (matches zero or many characters) and "?" (at least one character). - items: - type: string - type: array - namespaceSelector: - description: |- - NamespaceSelector is a label selector for the resource namespace. Label keys and values - in `matchLabels` support the wildcard characters `*` (matches zero or many characters) - and `?` (matches one character).Wildcards allows writing label selectors like - ["storage.k8s.io/*": "*"]. Note that using ["*" : "*"] matches any key and value but - does not match an empty label set. - properties: - matchExpressions: - description: matchExpressions is a list of - label selector requirements. The requirements - are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key that - the selector applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - namespaces: - description: |- - Namespaces is a list of namespaces names. Each name supports wildcard characters - "*" (matches zero or many characters) and "?" (at least one character). - items: - type: string - type: array - operations: - description: Operations can contain values ["CREATE, - "UPDATE", "CONNECT", "DELETE"], which are used - to match a specific action. - items: - description: AdmissionOperation can have one - of the values CREATE, UPDATE, CONNECT, DELETE, - which are used to match a specific action. - enum: - - CREATE - - CONNECT - - UPDATE - - DELETE - type: string - type: array - selector: - description: |- - Selector is a label selector. Label keys and values in `matchLabels` support the wildcard - characters `*` (matches zero or many characters) and `?` (matches one character). - Wildcards allows writing label selectors like ["storage.k8s.io/*": "*"]. Note that - using ["*" : "*"] matches any key and value but does not match an empty label set. - properties: - matchExpressions: - description: matchExpressions is a list of - label selector requirements. The requirements - are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key that - the selector applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - type: object - roles: - description: Roles is the list of namespaced role - names for the user. - items: - type: string - type: array - subjects: - description: Subjects is the list of subject names - like users, user groups, and service accounts. - items: - description: |- - Subject contains a reference to the object or user identities a role binding applies to. This can either hold a direct API object reference, - or a value for non-objects such as user and group names. - properties: - apiGroup: - description: |- - APIGroup holds the API group of the referenced subject. - Defaults to "" for ServiceAccount subjects. - Defaults to "rbac.authorization.k8s.io" for User and Group subjects. - type: string - kind: - description: |- - Kind of object being referenced. Values defined by this API group are "User", "Group", and "ServiceAccount". - If the Authorizer does not recognized the kind value, the Authorizer should report an error. - type: string - name: - description: Name of the object being referenced. - type: string - namespace: - description: |- - Namespace of the referenced object. If the object kind is non-namespace, such as "User" or "Group", and this value is not empty - the Authorizer should report an error. - type: string - required: - - kind - - name - type: object - x-kubernetes-map-type: atomic - type: array - type: object - type: array - any: - description: Any allows specifying resources which will - be ORed - items: - description: ResourceFilter allow users to "AND" or "OR" - between resources - properties: - clusterRoles: - description: ClusterRoles is the list of cluster-wide - role names for the user. - items: - type: string - type: array - resources: - description: ResourceDescription contains information - about the resource being created or modified. - not: - required: - - name - - names - properties: - annotations: - additionalProperties: - type: string - description: |- - Annotations is a map of annotations (key-value pairs of type string). Annotation keys - and values support the wildcard characters "*" (matches zero or many characters) and - "?" (matches at least one character). - type: object - kinds: - description: Kinds is a list of resource kinds. - items: - type: string - type: array - name: - description: |- - Name is the name of the resource. The name supports wildcard characters - "*" (matches zero or many characters) and "?" (at least one character). - NOTE: "Name" is being deprecated in favor of "Names". - type: string - names: - description: |- - Names are the names of the resources. Each name supports wildcard characters - "*" (matches zero or many characters) and "?" (at least one character). - items: - type: string - type: array - namespaceSelector: - description: |- - NamespaceSelector is a label selector for the resource namespace. Label keys and values - in `matchLabels` support the wildcard characters `*` (matches zero or many characters) - and `?` (matches one character).Wildcards allows writing label selectors like - ["storage.k8s.io/*": "*"]. Note that using ["*" : "*"] matches any key and value but - does not match an empty label set. - properties: - matchExpressions: - description: matchExpressions is a list of - label selector requirements. The requirements - are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key that - the selector applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - namespaces: - description: |- - Namespaces is a list of namespaces names. Each name supports wildcard characters - "*" (matches zero or many characters) and "?" (at least one character). - items: - type: string - type: array - operations: - description: Operations can contain values ["CREATE, - "UPDATE", "CONNECT", "DELETE"], which are used - to match a specific action. - items: - description: AdmissionOperation can have one - of the values CREATE, UPDATE, CONNECT, DELETE, - which are used to match a specific action. - enum: - - CREATE - - CONNECT - - UPDATE - - DELETE - type: string - type: array - selector: - description: |- - Selector is a label selector. Label keys and values in `matchLabels` support the wildcard - characters `*` (matches zero or many characters) and `?` (matches one character). - Wildcards allows writing label selectors like ["storage.k8s.io/*": "*"]. Note that - using ["*" : "*"] matches any key and value but does not match an empty label set. - properties: - matchExpressions: - description: matchExpressions is a list of - label selector requirements. The requirements - are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key that - the selector applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - type: object - roles: - description: Roles is the list of namespaced role - names for the user. - items: - type: string - type: array - subjects: - description: Subjects is the list of subject names - like users, user groups, and service accounts. - items: - description: |- - Subject contains a reference to the object or user identities a role binding applies to. This can either hold a direct API object reference, - or a value for non-objects such as user and group names. - properties: - apiGroup: - description: |- - APIGroup holds the API group of the referenced subject. - Defaults to "" for ServiceAccount subjects. - Defaults to "rbac.authorization.k8s.io" for User and Group subjects. - type: string - kind: - description: |- - Kind of object being referenced. Values defined by this API group are "User", "Group", and "ServiceAccount". - If the Authorizer does not recognized the kind value, the Authorizer should report an error. - type: string - name: - description: Name of the object being referenced. - type: string - namespace: - description: |- - Namespace of the referenced object. If the object kind is non-namespace, such as "User" or "Group", and this value is not empty - the Authorizer should report an error. - type: string - required: - - kind - - name - type: object - x-kubernetes-map-type: atomic - type: array - type: object - type: array - clusterRoles: - description: ClusterRoles is the list of cluster-wide role - names for the user. - items: - type: string - type: array - resources: - description: |- - ResourceDescription contains information about the resource being created or modified. - Requires at least one tag to be specified when under MatchResources. - Specifying ResourceDescription directly under match is being deprecated. - Please specify under "any" or "all" instead. - not: - required: - - name - - names - properties: - annotations: - additionalProperties: - type: string - description: |- - Annotations is a map of annotations (key-value pairs of type string). Annotation keys - and values support the wildcard characters "*" (matches zero or many characters) and - "?" (matches at least one character). - type: object - kinds: - description: Kinds is a list of resource kinds. - items: - type: string - type: array - name: - description: |- - Name is the name of the resource. The name supports wildcard characters - "*" (matches zero or many characters) and "?" (at least one character). - NOTE: "Name" is being deprecated in favor of "Names". - type: string - names: - description: |- - Names are the names of the resources. Each name supports wildcard characters - "*" (matches zero or many characters) and "?" (at least one character). - items: - type: string - type: array - namespaceSelector: - description: |- - NamespaceSelector is a label selector for the resource namespace. Label keys and values - in `matchLabels` support the wildcard characters `*` (matches zero or many characters) - and `?` (matches one character).Wildcards allows writing label selectors like - ["storage.k8s.io/*": "*"]. Note that using ["*" : "*"] matches any key and value but - does not match an empty label set. - properties: - matchExpressions: - description: matchExpressions is a list of label - selector requirements. The requirements are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key that the - selector applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - namespaces: - description: |- - Namespaces is a list of namespaces names. Each name supports wildcard characters - "*" (matches zero or many characters) and "?" (at least one character). - items: - type: string - type: array - operations: - description: Operations can contain values ["CREATE, - "UPDATE", "CONNECT", "DELETE"], which are used to - match a specific action. - items: - description: AdmissionOperation can have one of the - values CREATE, UPDATE, CONNECT, DELETE, which are - used to match a specific action. - enum: - - CREATE - - CONNECT - - UPDATE - - DELETE - type: string - type: array - selector: - description: |- - Selector is a label selector. Label keys and values in `matchLabels` support the wildcard - characters `*` (matches zero or many characters) and `?` (matches one character). - Wildcards allows writing label selectors like ["storage.k8s.io/*": "*"]. Note that - using ["*" : "*"] matches any key and value but does not match an empty label set. - properties: - matchExpressions: - description: matchExpressions is a list of label - selector requirements. The requirements are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key that the - selector applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - type: object - roles: - description: Roles is the list of namespaced role names - for the user. - items: - type: string - type: array - subjects: - description: Subjects is the list of subject names like - users, user groups, and service accounts. - items: - description: |- - Subject contains a reference to the object or user identities a role binding applies to. This can either hold a direct API object reference, - or a value for non-objects such as user and group names. - properties: - apiGroup: - description: |- - APIGroup holds the API group of the referenced subject. - Defaults to "" for ServiceAccount subjects. - Defaults to "rbac.authorization.k8s.io" for User and Group subjects. - type: string - kind: - description: |- - Kind of object being referenced. Values defined by this API group are "User", "Group", and "ServiceAccount". - If the Authorizer does not recognized the kind value, the Authorizer should report an error. - type: string - name: - description: Name of the object being referenced. - type: string - namespace: - description: |- - Namespace of the referenced object. If the object kind is non-namespace, such as "User" or "Group", and this value is not empty - the Authorizer should report an error. - type: string - required: - - kind - - name - type: object - x-kubernetes-map-type: atomic - type: array - type: object - mutate: - description: Mutation is used to modify matching resources. - properties: - foreach: - description: ForEach applies mutation rules to a list of - sub-elements by creating a context for each entry in the - list and looping over it to apply the specified logic. - items: - description: ForEachMutation applies mutation rules to - a list of sub-elements by creating a context for each - entry in the list and looping over it to apply the specified - logic. - properties: - context: - description: Context defines variables and data sources - that can be used during rule execution. - items: - description: |- - ContextEntry adds variables and data sources to a rule Context. Either a - ConfigMap reference or a APILookup must be provided. - oneOf: - - required: - - configMap - - required: - - apiCall - - required: - - imageRegistry - - required: - - variable - - required: - - globalReference - properties: - apiCall: - description: |- - APICall is an HTTP request to the Kubernetes API server, or other JSON web service. - The data returned is stored in the context with the name for the context entry. - properties: - data: - description: |- - The data object specifies the POST data sent to the server. - Only applicable when the method field is set to POST. - items: - description: RequestData contains the - HTTP POST data - properties: - key: - description: Key is a unique identifier - for the data value - type: string - value: - description: Value is the data value - x-kubernetes-preserve-unknown-fields: true - required: - - key - - value - type: object - type: array - default: - description: |- - Default is an optional arbitrary JSON object that the context - value is set to, if the apiCall returns error. - x-kubernetes-preserve-unknown-fields: true - jmesPath: - description: |- - JMESPath is an optional JSON Match Expression that can be used to - transform the JSON response returned from the server. For example - a JMESPath of "items | length(@)" applied to the API server response - for the URLPath "/apis/apps/v1/deployments" will return the total count - of deployments across all namespaces. - type: string - method: - default: GET - description: Method is the HTTP request - type (GET or POST). Defaults to GET. - enum: - - GET - - POST - type: string - service: - description: |- - Service is an API call to a JSON web service. - This is used for non-Kubernetes API server calls. - It's mutually exclusive with the URLPath field. - properties: - caBundle: - description: |- - CABundle is a PEM encoded CA bundle which will be used to validate - the server certificate. - type: string - headers: - description: Headers is a list of optional - HTTP headers to be included in the - request. - items: - properties: - key: - description: Key is the header - key - type: string - value: - description: Value is the header - value - type: string - required: - - key - - value - type: object - type: array - url: - description: |- - URL is the JSON web service URL. A typical form is - `https://{service}.{namespace}:{port}/{path}`. - type: string - required: - - url - type: object - urlPath: - description: |- - URLPath is the URL path to be used in the HTTP GET or POST request to the - Kubernetes API server (e.g. "/api/v1/namespaces" or "/apis/apps/v1/deployments"). - The format required is the same format used by the `kubectl get --raw` command. - See https://kyverno.io/docs/writing-policies/external-data-sources/#variables-from-kubernetes-api-server-calls - for details. - It's mutually exclusive with the Service field. - type: string - type: object - configMap: - description: ConfigMap is the ConfigMap reference. - properties: - name: - description: Name is the ConfigMap name. - type: string - namespace: - description: Namespace is the ConfigMap - namespace. - type: string - required: - - name - type: object - globalReference: - description: GlobalContextEntryReference is - a reference to a cached global context entry. - properties: - jmesPath: - description: |- - JMESPath is an optional JSON Match Expression that can be used to - transform the JSON response returned from the server. For example - a JMESPath of "items | length(@)" applied to the API server response - for the URLPath "/apis/apps/v1/deployments" will return the total count - of deployments across all namespaces. - type: string - name: - description: Name of the global context - entry - type: string - required: - - name - type: object - imageRegistry: - description: |- - ImageRegistry defines requests to an OCI/Docker V2 registry to fetch image - details. - properties: - imageRegistryCredentials: - description: ImageRegistryCredentials provides - credentials that will be used for authentication - with registry - properties: - allowInsecureRegistry: - description: AllowInsecureRegistry allows - insecure access to a registry. - type: boolean - providers: - description: |- - Providers specifies a list of OCI Registry names, whose authentication providers are provided. - It can be of one of these values: default,google,azure,amazon,github. - items: - description: ImageRegistryCredentialsProvidersType - provides the list of credential - providers required. - enum: - - default - - amazon - - azure - - google - - github - type: string - type: array - secrets: - description: |- - Secrets specifies a list of secrets that are provided for credentials. - Secrets must live in the Kyverno namespace. - items: - type: string - type: array - type: object - jmesPath: - description: |- - JMESPath is an optional JSON Match Expression that can be used to - transform the ImageData struct returned as a result of processing - the image reference. - type: string - reference: - description: |- - Reference is image reference to a container image in the registry. - Example: ghcr.io/kyverno/kyverno:latest - type: string - required: - - reference - type: object - name: - description: Name is the variable name. - type: string - variable: - description: Variable defines an arbitrary JMESPath - context variable that can be defined inline. - properties: - default: - description: |- - Default is an optional arbitrary JSON object that the variable may take if the JMESPath - expression evaluates to nil - x-kubernetes-preserve-unknown-fields: true - jmesPath: - description: |- - JMESPath is an optional JMESPath Expression that can be used to - transform the variable. - type: string - value: - description: Value is any arbitrary JSON - object representable in YAML or JSON form. - x-kubernetes-preserve-unknown-fields: true - type: object - required: - - name - type: object - type: array - foreach: - description: Foreach declares a nested foreach iterator - x-kubernetes-preserve-unknown-fields: true - list: - description: |- - List specifies a JMESPath expression that results in one or more elements - to which the validation logic is applied. - type: string - order: - description: |- - Order defines the iteration order on the list. - Can be Ascending to iterate from first to last element or Descending to iterate in from last to first element. - enum: - - Ascending - - Descending - type: string - patchStrategicMerge: - description: |- - PatchStrategicMerge is a strategic merge patch used to modify resources. - See https://kubernetes.io/docs/tasks/manage-kubernetes-objects/update-api-object-kubectl-patch/ - and https://kubectl.docs.kubernetes.io/references/kustomize/kustomization/patchesstrategicmerge/. - x-kubernetes-preserve-unknown-fields: true - patchesJson6902: - description: |- - PatchesJSON6902 is a list of RFC 6902 JSON Patch declarations used to modify resources. - See https://tools.ietf.org/html/rfc6902 and https://kubectl.docs.kubernetes.io/references/kustomize/kustomization/patchesjson6902/. - type: string - preconditions: - description: |- - AnyAllConditions are used to determine if a policy rule should be applied by evaluating a - set of conditions. The declaration can contain nested `any` or `all` statements. - See: https://kyverno.io/docs/writing-policies/preconditions/ - properties: - all: - description: |- - AllConditions enable variable-based conditional rule execution. This is useful for - finer control of when an rule is applied. A condition can reference object data - using JMESPath notation. - Here, all of the conditions need to pass - items: - description: Condition defines variable-based - conditional criteria for rule execution. - properties: - key: - description: Key is the context entry (using - JMESPath) for conditional rule evaluation. - x-kubernetes-preserve-unknown-fields: true - message: - description: Message is an optional display - message - type: string - operator: - description: |- - Operator is the conditional operation to perform. Valid operators are: - Equals, NotEquals, In, AnyIn, AllIn, NotIn, AnyNotIn, AllNotIn, GreaterThanOrEquals, - GreaterThan, LessThanOrEquals, LessThan, DurationGreaterThanOrEquals, DurationGreaterThan, - DurationLessThanOrEquals, DurationLessThan - enum: - - Equals - - NotEquals - - In - - AnyIn - - AllIn - - NotIn - - AnyNotIn - - AllNotIn - - GreaterThanOrEquals - - GreaterThan - - LessThanOrEquals - - LessThan - - DurationGreaterThanOrEquals - - DurationGreaterThan - - DurationLessThanOrEquals - - DurationLessThan - type: string - value: - description: |- - Value is the conditional value, or set of values. The values can be fixed set - or can be variables declared using JMESPath. - x-kubernetes-preserve-unknown-fields: true - type: object - type: array - any: - description: |- - AnyConditions enable variable-based conditional rule execution. This is useful for - finer control of when an rule is applied. A condition can reference object data - using JMESPath notation. - Here, at least one of the conditions need to pass - items: - description: Condition defines variable-based - conditional criteria for rule execution. - properties: - key: - description: Key is the context entry (using - JMESPath) for conditional rule evaluation. - x-kubernetes-preserve-unknown-fields: true - message: - description: Message is an optional display - message - type: string - operator: - description: |- - Operator is the conditional operation to perform. Valid operators are: - Equals, NotEquals, In, AnyIn, AllIn, NotIn, AnyNotIn, AllNotIn, GreaterThanOrEquals, - GreaterThan, LessThanOrEquals, LessThan, DurationGreaterThanOrEquals, DurationGreaterThan, - DurationLessThanOrEquals, DurationLessThan - enum: - - Equals - - NotEquals - - In - - AnyIn - - AllIn - - NotIn - - AnyNotIn - - AllNotIn - - GreaterThanOrEquals - - GreaterThan - - LessThanOrEquals - - LessThan - - DurationGreaterThanOrEquals - - DurationGreaterThan - - DurationLessThanOrEquals - - DurationLessThan - type: string - value: - description: |- - Value is the conditional value, or set of values. The values can be fixed set - or can be variables declared using JMESPath. - x-kubernetes-preserve-unknown-fields: true - type: object - type: array - type: object - x-kubernetes-preserve-unknown-fields: true - type: object - type: array - mutateExistingOnPolicyUpdate: - description: MutateExistingOnPolicyUpdate controls if the - mutateExisting rule will be applied on policy events. - type: boolean - patchStrategicMerge: - description: |- - PatchStrategicMerge is a strategic merge patch used to modify resources. - See https://kubernetes.io/docs/tasks/manage-kubernetes-objects/update-api-object-kubectl-patch/ - and https://kubectl.docs.kubernetes.io/references/kustomize/kustomization/patchesstrategicmerge/. - x-kubernetes-preserve-unknown-fields: true - patchesJson6902: - description: |- - PatchesJSON6902 is a list of RFC 6902 JSON Patch declarations used to modify resources. - See https://tools.ietf.org/html/rfc6902 and https://kubectl.docs.kubernetes.io/references/kustomize/kustomization/patchesjson6902/. - type: string - targets: - description: Targets defines the target resources to be - mutated. - items: - description: TargetResourceSpec defines targets for mutating - existing resources. - properties: - apiVersion: - description: APIVersion specifies resource apiVersion. - type: string - context: - description: Context defines variables and data sources - that can be used during rule execution. - items: - description: |- - ContextEntry adds variables and data sources to a rule Context. Either a - ConfigMap reference or a APILookup must be provided. - oneOf: - - required: - - configMap - - required: - - apiCall - - required: - - imageRegistry - - required: - - variable - - required: - - globalReference - properties: - apiCall: - description: |- - APICall is an HTTP request to the Kubernetes API server, or other JSON web service. - The data returned is stored in the context with the name for the context entry. - properties: - data: - description: |- - The data object specifies the POST data sent to the server. - Only applicable when the method field is set to POST. - items: - description: RequestData contains the - HTTP POST data - properties: - key: - description: Key is a unique identifier - for the data value - type: string - value: - description: Value is the data value - x-kubernetes-preserve-unknown-fields: true - required: - - key - - value - type: object - type: array - default: - description: |- - Default is an optional arbitrary JSON object that the context - value is set to, if the apiCall returns error. - x-kubernetes-preserve-unknown-fields: true - jmesPath: - description: |- - JMESPath is an optional JSON Match Expression that can be used to - transform the JSON response returned from the server. For example - a JMESPath of "items | length(@)" applied to the API server response - for the URLPath "/apis/apps/v1/deployments" will return the total count - of deployments across all namespaces. - type: string - method: - default: GET - description: Method is the HTTP request - type (GET or POST). Defaults to GET. - enum: - - GET - - POST - type: string - service: - description: |- - Service is an API call to a JSON web service. - This is used for non-Kubernetes API server calls. - It's mutually exclusive with the URLPath field. - properties: - caBundle: - description: |- - CABundle is a PEM encoded CA bundle which will be used to validate - the server certificate. - type: string - headers: - description: Headers is a list of optional - HTTP headers to be included in the - request. - items: - properties: - key: - description: Key is the header - key - type: string - value: - description: Value is the header - value - type: string - required: - - key - - value - type: object - type: array - url: - description: |- - URL is the JSON web service URL. A typical form is - `https://{service}.{namespace}:{port}/{path}`. - type: string - required: - - url - type: object - urlPath: - description: |- - URLPath is the URL path to be used in the HTTP GET or POST request to the - Kubernetes API server (e.g. "/api/v1/namespaces" or "/apis/apps/v1/deployments"). - The format required is the same format used by the `kubectl get --raw` command. - See https://kyverno.io/docs/writing-policies/external-data-sources/#variables-from-kubernetes-api-server-calls - for details. - It's mutually exclusive with the Service field. - type: string - type: object - configMap: - description: ConfigMap is the ConfigMap reference. - properties: - name: - description: Name is the ConfigMap name. - type: string - namespace: - description: Namespace is the ConfigMap - namespace. - type: string - required: - - name - type: object - globalReference: - description: GlobalContextEntryReference is - a reference to a cached global context entry. - properties: - jmesPath: - description: |- - JMESPath is an optional JSON Match Expression that can be used to - transform the JSON response returned from the server. For example - a JMESPath of "items | length(@)" applied to the API server response - for the URLPath "/apis/apps/v1/deployments" will return the total count - of deployments across all namespaces. - type: string - name: - description: Name of the global context - entry - type: string - required: - - name - type: object - imageRegistry: - description: |- - ImageRegistry defines requests to an OCI/Docker V2 registry to fetch image - details. - properties: - imageRegistryCredentials: - description: ImageRegistryCredentials provides - credentials that will be used for authentication - with registry - properties: - allowInsecureRegistry: - description: AllowInsecureRegistry allows - insecure access to a registry. - type: boolean - providers: - description: |- - Providers specifies a list of OCI Registry names, whose authentication providers are provided. - It can be of one of these values: default,google,azure,amazon,github. - items: - description: ImageRegistryCredentialsProvidersType - provides the list of credential - providers required. - enum: - - default - - amazon - - azure - - google - - github - type: string - type: array - secrets: - description: |- - Secrets specifies a list of secrets that are provided for credentials. - Secrets must live in the Kyverno namespace. - items: - type: string - type: array - type: object - jmesPath: - description: |- - JMESPath is an optional JSON Match Expression that can be used to - transform the ImageData struct returned as a result of processing - the image reference. - type: string - reference: - description: |- - Reference is image reference to a container image in the registry. - Example: ghcr.io/kyverno/kyverno:latest - type: string - required: - - reference - type: object - name: - description: Name is the variable name. - type: string - variable: - description: Variable defines an arbitrary JMESPath - context variable that can be defined inline. - properties: - default: - description: |- - Default is an optional arbitrary JSON object that the variable may take if the JMESPath - expression evaluates to nil - x-kubernetes-preserve-unknown-fields: true - jmesPath: - description: |- - JMESPath is an optional JMESPath Expression that can be used to - transform the variable. - type: string - value: - description: Value is any arbitrary JSON - object representable in YAML or JSON form. - x-kubernetes-preserve-unknown-fields: true - type: object - required: - - name - type: object - type: array - kind: - description: Kind specifies resource kind. - type: string - name: - description: Name specifies the resource name. - type: string - namespace: - description: Namespace specifies resource namespace. - type: string - preconditions: - description: |- - Preconditions are used to determine if a policy rule should be applied by evaluating a - set of conditions. The declaration can contain nested `any` or `all` statements. A direct list - of conditions (without `any` or `all` statements is supported for backwards compatibility but - will be deprecated in the next major release. - See: https://kyverno.io/docs/writing-policies/preconditions/ - x-kubernetes-preserve-unknown-fields: true - selector: - description: Selector allows you to select target - resources with their labels. - properties: - matchExpressions: - description: matchExpressions is a list of label - selector requirements. The requirements are - ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key that the - selector applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - uid: - description: UID specifies the resource uid. - type: string - type: object - type: array - type: object - name: - description: Name is a label to identify the rule, It must be - unique within the policy. - maxLength: 63 - type: string - preconditions: - description: |- - Preconditions are used to determine if a policy rule should be applied by evaluating a - set of conditions. The declaration can contain nested `any` or `all` statements. A direct list - of conditions (without `any` or `all` statements is supported for backwards compatibility but - will be deprecated in the next major release. - See: https://kyverno.io/docs/writing-policies/preconditions/ - x-kubernetes-preserve-unknown-fields: true - reportProperties: - additionalProperties: - type: string - description: ReportProperties are the additional properties - from the rule that will be added to the policy report result - type: object - skipBackgroundRequests: - default: true - description: |- - SkipBackgroundRequests bypasses admission requests that are sent by the background controller. - The default value is set to "true", it must be set to "false" to apply - generate and mutateExisting rules to those requests. - type: boolean - validate: - description: Validation is used to validate matching resources. - properties: - allowExistingViolations: - default: true - description: AllowExistingViolations allows prexisting violating - resources to continue violating a policy. - type: boolean - anyPattern: - description: |- - AnyPattern specifies list of validation patterns. At least one of the patterns - must be satisfied for the validation rule to succeed. - x-kubernetes-preserve-unknown-fields: true - assert: - description: Assert defines a kyverno-json assertion tree. - type: object - x-kubernetes-preserve-unknown-fields: true - cel: - description: CEL allows validation checks using the Common - Expression Language (https://kubernetes.io/docs/reference/using-api/cel/). - properties: - auditAnnotations: - description: AuditAnnotations contains CEL expressions - which are used to produce audit annotations for the - audit event of the API request. - items: - description: AuditAnnotation describes how to produce - an audit annotation for an API request. - properties: - key: - description: |- - key specifies the audit annotation key. The audit annotation keys of - a ValidatingAdmissionPolicy must be unique. The key must be a qualified - name ([A-Za-z0-9][-A-Za-z0-9_.]*) no more than 63 bytes in length. - - The key is combined with the resource name of the - ValidatingAdmissionPolicy to construct an audit annotation key: - "{ValidatingAdmissionPolicy name}/{key}". - - If an admission webhook uses the same resource name as this ValidatingAdmissionPolicy - and the same audit annotation key, the annotation key will be identical. - In this case, the first annotation written with the key will be included - in the audit event and all subsequent annotations with the same key - will be discarded. - - Required. - type: string - valueExpression: - description: |- - valueExpression represents the expression which is evaluated by CEL to - produce an audit annotation value. The expression must evaluate to either - a string or null value. If the expression evaluates to a string, the - audit annotation is included with the string value. If the expression - evaluates to null or empty string the audit annotation will be omitted. - The valueExpression may be no longer than 5kb in length. - If the result of the valueExpression is more than 10kb in length, it - will be truncated to 10kb. - - If multiple ValidatingAdmissionPolicyBinding resources match an - API request, then the valueExpression will be evaluated for - each binding. All unique values produced by the valueExpressions - will be joined together in a comma-separated list. - - Required. - type: string - required: - - key - - valueExpression - type: object - type: array - expressions: - description: Expressions is a list of CELExpression - types. - items: - description: Validation specifies the CEL expression - which is used to apply the validation. - properties: - expression: - description: "Expression represents the expression - which will be evaluated by CEL.\nref: https://github.com/google/cel-spec\nCEL - expressions have access to the contents of the - API request/response, organized into CEL variables - as well as some other useful variables:\n\n- - 'object' - The object from the incoming request. - The value is null for DELETE requests.\n- 'oldObject' - - The existing object. The value is null for - CREATE requests.\n- 'request' - Attributes of - the API request([ref](/pkg/apis/admission/types.go#AdmissionRequest)).\n- - 'params' - Parameter resource referred to by - the policy binding being evaluated. Only populated - if the policy has a ParamKind.\n- 'namespaceObject' - - The namespace object that the incoming object - belongs to. The value is null for cluster-scoped - resources.\n- 'variables' - Map of composited - variables, from its name to its lazily evaluated - value.\n For example, a variable named 'foo' - can be accessed as 'variables.foo'.\n- 'authorizer' - - A CEL Authorizer. May be used to perform authorization - checks for the principal (user or service account) - of the request.\n See https://pkg.go.dev/k8s.io/apiserver/pkg/cel/library#Authz\n- - 'authorizer.requestResource' - A CEL ResourceCheck - constructed from the 'authorizer' and configured - with the\n request resource.\n\nThe `apiVersion`, - `kind`, `metadata.name` and `metadata.generateName` - are always accessible from the root of the\nobject. - No other metadata properties are accessible.\n\nOnly - property names of the form `[a-zA-Z_.-/][a-zA-Z0-9_.-/]*` - are accessible.\nAccessible property names are - escaped according to the following rules when - accessed in the expression:\n- '__' escapes - to '__underscores__'\n- '.' escapes to '__dot__'\n- - '-' escapes to '__dash__'\n- '/' escapes to - '__slash__'\n- Property names that exactly match - a CEL RESERVED keyword escape to '__{keyword}__'. - The keywords are:\n\t \"true\", \"false\", - \"null\", \"in\", \"as\", \"break\", \"const\", - \"continue\", \"else\", \"for\", \"function\", - \"if\",\n\t \"import\", \"let\", \"loop\", - \"package\", \"namespace\", \"return\".\nExamples:\n - \ - Expression accessing a property named \"namespace\": - {\"Expression\": \"object.__namespace__ > 0\"}\n - \ - Expression accessing a property named \"x-prop\": - {\"Expression\": \"object.x__dash__prop > 0\"}\n - \ - Expression accessing a property named \"redact__d\": - {\"Expression\": \"object.redact__underscores__d - > 0\"}\n\nEquality on arrays with list type - of 'set' or 'map' ignores element order, i.e. - [1, 2] == [2, 1].\nConcatenation on arrays with - x-kubernetes-list-type use the semantics of - the list type:\n - 'set': `X + Y` performs - a union where the array positions of all elements - in `X` are preserved and\n non-intersecting - elements in `Y` are appended, retaining their - partial order.\n - 'map': `X + Y` performs - a merge where the array positions of all keys - in `X` are preserved but the values\n are - overwritten by values in `Y` when the key sets - of `X` and `Y` intersect. Elements in `Y` with\n - \ non-intersecting keys are appended, retaining - their partial order.\nRequired." - type: string - message: - description: |- - Message represents the message displayed when validation fails. The message is required if the Expression contains - line breaks. The message must not contain line breaks. - If unset, the message is "failed rule: {Rule}". - e.g. "must be a URL with the host matching spec.host" - If the Expression contains line breaks. Message is required. - The message must not contain line breaks. - If unset, the message is "failed Expression: {Expression}". - type: string - messageExpression: - description: |- - messageExpression declares a CEL expression that evaluates to the validation failure message that is returned when this rule fails. - Since messageExpression is used as a failure message, it must evaluate to a string. - If both message and messageExpression are present on a validation, then messageExpression will be used if validation fails. - If messageExpression results in a runtime error, the runtime error is logged, and the validation failure message is produced - as if the messageExpression field were unset. If messageExpression evaluates to an empty string, a string with only spaces, or a string - that contains line breaks, then the validation failure message will also be produced as if the messageExpression field were unset, and - the fact that messageExpression produced an empty string/string with only spaces/string with line breaks will be logged. - messageExpression has access to all the same variables as the `expression` except for 'authorizer' and 'authorizer.requestResource'. - Example: - "object.x must be less than max ("+string(params.max)+")" - type: string - reason: - description: |- - Reason represents a machine-readable description of why this validation failed. - If this is the first validation in the list to fail, this reason, as well as the - corresponding HTTP response code, are used in the - HTTP response to the client. - The currently supported reasons are: "Unauthorized", "Forbidden", "Invalid", "RequestEntityTooLarge". - If not set, StatusReasonInvalid is used in the response to the client. - type: string - required: - - expression - type: object - type: array - generate: - default: false - description: |- - Generate specifies whether to generate a Kubernetes ValidatingAdmissionPolicy from the rule. - Optional. Defaults to "false" if not specified. - type: boolean - paramKind: - description: ParamKind is a tuple of Group Kind and - Version. - properties: - apiVersion: - description: |- - APIVersion is the API group version the resources belong to. - In format of "group/version". - Required. - type: string - kind: - description: |- - Kind is the API kind the resources belong to. - Required. - type: string - type: object - x-kubernetes-map-type: atomic - paramRef: - description: ParamRef references a parameter resource. - properties: - name: - description: |- - name is the name of the resource being referenced. - - One of `name` or `selector` must be set, but `name` and `selector` are - mutually exclusive properties. If one is set, the other must be unset. - - A single parameter used for all admission requests can be configured - by setting the `name` field, leaving `selector` blank, and setting namespace - if `paramKind` is namespace-scoped. - type: string - namespace: - description: |- - namespace is the namespace of the referenced resource. Allows limiting - the search for params to a specific namespace. Applies to both `name` and - `selector` fields. - - A per-namespace parameter may be used by specifying a namespace-scoped - `paramKind` in the policy and leaving this field empty. - - - If `paramKind` is cluster-scoped, this field MUST be unset. Setting this - field results in a configuration error. - - - If `paramKind` is namespace-scoped, the namespace of the object being - evaluated for admission will be used when this field is left unset. Take - care that if this is left empty the binding must not match any cluster-scoped - resources, which will result in an error. - type: string - parameterNotFoundAction: - description: |- - `parameterNotFoundAction` controls the behavior of the binding when the resource - exists, and name or selector is valid, but there are no parameters - matched by the binding. If the value is set to `Allow`, then no - matched parameters will be treated as successful validation by the binding. - If set to `Deny`, then no matched parameters will be subject to the - `failurePolicy` of the policy. - - Allowed values are `Allow` or `Deny` - - Required - type: string - selector: - description: |- - selector can be used to match multiple param objects based on their labels. - Supply selector: {} to match all resources of the ParamKind. - - If multiple params are found, they are all evaluated with the policy expressions - and the results are ANDed together. - - One of `name` or `selector` must be set, but `name` and `selector` are - mutually exclusive properties. If one is set, the other must be unset. - properties: - matchExpressions: - description: matchExpressions is a list of label - selector requirements. The requirements are - ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key that - the selector applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - type: object - x-kubernetes-map-type: atomic - variables: - description: |- - Variables contain definitions of variables that can be used in composition of other expressions. - Each variable is defined as a named CEL expression. - The variables defined here will be available under `variables` in other expressions of the policy. - items: - description: Variable is the definition of a variable - that is used for composition. A variable is defined - as a named expression. - properties: - expression: - description: |- - Expression is the expression that will be evaluated as the value of the variable. - The CEL expression has access to the same identifiers as the CEL expressions in Validation. - type: string - name: - description: |- - Name is the name of the variable. The name must be a valid CEL identifier and unique among all variables. - The variable can be accessed in other expressions through `variables` - For example, if name is "foo", the variable will be available as `variables.foo` - type: string - required: - - expression - - name - type: object - x-kubernetes-map-type: atomic - type: array - type: object - deny: - description: Deny defines conditions used to pass or fail - a validation rule. - properties: - conditions: - description: |- - Multiple conditions can be declared under an `any` or `all` statement. A direct list - of conditions (without `any` or `all` statements) is also supported for backwards compatibility - but will be deprecated in the next major release. - See: https://kyverno.io/docs/writing-policies/validate/#deny-rules - x-kubernetes-preserve-unknown-fields: true - type: object - failureAction: - description: |- - FailureAction defines if a validation policy rule violation should block - the admission review request (Enforce), or allow (Audit) the admission review request - and report an error in a policy report. Optional. - Allowed values are Audit or Enforce. - enum: - - Audit - - Enforce - type: string - failureActionOverrides: - description: |- - FailureActionOverrides is a Cluster Policy attribute that specifies FailureAction - namespace-wise. It overrides FailureAction for the specified namespaces. - items: - properties: - action: - description: ValidationFailureAction defines the policy - validation failure action - enum: - - audit - - enforce - - Audit - - Enforce - type: string - namespaceSelector: - description: |- - A label selector is a label query over a set of resources. The result of matchLabels and - matchExpressions are ANDed. An empty label selector matches all objects. A null - label selector matches no objects. - properties: - matchExpressions: - description: matchExpressions is a list of label - selector requirements. The requirements are - ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key that the - selector applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - namespaces: - items: - type: string - type: array - type: object - type: array - foreach: - description: ForEach applies validate rules to a list of - sub-elements by creating a context for each entry in the - list and looping over it to apply the specified logic. - items: - description: ForEachValidation applies validate rules - to a list of sub-elements by creating a context for - each entry in the list and looping over it to apply - the specified logic. - properties: - anyPattern: - description: |- - AnyPattern specifies list of validation patterns. At least one of the patterns - must be satisfied for the validation rule to succeed. - x-kubernetes-preserve-unknown-fields: true - context: - description: Context defines variables and data sources - that can be used during rule execution. - items: - description: |- - ContextEntry adds variables and data sources to a rule Context. Either a - ConfigMap reference or a APILookup must be provided. - oneOf: - - required: - - configMap - - required: - - apiCall - - required: - - imageRegistry - - required: - - variable - - required: - - globalReference - properties: - apiCall: - description: |- - APICall is an HTTP request to the Kubernetes API server, or other JSON web service. - The data returned is stored in the context with the name for the context entry. - properties: - data: - description: |- - The data object specifies the POST data sent to the server. - Only applicable when the method field is set to POST. - items: - description: RequestData contains the - HTTP POST data - properties: - key: - description: Key is a unique identifier - for the data value - type: string - value: - description: Value is the data value - x-kubernetes-preserve-unknown-fields: true - required: - - key - - value - type: object - type: array - default: - description: |- - Default is an optional arbitrary JSON object that the context - value is set to, if the apiCall returns error. - x-kubernetes-preserve-unknown-fields: true - jmesPath: - description: |- - JMESPath is an optional JSON Match Expression that can be used to - transform the JSON response returned from the server. For example - a JMESPath of "items | length(@)" applied to the API server response - for the URLPath "/apis/apps/v1/deployments" will return the total count - of deployments across all namespaces. - type: string - method: - default: GET - description: Method is the HTTP request - type (GET or POST). Defaults to GET. - enum: - - GET - - POST - type: string - service: - description: |- - Service is an API call to a JSON web service. - This is used for non-Kubernetes API server calls. - It's mutually exclusive with the URLPath field. - properties: - caBundle: - description: |- - CABundle is a PEM encoded CA bundle which will be used to validate - the server certificate. - type: string - headers: - description: Headers is a list of optional - HTTP headers to be included in the - request. - items: - properties: - key: - description: Key is the header - key - type: string - value: - description: Value is the header - value - type: string - required: - - key - - value - type: object - type: array - url: - description: |- - URL is the JSON web service URL. A typical form is - `https://{service}.{namespace}:{port}/{path}`. - type: string - required: - - url - type: object - urlPath: - description: |- - URLPath is the URL path to be used in the HTTP GET or POST request to the - Kubernetes API server (e.g. "/api/v1/namespaces" or "/apis/apps/v1/deployments"). - The format required is the same format used by the `kubectl get --raw` command. - See https://kyverno.io/docs/writing-policies/external-data-sources/#variables-from-kubernetes-api-server-calls - for details. - It's mutually exclusive with the Service field. - type: string - type: object - configMap: - description: ConfigMap is the ConfigMap reference. - properties: - name: - description: Name is the ConfigMap name. - type: string - namespace: - description: Namespace is the ConfigMap - namespace. - type: string - required: - - name - type: object - globalReference: - description: GlobalContextEntryReference is - a reference to a cached global context entry. - properties: - jmesPath: - description: |- - JMESPath is an optional JSON Match Expression that can be used to - transform the JSON response returned from the server. For example - a JMESPath of "items | length(@)" applied to the API server response - for the URLPath "/apis/apps/v1/deployments" will return the total count - of deployments across all namespaces. - type: string - name: - description: Name of the global context - entry - type: string - required: - - name - type: object - imageRegistry: - description: |- - ImageRegistry defines requests to an OCI/Docker V2 registry to fetch image - details. - properties: - imageRegistryCredentials: - description: ImageRegistryCredentials provides - credentials that will be used for authentication - with registry - properties: - allowInsecureRegistry: - description: AllowInsecureRegistry allows - insecure access to a registry. - type: boolean - providers: - description: |- - Providers specifies a list of OCI Registry names, whose authentication providers are provided. - It can be of one of these values: default,google,azure,amazon,github. - items: - description: ImageRegistryCredentialsProvidersType - provides the list of credential - providers required. - enum: - - default - - amazon - - azure - - google - - github - type: string - type: array - secrets: - description: |- - Secrets specifies a list of secrets that are provided for credentials. - Secrets must live in the Kyverno namespace. - items: - type: string - type: array - type: object - jmesPath: - description: |- - JMESPath is an optional JSON Match Expression that can be used to - transform the ImageData struct returned as a result of processing - the image reference. - type: string - reference: - description: |- - Reference is image reference to a container image in the registry. - Example: ghcr.io/kyverno/kyverno:latest - type: string - required: - - reference - type: object - name: - description: Name is the variable name. - type: string - variable: - description: Variable defines an arbitrary JMESPath - context variable that can be defined inline. - properties: - default: - description: |- - Default is an optional arbitrary JSON object that the variable may take if the JMESPath - expression evaluates to nil - x-kubernetes-preserve-unknown-fields: true - jmesPath: - description: |- - JMESPath is an optional JMESPath Expression that can be used to - transform the variable. - type: string - value: - description: Value is any arbitrary JSON - object representable in YAML or JSON form. - x-kubernetes-preserve-unknown-fields: true - type: object - required: - - name - type: object - type: array - deny: - description: Deny defines conditions used to pass - or fail a validation rule. - properties: - conditions: - description: |- - Multiple conditions can be declared under an `any` or `all` statement. A direct list - of conditions (without `any` or `all` statements) is also supported for backwards compatibility - but will be deprecated in the next major release. - See: https://kyverno.io/docs/writing-policies/validate/#deny-rules - x-kubernetes-preserve-unknown-fields: true - type: object - elementScope: - description: |- - ElementScope specifies whether to use the current list element as the scope for validation. Defaults to "true" if not specified. - When set to "false", "request.object" is used as the validation scope within the foreach - block to allow referencing other elements in the subtree. - type: boolean - foreach: - description: Foreach declares a nested foreach iterator - x-kubernetes-preserve-unknown-fields: true - list: - description: |- - List specifies a JMESPath expression that results in one or more elements - to which the validation logic is applied. - type: string - pattern: - description: Pattern specifies an overlay-style pattern - used to check resources. - x-kubernetes-preserve-unknown-fields: true - preconditions: - description: |- - AnyAllConditions are used to determine if a policy rule should be applied by evaluating a - set of conditions. The declaration can contain nested `any` or `all` statements. - See: https://kyverno.io/docs/writing-policies/preconditions/ - properties: - all: - description: |- - AllConditions enable variable-based conditional rule execution. This is useful for - finer control of when an rule is applied. A condition can reference object data - using JMESPath notation. - Here, all of the conditions need to pass - items: - description: Condition defines variable-based - conditional criteria for rule execution. - properties: - key: - description: Key is the context entry (using - JMESPath) for conditional rule evaluation. - x-kubernetes-preserve-unknown-fields: true - message: - description: Message is an optional display - message - type: string - operator: - description: |- - Operator is the conditional operation to perform. Valid operators are: - Equals, NotEquals, In, AnyIn, AllIn, NotIn, AnyNotIn, AllNotIn, GreaterThanOrEquals, - GreaterThan, LessThanOrEquals, LessThan, DurationGreaterThanOrEquals, DurationGreaterThan, - DurationLessThanOrEquals, DurationLessThan - enum: - - Equals - - NotEquals - - In - - AnyIn - - AllIn - - NotIn - - AnyNotIn - - AllNotIn - - GreaterThanOrEquals - - GreaterThan - - LessThanOrEquals - - LessThan - - DurationGreaterThanOrEquals - - DurationGreaterThan - - DurationLessThanOrEquals - - DurationLessThan - type: string - value: - description: |- - Value is the conditional value, or set of values. The values can be fixed set - or can be variables declared using JMESPath. - x-kubernetes-preserve-unknown-fields: true - type: object - type: array - any: - description: |- - AnyConditions enable variable-based conditional rule execution. This is useful for - finer control of when an rule is applied. A condition can reference object data - using JMESPath notation. - Here, at least one of the conditions need to pass - items: - description: Condition defines variable-based - conditional criteria for rule execution. - properties: - key: - description: Key is the context entry (using - JMESPath) for conditional rule evaluation. - x-kubernetes-preserve-unknown-fields: true - message: - description: Message is an optional display - message - type: string - operator: - description: |- - Operator is the conditional operation to perform. Valid operators are: - Equals, NotEquals, In, AnyIn, AllIn, NotIn, AnyNotIn, AllNotIn, GreaterThanOrEquals, - GreaterThan, LessThanOrEquals, LessThan, DurationGreaterThanOrEquals, DurationGreaterThan, - DurationLessThanOrEquals, DurationLessThan - enum: - - Equals - - NotEquals - - In - - AnyIn - - AllIn - - NotIn - - AnyNotIn - - AllNotIn - - GreaterThanOrEquals - - GreaterThan - - LessThanOrEquals - - LessThan - - DurationGreaterThanOrEquals - - DurationGreaterThan - - DurationLessThanOrEquals - - DurationLessThan - type: string - value: - description: |- - Value is the conditional value, or set of values. The values can be fixed set - or can be variables declared using JMESPath. - x-kubernetes-preserve-unknown-fields: true - type: object - type: array - type: object - x-kubernetes-preserve-unknown-fields: true - type: object - type: array - manifests: - description: Manifest specifies conditions for manifest - verification - properties: - annotationDomain: - description: AnnotationDomain is custom domain of annotation - for message and signature. Default is "cosign.sigstore.dev". - type: string - attestors: - description: Attestors specified the required attestors - (i.e. authorities) - items: - properties: - count: - description: |- - Count specifies the required number of entries that must match. If the count is null, all entries must match - (a logical AND). If the count is 1, at least one entry must match (a logical OR). If the count contains a - value N, then N must be less than or equal to the size of entries, and at least N entries must match. - minimum: 1 - type: integer - entries: - description: |- - Entries contains the available attestors. An attestor can be a static key, - attributes for keyless verification, or a nested attestor declaration. - items: - properties: - annotations: - additionalProperties: - type: string - description: |- - Annotations are used for image verification. - Every specified key-value pair must exist and match in the verified payload. - The payload may contain other key-value pairs. - type: object - attestor: - description: Attestor is a nested set of - Attestor used to specify a more complex - set of match authorities. - x-kubernetes-preserve-unknown-fields: true - certificates: - description: Certificates specifies one - or more certificates. - properties: - cert: - description: Cert is an optional PEM-encoded - public certificate. - type: string - certChain: - description: CertChain is an optional - PEM encoded set of certificates used - to verify. - type: string - ctlog: - description: |- - CTLog (certificate timestamp log) provides a configuration for validation of Signed Certificate - Timestamps (SCTs). If the value is unset, the default behavior by Cosign is used. - properties: - ignoreSCT: - description: |- - IgnoreSCT defines whether to use the Signed Certificate Timestamp (SCT) log to check for a certificate - timestamp. Default is false. Set to true if this was opted out during signing. - type: boolean - pubkey: - description: PubKey, if set, is - used to validate SCTs against - a custom source. - type: string - tsaCertChain: - description: |- - TSACertChain, if set, is the PEM-encoded certificate chain file for the RFC3161 timestamp authority. Must - contain the root CA certificate. Optionally may contain intermediate CA certificates, and - may contain the leaf TSA certificate if not present in the timestamurce. - type: string - type: object - rekor: - description: |- - Rekor provides configuration for the Rekor transparency log service. If an empty object - is provided the public instance of Rekor (https://rekor.sigstore.dev) is used. - properties: - ignoreTlog: - description: IgnoreTlog skips transparency - log verification. - type: boolean - pubkey: - description: |- - RekorPubKey is an optional PEM-encoded public key to use for a custom Rekor. - If set, this will be used to validate transparency log signatures from a custom Rekor. - type: string - url: - description: URL is the address - of the transparency log. Defaults - to the public Rekor log instance - https://rekor.sigstore.dev. - type: string - type: object - type: object - keyless: - description: |- - Keyless is a set of attribute used to verify a Sigstore keyless attestor. - See https://github.com/sigstore/cosign/blob/main/KEYLESS.md. - properties: - additionalExtensions: - additionalProperties: - type: string - description: AdditionalExtensions are - certificate-extensions used for keyless - signing. - type: object - ctlog: - description: |- - CTLog (certificate timestamp log) provides a configuration for validation of Signed Certificate - Timestamps (SCTs). If the value is unset, the default behavior by Cosign is used. - properties: - ignoreSCT: - description: |- - IgnoreSCT defines whether to use the Signed Certificate Timestamp (SCT) log to check for a certificate - timestamp. Default is false. Set to true if this was opted out during signing. - type: boolean - pubkey: - description: PubKey, if set, is - used to validate SCTs against - a custom source. - type: string - tsaCertChain: - description: |- - TSACertChain, if set, is the PEM-encoded certificate chain file for the RFC3161 timestamp authority. Must - contain the root CA certificate. Optionally may contain intermediate CA certificates, and - may contain the leaf TSA certificate if not present in the timestamurce. - type: string - type: object - issuer: - description: Issuer is the certificate - issuer used for keyless signing. - type: string - issuerRegExp: - description: IssuerRegExp is the regular - expression to match certificate issuer - used for keyless signing. - type: string - rekor: - description: |- - Rekor provides configuration for the Rekor transparency log service. If an empty object - is provided the public instance of Rekor (https://rekor.sigstore.dev) is used. - properties: - ignoreTlog: - description: IgnoreTlog skips transparency - log verification. - type: boolean - pubkey: - description: |- - RekorPubKey is an optional PEM-encoded public key to use for a custom Rekor. - If set, this will be used to validate transparency log signatures from a custom Rekor. - type: string - url: - description: URL is the address - of the transparency log. Defaults - to the public Rekor log instance - https://rekor.sigstore.dev. - type: string - type: object - roots: - description: |- - Roots is an optional set of PEM encoded trusted root certificates. - If not provided, the system roots are used. - type: string - subject: - description: Subject is the verified - identity used for keyless signing, - for example the email address. - type: string - subjectRegExp: - description: SubjectRegExp is the regular - expression to match identity used - for keyless signing, for example the - email address. - type: string - type: object - keys: - description: Keys specifies one or more - public keys. - properties: - ctlog: - description: |- - CTLog (certificate timestamp log) provides a configuration for validation of Signed Certificate - Timestamps (SCTs). If the value is unset, the default behavior by Cosign is used. - properties: - ignoreSCT: - description: |- - IgnoreSCT defines whether to use the Signed Certificate Timestamp (SCT) log to check for a certificate - timestamp. Default is false. Set to true if this was opted out during signing. - type: boolean - pubkey: - description: PubKey, if set, is - used to validate SCTs against - a custom source. - type: string - tsaCertChain: - description: |- - TSACertChain, if set, is the PEM-encoded certificate chain file for the RFC3161 timestamp authority. Must - contain the root CA certificate. Optionally may contain intermediate CA certificates, and - may contain the leaf TSA certificate if not present in the timestamurce. - type: string - type: object - kms: - description: |- - KMS provides the URI to the public key stored in a Key Management System. See: - https://github.com/sigstore/cosign/blob/main/KMS.md - type: string - publicKeys: - description: |- - Keys is a set of X.509 public keys used to verify image signatures. The keys can be directly - specified or can be a variable reference to a key specified in a ConfigMap (see - https://kyverno.io/docs/writing-policies/variables/), or reference a standard Kubernetes Secret - elsewhere in the cluster by specifying it in the format "k8s:///". - The named Secret must specify a key `cosign.pub` containing the public key used for - verification, (see https://github.com/sigstore/cosign/blob/main/KMS.md#kubernetes-secret). - When multiple keys are specified each key is processed as a separate staticKey entry - (.attestors[*].entries.keys) within the set of attestors and the count is applied across the keys. - type: string - rekor: - description: |- - Rekor provides configuration for the Rekor transparency log service. If an empty object - is provided the public instance of Rekor (https://rekor.sigstore.dev) is used. - properties: - ignoreTlog: - description: IgnoreTlog skips transparency - log verification. - type: boolean - pubkey: - description: |- - RekorPubKey is an optional PEM-encoded public key to use for a custom Rekor. - If set, this will be used to validate transparency log signatures from a custom Rekor. - type: string - url: - description: URL is the address - of the transparency log. Defaults - to the public Rekor log instance - https://rekor.sigstore.dev. - type: string - type: object - secret: - description: Reference to a Secret resource - that contains a public key - properties: - name: - description: Name of the secret. - The provided secret must contain - a key named cosign.pub. - type: string - namespace: - description: Namespace name where - the Secret exists. - type: string - required: - - name - - namespace - type: object - signatureAlgorithm: - default: sha256 - description: Deprecated. Use attestor.signatureAlgorithm - instead. - type: string - type: object - repository: - description: |- - Repository is an optional alternate OCI repository to use for signatures and attestations that match this rule. - If specified Repository will override other OCI image repository locations for this Attestor. - type: string - signatureAlgorithm: - default: sha256 - description: Specify signature algorithm - for public keys. Supported values are - sha224, sha256, sha384 and sha512. - type: string - type: object - type: array - type: object - type: array - dryRun: - description: DryRun configuration - properties: - enable: - type: boolean - namespace: - type: string - type: object - ignoreFields: - description: Fields which will be ignored while comparing - manifests. - items: - properties: - fields: - items: - type: string - type: array - objects: - items: - properties: - group: - type: string - kind: - type: string - name: - type: string - namespace: - type: string - version: - type: string - type: object - type: array - type: object - type: array - repository: - description: |- - Repository is an optional alternate OCI repository to use for resource bundle reference. - The repository can be overridden per Attestor or Attestation. - type: string - type: object - message: - description: Message specifies a custom message to be displayed - on failure. - type: string - pattern: - description: Pattern specifies an overlay-style pattern - used to check resources. - x-kubernetes-preserve-unknown-fields: true - podSecurity: - description: |- - PodSecurity applies exemptions for Kubernetes Pod Security admission - by specifying exclusions for Pod Security Standards controls. - properties: - exclude: - description: Exclude specifies the Pod Security Standard - controls to be excluded. - items: - description: PodSecurityStandard specifies the Pod - Security Standard controls to be excluded. - properties: - controlName: - description: |- - ControlName specifies the name of the Pod Security Standard control. - See: https://kubernetes.io/docs/concepts/security/pod-security-standards/ - enum: - - HostProcess - - Host Namespaces - - Privileged Containers - - Capabilities - - HostPath Volumes - - Host Ports - - AppArmor - - SELinux - - /proc Mount Type - - Seccomp - - Sysctls - - Volume Types - - Privilege Escalation - - Running as Non-root - - Running as Non-root user - type: string - images: - description: |- - Images selects matching containers and applies the container level PSS. - Each image is the image name consisting of the registry address, repository, image, and tag. - Empty list matches no containers, PSS checks are applied at the pod level only. - Wildcards ('*' and '?') are allowed. See: https://kubernetes.io/docs/concepts/containers/images. - items: - type: string - type: array - restrictedField: - description: |- - RestrictedField selects the field for the given Pod Security Standard control. - When not set, all restricted fields for the control are selected. - type: string - values: - description: Values defines the allowed values - that can be excluded. - items: - type: string - type: array - required: - - controlName - type: object - type: array - level: - description: |- - Level defines the Pod Security Standard level to be applied to workloads. - Allowed values are privileged, baseline, and restricted. - enum: - - privileged - - baseline - - restricted - type: string - version: - description: |- - Version defines the Pod Security Standard versions that Kubernetes supports. - Allowed values are v1.19, v1.20, v1.21, v1.22, v1.23, v1.24, v1.25, v1.26, v1.27, v1.28, v1.29, latest. Defaults to latest. - enum: - - v1.19 - - v1.20 - - v1.21 - - v1.22 - - v1.23 - - v1.24 - - v1.25 - - v1.26 - - v1.27 - - v1.28 - - v1.29 - - latest - type: string - type: object - type: object - verifyImages: - description: VerifyImages is used to verify image signatures - and mutate them to add a digest - items: - description: |- - ImageVerification validates that images that match the specified pattern - are signed with the supplied public key. Once the image is verified it is - mutated to include the SHA digest retrieved during the registration. - properties: - additionalExtensions: - additionalProperties: - type: string - description: Deprecated. - type: object - annotations: - additionalProperties: - type: string - description: Deprecated. Use annotations per Attestor - instead. - type: object - attestations: - description: |- - Attestations are optional checks for signed in-toto Statements used to verify the image. - See https://github.com/in-toto/attestation. Kyverno fetches signed attestations from the - OCI registry and decodes them into a list of Statement declarations. - items: - description: |- - Attestation are checks for signed in-toto Statements that are used to verify the image. - See https://github.com/in-toto/attestation. Kyverno fetches signed attestations from the - OCI registry and decodes them into a list of Statements. - properties: - attestors: - description: Attestors specify the required attestors - (i.e. authorities). - items: - properties: - count: - description: |- - Count specifies the required number of entries that must match. If the count is null, all entries must match - (a logical AND). If the count is 1, at least one entry must match (a logical OR). If the count contains a - value N, then N must be less than or equal to the size of entries, and at least N entries must match. - minimum: 1 - type: integer - entries: - description: |- - Entries contains the available attestors. An attestor can be a static key, - attributes for keyless verification, or a nested attestor declaration. - items: - properties: - annotations: - additionalProperties: - type: string - description: |- - Annotations are used for image verification. - Every specified key-value pair must exist and match in the verified payload. - The payload may contain other key-value pairs. - type: object - attestor: - description: Attestor is a nested set - of Attestor used to specify a more - complex set of match authorities. - x-kubernetes-preserve-unknown-fields: true - certificates: - description: Certificates specifies - one or more certificates. - properties: - cert: - description: Cert is an optional - PEM-encoded public certificate. - type: string - certChain: - description: CertChain is an optional - PEM encoded set of certificates - used to verify. - type: string - ctlog: - description: |- - CTLog (certificate timestamp log) provides a configuration for validation of Signed Certificate - Timestamps (SCTs). If the value is unset, the default behavior by Cosign is used. - properties: - ignoreSCT: - description: |- - IgnoreSCT defines whether to use the Signed Certificate Timestamp (SCT) log to check for a certificate - timestamp. Default is false. Set to true if this was opted out during signing. - type: boolean - pubkey: - description: PubKey, if set, - is used to validate SCTs against - a custom source. - type: string - tsaCertChain: - description: |- - TSACertChain, if set, is the PEM-encoded certificate chain file for the RFC3161 timestamp authority. Must - contain the root CA certificate. Optionally may contain intermediate CA certificates, and - may contain the leaf TSA certificate if not present in the timestamurce. - type: string - type: object - rekor: - description: |- - Rekor provides configuration for the Rekor transparency log service. If an empty object - is provided the public instance of Rekor (https://rekor.sigstore.dev) is used. - properties: - ignoreTlog: - description: IgnoreTlog skips - transparency log verification. - type: boolean - pubkey: - description: |- - RekorPubKey is an optional PEM-encoded public key to use for a custom Rekor. - If set, this will be used to validate transparency log signatures from a custom Rekor. - type: string - url: - description: URL is the address - of the transparency log. Defaults - to the public Rekor log instance - https://rekor.sigstore.dev. - type: string - type: object - type: object - keyless: - description: |- - Keyless is a set of attribute used to verify a Sigstore keyless attestor. - See https://github.com/sigstore/cosign/blob/main/KEYLESS.md. - properties: - additionalExtensions: - additionalProperties: - type: string - description: AdditionalExtensions - are certificate-extensions used - for keyless signing. - type: object - ctlog: - description: |- - CTLog (certificate timestamp log) provides a configuration for validation of Signed Certificate - Timestamps (SCTs). If the value is unset, the default behavior by Cosign is used. - properties: - ignoreSCT: - description: |- - IgnoreSCT defines whether to use the Signed Certificate Timestamp (SCT) log to check for a certificate - timestamp. Default is false. Set to true if this was opted out during signing. - type: boolean - pubkey: - description: PubKey, if set, - is used to validate SCTs against - a custom source. - type: string - tsaCertChain: - description: |- - TSACertChain, if set, is the PEM-encoded certificate chain file for the RFC3161 timestamp authority. Must - contain the root CA certificate. Optionally may contain intermediate CA certificates, and - may contain the leaf TSA certificate if not present in the timestamurce. - type: string - type: object - issuer: - description: Issuer is the certificate - issuer used for keyless signing. - type: string - issuerRegExp: - description: IssuerRegExp is the - regular expression to match certificate - issuer used for keyless signing. - type: string - rekor: - description: |- - Rekor provides configuration for the Rekor transparency log service. If an empty object - is provided the public instance of Rekor (https://rekor.sigstore.dev) is used. - properties: - ignoreTlog: - description: IgnoreTlog skips - transparency log verification. - type: boolean - pubkey: - description: |- - RekorPubKey is an optional PEM-encoded public key to use for a custom Rekor. - If set, this will be used to validate transparency log signatures from a custom Rekor. - type: string - url: - description: URL is the address - of the transparency log. Defaults - to the public Rekor log instance - https://rekor.sigstore.dev. - type: string - type: object - roots: - description: |- - Roots is an optional set of PEM encoded trusted root certificates. - If not provided, the system roots are used. - type: string - subject: - description: Subject is the verified - identity used for keyless signing, - for example the email address. - type: string - subjectRegExp: - description: SubjectRegExp is the - regular expression to match identity - used for keyless signing, for - example the email address. - type: string - type: object - keys: - description: Keys specifies one or more - public keys. - properties: - ctlog: - description: |- - CTLog (certificate timestamp log) provides a configuration for validation of Signed Certificate - Timestamps (SCTs). If the value is unset, the default behavior by Cosign is used. - properties: - ignoreSCT: - description: |- - IgnoreSCT defines whether to use the Signed Certificate Timestamp (SCT) log to check for a certificate - timestamp. Default is false. Set to true if this was opted out during signing. - type: boolean - pubkey: - description: PubKey, if set, - is used to validate SCTs against - a custom source. - type: string - tsaCertChain: - description: |- - TSACertChain, if set, is the PEM-encoded certificate chain file for the RFC3161 timestamp authority. Must - contain the root CA certificate. Optionally may contain intermediate CA certificates, and - may contain the leaf TSA certificate if not present in the timestamurce. - type: string - type: object - kms: - description: |- - KMS provides the URI to the public key stored in a Key Management System. See: - https://github.com/sigstore/cosign/blob/main/KMS.md - type: string - publicKeys: - description: |- - Keys is a set of X.509 public keys used to verify image signatures. The keys can be directly - specified or can be a variable reference to a key specified in a ConfigMap (see - https://kyverno.io/docs/writing-policies/variables/), or reference a standard Kubernetes Secret - elsewhere in the cluster by specifying it in the format "k8s:///". - The named Secret must specify a key `cosign.pub` containing the public key used for - verification, (see https://github.com/sigstore/cosign/blob/main/KMS.md#kubernetes-secret). - When multiple keys are specified each key is processed as a separate staticKey entry - (.attestors[*].entries.keys) within the set of attestors and the count is applied across the keys. - type: string - rekor: - description: |- - Rekor provides configuration for the Rekor transparency log service. If an empty object - is provided the public instance of Rekor (https://rekor.sigstore.dev) is used. - properties: - ignoreTlog: - description: IgnoreTlog skips - transparency log verification. - type: boolean - pubkey: - description: |- - RekorPubKey is an optional PEM-encoded public key to use for a custom Rekor. - If set, this will be used to validate transparency log signatures from a custom Rekor. - type: string - url: - description: URL is the address - of the transparency log. Defaults - to the public Rekor log instance - https://rekor.sigstore.dev. - type: string - type: object - secret: - description: Reference to a Secret - resource that contains a public - key - properties: - name: - description: Name of the secret. - The provided secret must contain - a key named cosign.pub. - type: string - namespace: - description: Namespace name - where the Secret exists. - type: string - required: - - name - - namespace - type: object - signatureAlgorithm: - default: sha256 - description: Deprecated. Use attestor.signatureAlgorithm - instead. - type: string - type: object - repository: - description: |- - Repository is an optional alternate OCI repository to use for signatures and attestations that match this rule. - If specified Repository will override other OCI image repository locations for this Attestor. - type: string - signatureAlgorithm: - default: sha256 - description: Specify signature algorithm - for public keys. Supported values - are sha224, sha256, sha384 and sha512. - type: string - type: object - type: array - type: object - type: array - conditions: - description: |- - Conditions are used to verify attributes within a Predicate. If no Conditions are specified - the attestation check is satisfied as long there are predicates that match the predicate type. - items: - description: |- - AnyAllConditions consists of conditions wrapped denoting a logical criteria to be fulfilled. - AnyConditions get fulfilled when at least one of its sub-conditions passes. - AllConditions get fulfilled only when all of its sub-conditions pass. - properties: - all: - description: |- - AllConditions enable variable-based conditional rule execution. This is useful for - finer control of when an rule is applied. A condition can reference object data - using JMESPath notation. - Here, all of the conditions need to pass - items: - description: Condition defines variable-based - conditional criteria for rule execution. - properties: - key: - description: Key is the context entry - (using JMESPath) for conditional rule - evaluation. - x-kubernetes-preserve-unknown-fields: true - message: - description: Message is an optional - display message - type: string - operator: - description: |- - Operator is the conditional operation to perform. Valid operators are: - Equals, NotEquals, In, AnyIn, AllIn, NotIn, AnyNotIn, AllNotIn, GreaterThanOrEquals, - GreaterThan, LessThanOrEquals, LessThan, DurationGreaterThanOrEquals, DurationGreaterThan, - DurationLessThanOrEquals, DurationLessThan - enum: - - Equals - - NotEquals - - In - - AnyIn - - AllIn - - NotIn - - AnyNotIn - - AllNotIn - - GreaterThanOrEquals - - GreaterThan - - LessThanOrEquals - - LessThan - - DurationGreaterThanOrEquals - - DurationGreaterThan - - DurationLessThanOrEquals - - DurationLessThan - type: string - value: - description: |- - Value is the conditional value, or set of values. The values can be fixed set - or can be variables declared using JMESPath. - x-kubernetes-preserve-unknown-fields: true - type: object - type: array - any: - description: |- - AnyConditions enable variable-based conditional rule execution. This is useful for - finer control of when an rule is applied. A condition can reference object data - using JMESPath notation. - Here, at least one of the conditions need to pass - items: - description: Condition defines variable-based - conditional criteria for rule execution. - properties: - key: - description: Key is the context entry - (using JMESPath) for conditional rule - evaluation. - x-kubernetes-preserve-unknown-fields: true - message: - description: Message is an optional - display message - type: string - operator: - description: |- - Operator is the conditional operation to perform. Valid operators are: - Equals, NotEquals, In, AnyIn, AllIn, NotIn, AnyNotIn, AllNotIn, GreaterThanOrEquals, - GreaterThan, LessThanOrEquals, LessThan, DurationGreaterThanOrEquals, DurationGreaterThan, - DurationLessThanOrEquals, DurationLessThan - enum: - - Equals - - NotEquals - - In - - AnyIn - - AllIn - - NotIn - - AnyNotIn - - AllNotIn - - GreaterThanOrEquals - - GreaterThan - - LessThanOrEquals - - LessThan - - DurationGreaterThanOrEquals - - DurationGreaterThan - - DurationLessThanOrEquals - - DurationLessThan - type: string - value: - description: |- - Value is the conditional value, or set of values. The values can be fixed set - or can be variables declared using JMESPath. - x-kubernetes-preserve-unknown-fields: true - type: object - type: array - type: object - type: array - name: - description: Name is the variable name. - type: string - predicateType: - description: Deprecated in favour of 'Type', to - be removed soon - type: string - type: - description: Type defines the type of attestation - contained within the Statement. - type: string - type: object - type: array - attestors: - description: Attestors specified the required attestors - (i.e. authorities) - items: - properties: - count: - description: |- - Count specifies the required number of entries that must match. If the count is null, all entries must match - (a logical AND). If the count is 1, at least one entry must match (a logical OR). If the count contains a - value N, then N must be less than or equal to the size of entries, and at least N entries must match. - minimum: 1 - type: integer - entries: - description: |- - Entries contains the available attestors. An attestor can be a static key, - attributes for keyless verification, or a nested attestor declaration. - items: - properties: - annotations: - additionalProperties: - type: string - description: |- - Annotations are used for image verification. - Every specified key-value pair must exist and match in the verified payload. - The payload may contain other key-value pairs. - type: object - attestor: - description: Attestor is a nested set of Attestor - used to specify a more complex set of match - authorities. - x-kubernetes-preserve-unknown-fields: true - certificates: - description: Certificates specifies one or - more certificates. - properties: - cert: - description: Cert is an optional PEM-encoded - public certificate. - type: string - certChain: - description: CertChain is an optional - PEM encoded set of certificates used - to verify. - type: string - ctlog: - description: |- - CTLog (certificate timestamp log) provides a configuration for validation of Signed Certificate - Timestamps (SCTs). If the value is unset, the default behavior by Cosign is used. - properties: - ignoreSCT: - description: |- - IgnoreSCT defines whether to use the Signed Certificate Timestamp (SCT) log to check for a certificate - timestamp. Default is false. Set to true if this was opted out during signing. - type: boolean - pubkey: - description: PubKey, if set, is used - to validate SCTs against a custom - source. - type: string - tsaCertChain: - description: |- - TSACertChain, if set, is the PEM-encoded certificate chain file for the RFC3161 timestamp authority. Must - contain the root CA certificate. Optionally may contain intermediate CA certificates, and - may contain the leaf TSA certificate if not present in the timestamurce. - type: string - type: object - rekor: - description: |- - Rekor provides configuration for the Rekor transparency log service. If an empty object - is provided the public instance of Rekor (https://rekor.sigstore.dev) is used. - properties: - ignoreTlog: - description: IgnoreTlog skips transparency - log verification. - type: boolean - pubkey: - description: |- - RekorPubKey is an optional PEM-encoded public key to use for a custom Rekor. - If set, this will be used to validate transparency log signatures from a custom Rekor. - type: string - url: - description: URL is the address of - the transparency log. Defaults to - the public Rekor log instance https://rekor.sigstore.dev. - type: string - type: object - type: object - keyless: - description: |- - Keyless is a set of attribute used to verify a Sigstore keyless attestor. - See https://github.com/sigstore/cosign/blob/main/KEYLESS.md. - properties: - additionalExtensions: - additionalProperties: - type: string - description: AdditionalExtensions are - certificate-extensions used for keyless - signing. - type: object - ctlog: - description: |- - CTLog (certificate timestamp log) provides a configuration for validation of Signed Certificate - Timestamps (SCTs). If the value is unset, the default behavior by Cosign is used. - properties: - ignoreSCT: - description: |- - IgnoreSCT defines whether to use the Signed Certificate Timestamp (SCT) log to check for a certificate - timestamp. Default is false. Set to true if this was opted out during signing. - type: boolean - pubkey: - description: PubKey, if set, is used - to validate SCTs against a custom - source. - type: string - tsaCertChain: - description: |- - TSACertChain, if set, is the PEM-encoded certificate chain file for the RFC3161 timestamp authority. Must - contain the root CA certificate. Optionally may contain intermediate CA certificates, and - may contain the leaf TSA certificate if not present in the timestamurce. - type: string - type: object - issuer: - description: Issuer is the certificate - issuer used for keyless signing. - type: string - issuerRegExp: - description: IssuerRegExp is the regular - expression to match certificate issuer - used for keyless signing. - type: string - rekor: - description: |- - Rekor provides configuration for the Rekor transparency log service. If an empty object - is provided the public instance of Rekor (https://rekor.sigstore.dev) is used. - properties: - ignoreTlog: - description: IgnoreTlog skips transparency - log verification. - type: boolean - pubkey: - description: |- - RekorPubKey is an optional PEM-encoded public key to use for a custom Rekor. - If set, this will be used to validate transparency log signatures from a custom Rekor. - type: string - url: - description: URL is the address of - the transparency log. Defaults to - the public Rekor log instance https://rekor.sigstore.dev. - type: string - type: object - roots: - description: |- - Roots is an optional set of PEM encoded trusted root certificates. - If not provided, the system roots are used. - type: string - subject: - description: Subject is the verified identity - used for keyless signing, for example - the email address. - type: string - subjectRegExp: - description: SubjectRegExp is the regular - expression to match identity used for - keyless signing, for example the email - address. - type: string - type: object - keys: - description: Keys specifies one or more public - keys. - properties: - ctlog: - description: |- - CTLog (certificate timestamp log) provides a configuration for validation of Signed Certificate - Timestamps (SCTs). If the value is unset, the default behavior by Cosign is used. - properties: - ignoreSCT: - description: |- - IgnoreSCT defines whether to use the Signed Certificate Timestamp (SCT) log to check for a certificate - timestamp. Default is false. Set to true if this was opted out during signing. - type: boolean - pubkey: - description: PubKey, if set, is used - to validate SCTs against a custom - source. - type: string - tsaCertChain: - description: |- - TSACertChain, if set, is the PEM-encoded certificate chain file for the RFC3161 timestamp authority. Must - contain the root CA certificate. Optionally may contain intermediate CA certificates, and - may contain the leaf TSA certificate if not present in the timestamurce. - type: string - type: object - kms: - description: |- - KMS provides the URI to the public key stored in a Key Management System. See: - https://github.com/sigstore/cosign/blob/main/KMS.md - type: string - publicKeys: - description: |- - Keys is a set of X.509 public keys used to verify image signatures. The keys can be directly - specified or can be a variable reference to a key specified in a ConfigMap (see - https://kyverno.io/docs/writing-policies/variables/), or reference a standard Kubernetes Secret - elsewhere in the cluster by specifying it in the format "k8s:///". - The named Secret must specify a key `cosign.pub` containing the public key used for - verification, (see https://github.com/sigstore/cosign/blob/main/KMS.md#kubernetes-secret). - When multiple keys are specified each key is processed as a separate staticKey entry - (.attestors[*].entries.keys) within the set of attestors and the count is applied across the keys. - type: string - rekor: - description: |- - Rekor provides configuration for the Rekor transparency log service. If an empty object - is provided the public instance of Rekor (https://rekor.sigstore.dev) is used. - properties: - ignoreTlog: - description: IgnoreTlog skips transparency - log verification. - type: boolean - pubkey: - description: |- - RekorPubKey is an optional PEM-encoded public key to use for a custom Rekor. - If set, this will be used to validate transparency log signatures from a custom Rekor. - type: string - url: - description: URL is the address of - the transparency log. Defaults to - the public Rekor log instance https://rekor.sigstore.dev. - type: string - type: object - secret: - description: Reference to a Secret resource - that contains a public key - properties: - name: - description: Name of the secret. The - provided secret must contain a key - named cosign.pub. - type: string - namespace: - description: Namespace name where - the Secret exists. - type: string - required: - - name - - namespace - type: object - signatureAlgorithm: - default: sha256 - description: Deprecated. Use attestor.signatureAlgorithm - instead. - type: string - type: object - repository: - description: |- - Repository is an optional alternate OCI repository to use for signatures and attestations that match this rule. - If specified Repository will override other OCI image repository locations for this Attestor. - type: string - signatureAlgorithm: - default: sha256 - description: Specify signature algorithm for - public keys. Supported values are sha224, - sha256, sha384 and sha512. - type: string - type: object - type: array - type: object - type: array - cosignOCI11: - description: |- - CosignOCI11 enables the experimental OCI 1.1 behaviour in cosign image verification. - Defaults to false. - type: boolean - failureAction: - description: Allowed values are Audit or Enforce. - enum: - - Audit - - Enforce - type: string - image: - description: Deprecated. Use ImageReferences instead. - type: string - imageReferences: - description: |- - ImageReferences is a list of matching image reference patterns. At least one pattern in the - list must match the image for the rule to apply. Each image reference consists of a registry - address (defaults to docker.io), repository, image, and tag (defaults to latest). - Wildcards ('*' and '?') are allowed. See: https://kubernetes.io/docs/concepts/containers/images. - items: - type: string - type: array - imageRegistryCredentials: - description: ImageRegistryCredentials provides credentials - that will be used for authentication with registry. - properties: - allowInsecureRegistry: - description: AllowInsecureRegistry allows insecure - access to a registry. - type: boolean - providers: - description: |- - Providers specifies a list of OCI Registry names, whose authentication providers are provided. - It can be of one of these values: default,google,azure,amazon,github. - items: - description: ImageRegistryCredentialsProvidersType - provides the list of credential providers required. - enum: - - default - - amazon - - azure - - google - - github - type: string - type: array - secrets: - description: |- - Secrets specifies a list of secrets that are provided for credentials. - Secrets must live in the Kyverno namespace. - items: - type: string - type: array - type: object - issuer: - description: Deprecated. Use KeylessAttestor instead. - type: string - key: - description: Deprecated. Use StaticKeyAttestor instead. - type: string - mutateDigest: - default: true - description: |- - MutateDigest enables replacement of image tags with digests. - Defaults to true. - type: boolean - repository: - description: |- - Repository is an optional alternate OCI repository to use for image signatures and attestations that match this rule. - If specified Repository will override the default OCI image repository configured for the installation. - The repository can also be overridden per Attestor or Attestation. - type: string - required: - default: true - description: Required validates that images are verified - i.e. have matched passed a signature or attestation - check. - type: boolean - roots: - description: Deprecated. Use KeylessAttestor instead. - type: string - skipImageReferences: - description: |- - SkipImageReferences is a list of matching image reference patterns that should be skipped. - At least one pattern in the list must match the image for the rule to be skipped. Each image reference - consists of a registry address (defaults to docker.io), repository, image, and tag (defaults to latest). - Wildcards ('*' and '?') are allowed. See: https://kubernetes.io/docs/concepts/containers/images. - items: - type: string - type: array - subject: - description: Deprecated. Use KeylessAttestor instead. - type: string - type: - description: |- - Type specifies the method of signature validation. The allowed options - are Cosign, Sigstore Bundle and Notary. By default Cosign is used if a type is not specified. - enum: - - Cosign - - SigstoreBundle - - Notary - type: string - useCache: - default: true - description: UseCache enables caching of image verify - responses for this rule. - type: boolean - validate: - description: |- - Validation checks conditions across multiple image - verification attestations or context entries - properties: - deny: - description: Deny defines conditions used to pass - or fail a validation rule. - properties: - conditions: - description: |- - Multiple conditions can be declared under an `any` or `all` statement. A direct list - of conditions (without `any` or `all` statements) is also supported for backwards compatibility - but will be deprecated in the next major release. - See: https://kyverno.io/docs/writing-policies/validate/#deny-rules - x-kubernetes-preserve-unknown-fields: true - type: object - message: - description: Message specifies a custom message to - be displayed on failure. - type: string - type: object - verifyDigest: - default: true - description: VerifyDigest validates that images have a - digest. - type: boolean - type: object - type: array - required: - - match - - name - type: object - type: array - schemaValidation: - description: Deprecated. - type: boolean - useServerSideApply: - description: |- - UseServerSideApply controls whether to use server-side apply for generate rules - If is set to "true" create & update for generate rules will use apply instead of create/update. - Defaults to "false" if not specified. - type: boolean - validationFailureAction: - default: Audit - description: Deprecated, use validationFailureAction under the validate - rule instead. - enum: - - audit - - enforce - - Audit - - Enforce - type: string - validationFailureActionOverrides: - description: Deprecated, use validationFailureActionOverrides under - the validate rule instead. - items: - properties: - action: - description: ValidationFailureAction defines the policy validation - failure action - enum: - - audit - - enforce - - Audit - - Enforce - type: string - namespaceSelector: - description: |- - A label selector is a label query over a set of resources. The result of matchLabels and - matchExpressions are ANDed. An empty label selector matches all objects. A null - label selector matches no objects. - properties: - matchExpressions: - description: matchExpressions is a list of label selector - requirements. The requirements are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key that the selector - applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - namespaces: - items: - type: string - type: array - type: object - type: array - webhookConfiguration: - description: WebhookConfiguration specifies the custom configuration - for Kubernetes admission webhookconfiguration. - properties: - failurePolicy: - description: |- - FailurePolicy defines how unexpected policy errors and webhook response timeout errors are handled. - Rules within the same policy share the same failure behavior. - This field should not be accessed directly, instead `GetFailurePolicy()` should be used. - Allowed values are Ignore or Fail. Defaults to Fail. - enum: - - Ignore - - Fail - type: string - matchConditions: - description: |- - MatchCondition configures admission webhook matchConditions. - Requires Kubernetes 1.27 or later. - items: - description: MatchCondition represents a condition which must - by fulfilled for a request to be sent to a webhook. - properties: - expression: - description: |- - Expression represents the expression which will be evaluated by CEL. Must evaluate to bool. - CEL expressions have access to the contents of the AdmissionRequest and Authorizer, organized into CEL variables: - - 'object' - The object from the incoming request. The value is null for DELETE requests. - 'oldObject' - The existing object. The value is null for CREATE requests. - 'request' - Attributes of the admission request(/pkg/apis/admission/types.go#AdmissionRequest). - 'authorizer' - A CEL Authorizer. May be used to perform authorization checks for the principal (user or service account) of the request. - See https://pkg.go.dev/k8s.io/apiserver/pkg/cel/library#Authz - 'authorizer.requestResource' - A CEL ResourceCheck constructed from the 'authorizer' and configured with the - request resource. - Documentation on CEL: https://kubernetes.io/docs/reference/using-api/cel/ - - Required. - type: string - name: - description: |- - Name is an identifier for this match condition, used for strategic merging of MatchConditions, - as well as providing an identifier for logging purposes. A good name should be descriptive of - the associated expression. - Name must be a qualified name consisting of alphanumeric characters, '-', '_' or '.', and - must start and end with an alphanumeric character (e.g. 'MyName', or 'my.name', or - '123-abc', regex used for validation is '([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9]') with an - optional DNS subdomain prefix and '/' (e.g. 'example.com/MyName') - - Required. - type: string - required: - - expression - - name - type: object - type: array - timeoutSeconds: - description: |- - TimeoutSeconds specifies the maximum time in seconds allowed to apply this policy. - After the configured time expires, the admission request may fail, or may simply ignore the policy results, - based on the failure policy. The default timeout is 10s, the value must be between 1 and 30 seconds. - format: int32 - type: integer - type: object - webhookTimeoutSeconds: - description: Deprecated, use webhookTimeoutSeconds under webhookConfiguration - instead. - format: int32 - type: integer - type: object - status: - description: Status contains policy runtime data. - properties: - autogen: - description: AutogenStatus contains autogen status information. - properties: - rules: - description: Rules is a list of Rule instances. It contains auto - generated rules added for pod controllers - items: - description: |- - Rule defines a validation, mutation, or generation control for matching resources. - Each rules contains a match declaration to select resources, and an optional exclude - declaration to specify which resources to exclude. - properties: - celPreconditions: - description: |- - CELPreconditions are used to determine if a policy rule should be applied by evaluating a - set of CEL conditions. It can only be used with the validate.cel subrule - items: - description: MatchCondition represents a condition which - must by fulfilled for a request to be sent to a webhook. - properties: - expression: - description: |- - Expression represents the expression which will be evaluated by CEL. Must evaluate to bool. - CEL expressions have access to the contents of the AdmissionRequest and Authorizer, organized into CEL variables: - - 'object' - The object from the incoming request. The value is null for DELETE requests. - 'oldObject' - The existing object. The value is null for CREATE requests. - 'request' - Attributes of the admission request(/pkg/apis/admission/types.go#AdmissionRequest). - 'authorizer' - A CEL Authorizer. May be used to perform authorization checks for the principal (user or service account) of the request. - See https://pkg.go.dev/k8s.io/apiserver/pkg/cel/library#Authz - 'authorizer.requestResource' - A CEL ResourceCheck constructed from the 'authorizer' and configured with the - request resource. - Documentation on CEL: https://kubernetes.io/docs/reference/using-api/cel/ - - Required. - type: string - name: - description: |- - Name is an identifier for this match condition, used for strategic merging of MatchConditions, - as well as providing an identifier for logging purposes. A good name should be descriptive of - the associated expression. - Name must be a qualified name consisting of alphanumeric characters, '-', '_' or '.', and - must start and end with an alphanumeric character (e.g. 'MyName', or 'my.name', or - '123-abc', regex used for validation is '([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9]') with an - optional DNS subdomain prefix and '/' (e.g. 'example.com/MyName') - - Required. - type: string - required: - - expression - - name - type: object - type: array - context: - description: Context defines variables and data sources - that can be used during rule execution. - items: - description: |- - ContextEntry adds variables and data sources to a rule Context. Either a - ConfigMap reference or a APILookup must be provided. - oneOf: - - required: - - configMap - - required: - - apiCall - - required: - - imageRegistry - - required: - - variable - - required: - - globalReference - properties: - apiCall: - description: |- - APICall is an HTTP request to the Kubernetes API server, or other JSON web service. - The data returned is stored in the context with the name for the context entry. - properties: - data: - description: |- - The data object specifies the POST data sent to the server. - Only applicable when the method field is set to POST. - items: - description: RequestData contains the HTTP POST - data - properties: - key: - description: Key is a unique identifier - for the data value - type: string - value: - description: Value is the data value - x-kubernetes-preserve-unknown-fields: true - required: - - key - - value - type: object - type: array - default: - description: |- - Default is an optional arbitrary JSON object that the context - value is set to, if the apiCall returns error. - x-kubernetes-preserve-unknown-fields: true - jmesPath: - description: |- - JMESPath is an optional JSON Match Expression that can be used to - transform the JSON response returned from the server. For example - a JMESPath of "items | length(@)" applied to the API server response - for the URLPath "/apis/apps/v1/deployments" will return the total count - of deployments across all namespaces. - type: string - method: - default: GET - description: Method is the HTTP request type (GET - or POST). Defaults to GET. - enum: - - GET - - POST - type: string - service: - description: |- - Service is an API call to a JSON web service. - This is used for non-Kubernetes API server calls. - It's mutually exclusive with the URLPath field. - properties: - caBundle: - description: |- - CABundle is a PEM encoded CA bundle which will be used to validate - the server certificate. - type: string - headers: - description: Headers is a list of optional - HTTP headers to be included in the request. - items: - properties: - key: - description: Key is the header key - type: string - value: - description: Value is the header value - type: string - required: - - key - - value - type: object - type: array - url: - description: |- - URL is the JSON web service URL. A typical form is - `https://{service}.{namespace}:{port}/{path}`. - type: string - required: - - url - type: object - urlPath: - description: |- - URLPath is the URL path to be used in the HTTP GET or POST request to the - Kubernetes API server (e.g. "/api/v1/namespaces" or "/apis/apps/v1/deployments"). - The format required is the same format used by the `kubectl get --raw` command. - See https://kyverno.io/docs/writing-policies/external-data-sources/#variables-from-kubernetes-api-server-calls - for details. - It's mutually exclusive with the Service field. - type: string - type: object - configMap: - description: ConfigMap is the ConfigMap reference. - properties: - name: - description: Name is the ConfigMap name. - type: string - namespace: - description: Namespace is the ConfigMap namespace. - type: string - required: - - name - type: object - globalReference: - description: GlobalContextEntryReference is a reference - to a cached global context entry. - properties: - jmesPath: - description: |- - JMESPath is an optional JSON Match Expression that can be used to - transform the JSON response returned from the server. For example - a JMESPath of "items | length(@)" applied to the API server response - for the URLPath "/apis/apps/v1/deployments" will return the total count - of deployments across all namespaces. - type: string - name: - description: Name of the global context entry - type: string - required: - - name - type: object - imageRegistry: - description: |- - ImageRegistry defines requests to an OCI/Docker V2 registry to fetch image - details. - properties: - imageRegistryCredentials: - description: ImageRegistryCredentials provides - credentials that will be used for authentication - with registry - properties: - allowInsecureRegistry: - description: AllowInsecureRegistry allows - insecure access to a registry. - type: boolean - providers: - description: |- - Providers specifies a list of OCI Registry names, whose authentication providers are provided. - It can be of one of these values: default,google,azure,amazon,github. - items: - description: ImageRegistryCredentialsProvidersType - provides the list of credential providers - required. - enum: - - default - - amazon - - azure - - google - - github - type: string - type: array - secrets: - description: |- - Secrets specifies a list of secrets that are provided for credentials. - Secrets must live in the Kyverno namespace. - items: - type: string - type: array - type: object - jmesPath: - description: |- - JMESPath is an optional JSON Match Expression that can be used to - transform the ImageData struct returned as a result of processing - the image reference. - type: string - reference: - description: |- - Reference is image reference to a container image in the registry. - Example: ghcr.io/kyverno/kyverno:latest - type: string - required: - - reference - type: object - name: - description: Name is the variable name. - type: string - variable: - description: Variable defines an arbitrary JMESPath - context variable that can be defined inline. - properties: - default: - description: |- - Default is an optional arbitrary JSON object that the variable may take if the JMESPath - expression evaluates to nil - x-kubernetes-preserve-unknown-fields: true - jmesPath: - description: |- - JMESPath is an optional JMESPath Expression that can be used to - transform the variable. - type: string - value: - description: Value is any arbitrary JSON object - representable in YAML or JSON form. - x-kubernetes-preserve-unknown-fields: true - type: object - required: - - name - type: object - type: array - exclude: - description: |- - ExcludeResources defines when this policy rule should not be applied. The exclude - criteria can include resource information (e.g. kind, name, namespace, labels) - and admission review request information like the name or role. - not: - required: - - any - - all - properties: - all: - description: All allows specifying resources which will - be ANDed - items: - description: ResourceFilter allow users to "AND" or - "OR" between resources - properties: - clusterRoles: - description: ClusterRoles is the list of cluster-wide - role names for the user. - items: - type: string - type: array - resources: - description: ResourceDescription contains information - about the resource being created or modified. - not: - required: - - name - - names - properties: - annotations: - additionalProperties: - type: string - description: |- - Annotations is a map of annotations (key-value pairs of type string). Annotation keys - and values support the wildcard characters "*" (matches zero or many characters) and - "?" (matches at least one character). - type: object - kinds: - description: Kinds is a list of resource kinds. - items: - type: string - type: array - name: - description: |- - Name is the name of the resource. The name supports wildcard characters - "*" (matches zero or many characters) and "?" (at least one character). - NOTE: "Name" is being deprecated in favor of "Names". - type: string - names: - description: |- - Names are the names of the resources. Each name supports wildcard characters - "*" (matches zero or many characters) and "?" (at least one character). - items: - type: string - type: array - namespaceSelector: - description: |- - NamespaceSelector is a label selector for the resource namespace. Label keys and values - in `matchLabels` support the wildcard characters `*` (matches zero or many characters) - and `?` (matches one character).Wildcards allows writing label selectors like - ["storage.k8s.io/*": "*"]. Note that using ["*" : "*"] matches any key and value but - does not match an empty label set. - properties: - matchExpressions: - description: matchExpressions is a list - of label selector requirements. The - requirements are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key - that the selector applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - namespaces: - description: |- - Namespaces is a list of namespaces names. Each name supports wildcard characters - "*" (matches zero or many characters) and "?" (at least one character). - items: - type: string - type: array - operations: - description: Operations can contain values - ["CREATE, "UPDATE", "CONNECT", "DELETE"], - which are used to match a specific action. - items: - description: AdmissionOperation can have - one of the values CREATE, UPDATE, CONNECT, - DELETE, which are used to match a specific - action. - enum: - - CREATE - - CONNECT - - UPDATE - - DELETE - type: string - type: array - selector: - description: |- - Selector is a label selector. Label keys and values in `matchLabels` support the wildcard - characters `*` (matches zero or many characters) and `?` (matches one character). - Wildcards allows writing label selectors like ["storage.k8s.io/*": "*"]. Note that - using ["*" : "*"] matches any key and value but does not match an empty label set. - properties: - matchExpressions: - description: matchExpressions is a list - of label selector requirements. The - requirements are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key - that the selector applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - type: object - roles: - description: Roles is the list of namespaced role - names for the user. - items: - type: string - type: array - subjects: - description: Subjects is the list of subject names - like users, user groups, and service accounts. - items: - description: |- - Subject contains a reference to the object or user identities a role binding applies to. This can either hold a direct API object reference, - or a value for non-objects such as user and group names. - properties: - apiGroup: - description: |- - APIGroup holds the API group of the referenced subject. - Defaults to "" for ServiceAccount subjects. - Defaults to "rbac.authorization.k8s.io" for User and Group subjects. - type: string - kind: - description: |- - Kind of object being referenced. Values defined by this API group are "User", "Group", and "ServiceAccount". - If the Authorizer does not recognized the kind value, the Authorizer should report an error. - type: string - name: - description: Name of the object being referenced. - type: string - namespace: - description: |- - Namespace of the referenced object. If the object kind is non-namespace, such as "User" or "Group", and this value is not empty - the Authorizer should report an error. - type: string - required: - - kind - - name - type: object - x-kubernetes-map-type: atomic - type: array - type: object - type: array - any: - description: Any allows specifying resources which will - be ORed - items: - description: ResourceFilter allow users to "AND" or - "OR" between resources - properties: - clusterRoles: - description: ClusterRoles is the list of cluster-wide - role names for the user. - items: - type: string - type: array - resources: - description: ResourceDescription contains information - about the resource being created or modified. - not: - required: - - name - - names - properties: - annotations: - additionalProperties: - type: string - description: |- - Annotations is a map of annotations (key-value pairs of type string). Annotation keys - and values support the wildcard characters "*" (matches zero or many characters) and - "?" (matches at least one character). - type: object - kinds: - description: Kinds is a list of resource kinds. - items: - type: string - type: array - name: - description: |- - Name is the name of the resource. The name supports wildcard characters - "*" (matches zero or many characters) and "?" (at least one character). - NOTE: "Name" is being deprecated in favor of "Names". - type: string - names: - description: |- - Names are the names of the resources. Each name supports wildcard characters - "*" (matches zero or many characters) and "?" (at least one character). - items: - type: string - type: array - namespaceSelector: - description: |- - NamespaceSelector is a label selector for the resource namespace. Label keys and values - in `matchLabels` support the wildcard characters `*` (matches zero or many characters) - and `?` (matches one character).Wildcards allows writing label selectors like - ["storage.k8s.io/*": "*"]. Note that using ["*" : "*"] matches any key and value but - does not match an empty label set. - properties: - matchExpressions: - description: matchExpressions is a list - of label selector requirements. The - requirements are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key - that the selector applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - namespaces: - description: |- - Namespaces is a list of namespaces names. Each name supports wildcard characters - "*" (matches zero or many characters) and "?" (at least one character). - items: - type: string - type: array - operations: - description: Operations can contain values - ["CREATE, "UPDATE", "CONNECT", "DELETE"], - which are used to match a specific action. - items: - description: AdmissionOperation can have - one of the values CREATE, UPDATE, CONNECT, - DELETE, which are used to match a specific - action. - enum: - - CREATE - - CONNECT - - UPDATE - - DELETE - type: string - type: array - selector: - description: |- - Selector is a label selector. Label keys and values in `matchLabels` support the wildcard - characters `*` (matches zero or many characters) and `?` (matches one character). - Wildcards allows writing label selectors like ["storage.k8s.io/*": "*"]. Note that - using ["*" : "*"] matches any key and value but does not match an empty label set. - properties: - matchExpressions: - description: matchExpressions is a list - of label selector requirements. The - requirements are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key - that the selector applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - type: object - roles: - description: Roles is the list of namespaced role - names for the user. - items: - type: string - type: array - subjects: - description: Subjects is the list of subject names - like users, user groups, and service accounts. - items: - description: |- - Subject contains a reference to the object or user identities a role binding applies to. This can either hold a direct API object reference, - or a value for non-objects such as user and group names. - properties: - apiGroup: - description: |- - APIGroup holds the API group of the referenced subject. - Defaults to "" for ServiceAccount subjects. - Defaults to "rbac.authorization.k8s.io" for User and Group subjects. - type: string - kind: - description: |- - Kind of object being referenced. Values defined by this API group are "User", "Group", and "ServiceAccount". - If the Authorizer does not recognized the kind value, the Authorizer should report an error. - type: string - name: - description: Name of the object being referenced. - type: string - namespace: - description: |- - Namespace of the referenced object. If the object kind is non-namespace, such as "User" or "Group", and this value is not empty - the Authorizer should report an error. - type: string - required: - - kind - - name - type: object - x-kubernetes-map-type: atomic - type: array - type: object - type: array - clusterRoles: - description: ClusterRoles is the list of cluster-wide - role names for the user. - items: - type: string - type: array - resources: - description: |- - ResourceDescription contains information about the resource being created or modified. - Requires at least one tag to be specified when under MatchResources. - Specifying ResourceDescription directly under match is being deprecated. - Please specify under "any" or "all" instead. - not: - required: - - name - - names - properties: - annotations: - additionalProperties: - type: string - description: |- - Annotations is a map of annotations (key-value pairs of type string). Annotation keys - and values support the wildcard characters "*" (matches zero or many characters) and - "?" (matches at least one character). - type: object - kinds: - description: Kinds is a list of resource kinds. - items: - type: string - type: array - name: - description: |- - Name is the name of the resource. The name supports wildcard characters - "*" (matches zero or many characters) and "?" (at least one character). - NOTE: "Name" is being deprecated in favor of "Names". - type: string - names: - description: |- - Names are the names of the resources. Each name supports wildcard characters - "*" (matches zero or many characters) and "?" (at least one character). - items: - type: string - type: array - namespaceSelector: - description: |- - NamespaceSelector is a label selector for the resource namespace. Label keys and values - in `matchLabels` support the wildcard characters `*` (matches zero or many characters) - and `?` (matches one character).Wildcards allows writing label selectors like - ["storage.k8s.io/*": "*"]. Note that using ["*" : "*"] matches any key and value but - does not match an empty label set. - properties: - matchExpressions: - description: matchExpressions is a list of label - selector requirements. The requirements are - ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key that - the selector applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - namespaces: - description: |- - Namespaces is a list of namespaces names. Each name supports wildcard characters - "*" (matches zero or many characters) and "?" (at least one character). - items: - type: string - type: array - operations: - description: Operations can contain values ["CREATE, - "UPDATE", "CONNECT", "DELETE"], which are used - to match a specific action. - items: - description: AdmissionOperation can have one of - the values CREATE, UPDATE, CONNECT, DELETE, - which are used to match a specific action. - enum: - - CREATE - - CONNECT - - UPDATE - - DELETE - type: string - type: array - selector: - description: |- - Selector is a label selector. Label keys and values in `matchLabels` support the wildcard - characters `*` (matches zero or many characters) and `?` (matches one character). - Wildcards allows writing label selectors like ["storage.k8s.io/*": "*"]. Note that - using ["*" : "*"] matches any key and value but does not match an empty label set. - properties: - matchExpressions: - description: matchExpressions is a list of label - selector requirements. The requirements are - ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key that - the selector applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - type: object - roles: - description: Roles is the list of namespaced role names - for the user. - items: - type: string - type: array - subjects: - description: Subjects is the list of subject names like - users, user groups, and service accounts. - items: - description: |- - Subject contains a reference to the object or user identities a role binding applies to. This can either hold a direct API object reference, - or a value for non-objects such as user and group names. - properties: - apiGroup: - description: |- - APIGroup holds the API group of the referenced subject. - Defaults to "" for ServiceAccount subjects. - Defaults to "rbac.authorization.k8s.io" for User and Group subjects. - type: string - kind: - description: |- - Kind of object being referenced. Values defined by this API group are "User", "Group", and "ServiceAccount". - If the Authorizer does not recognized the kind value, the Authorizer should report an error. - type: string - name: - description: Name of the object being referenced. - type: string - namespace: - description: |- - Namespace of the referenced object. If the object kind is non-namespace, such as "User" or "Group", and this value is not empty - the Authorizer should report an error. - type: string - required: - - kind - - name - type: object - x-kubernetes-map-type: atomic - type: array - type: object - generate: - description: Generation is used to create new resources. - properties: - apiVersion: - description: APIVersion specifies resource apiVersion. - type: string - clone: - description: |- - Clone specifies the source resource used to populate each generated resource. - At most one of Data or Clone can be specified. If neither are provided, the generated - resource will be created with default data only. - properties: - name: - description: Name specifies name of the resource. - type: string - namespace: - description: Namespace specifies source resource - namespace. - type: string - type: object - cloneList: - description: CloneList specifies the list of source - resource used to populate each generated resource. - properties: - kinds: - description: Kinds is a list of resource kinds. - items: - type: string - type: array - namespace: - description: Namespace specifies source resource - namespace. - type: string - selector: - description: |- - Selector is a label selector. Label keys and values in `matchLabels`. - wildcard characters are not supported. - properties: - matchExpressions: - description: matchExpressions is a list of label - selector requirements. The requirements are - ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key that - the selector applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - type: object - data: - description: |- - Data provides the resource declaration used to populate each generated resource. - At most one of Data or Clone must be specified. If neither are provided, the generated - resource will be created with default data only. - x-kubernetes-preserve-unknown-fields: true - foreach: - description: ForEach applies generate rules to a list - of sub-elements by creating a context for each entry - in the list and looping over it to apply the specified - logic. - items: - properties: - apiVersion: - description: APIVersion specifies resource apiVersion. - type: string - clone: - description: |- - Clone specifies the source resource used to populate each generated resource. - At most one of Data or Clone can be specified. If neither are provided, the generated - resource will be created with default data only. - properties: - name: - description: Name specifies name of the resource. - type: string - namespace: - description: Namespace specifies source resource - namespace. - type: string - type: object - cloneList: - description: CloneList specifies the list of source - resource used to populate each generated resource. - properties: - kinds: - description: Kinds is a list of resource kinds. - items: - type: string - type: array - namespace: - description: Namespace specifies source resource - namespace. - type: string - selector: - description: |- - Selector is a label selector. Label keys and values in `matchLabels`. - wildcard characters are not supported. - properties: - matchExpressions: - description: matchExpressions is a list - of label selector requirements. The - requirements are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key - that the selector applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - type: object - context: - description: Context defines variables and data - sources that can be used during rule execution. - items: - description: |- - ContextEntry adds variables and data sources to a rule Context. Either a - ConfigMap reference or a APILookup must be provided. - oneOf: - - required: - - configMap - - required: - - apiCall - - required: - - imageRegistry - - required: - - variable - - required: - - globalReference - properties: - apiCall: - description: |- - APICall is an HTTP request to the Kubernetes API server, or other JSON web service. - The data returned is stored in the context with the name for the context entry. - properties: - data: - description: |- - The data object specifies the POST data sent to the server. - Only applicable when the method field is set to POST. - items: - description: RequestData contains - the HTTP POST data - properties: - key: - description: Key is a unique identifier - for the data value - type: string - value: - description: Value is the data - value - x-kubernetes-preserve-unknown-fields: true - required: - - key - - value - type: object - type: array - default: - description: |- - Default is an optional arbitrary JSON object that the context - value is set to, if the apiCall returns error. - x-kubernetes-preserve-unknown-fields: true - jmesPath: - description: |- - JMESPath is an optional JSON Match Expression that can be used to - transform the JSON response returned from the server. For example - a JMESPath of "items | length(@)" applied to the API server response - for the URLPath "/apis/apps/v1/deployments" will return the total count - of deployments across all namespaces. - type: string - method: - default: GET - description: Method is the HTTP request - type (GET or POST). Defaults to GET. - enum: - - GET - - POST - type: string - service: - description: |- - Service is an API call to a JSON web service. - This is used for non-Kubernetes API server calls. - It's mutually exclusive with the URLPath field. - properties: - caBundle: - description: |- - CABundle is a PEM encoded CA bundle which will be used to validate - the server certificate. - type: string - headers: - description: Headers is a list of - optional HTTP headers to be included - in the request. - items: - properties: - key: - description: Key is the header - key - type: string - value: - description: Value is the - header value - type: string - required: - - key - - value - type: object - type: array - url: - description: |- - URL is the JSON web service URL. A typical form is - `https://{service}.{namespace}:{port}/{path}`. - type: string - required: - - url - type: object - urlPath: - description: |- - URLPath is the URL path to be used in the HTTP GET or POST request to the - Kubernetes API server (e.g. "/api/v1/namespaces" or "/apis/apps/v1/deployments"). - The format required is the same format used by the `kubectl get --raw` command. - See https://kyverno.io/docs/writing-policies/external-data-sources/#variables-from-kubernetes-api-server-calls - for details. - It's mutually exclusive with the Service field. - type: string - type: object - configMap: - description: ConfigMap is the ConfigMap - reference. - properties: - name: - description: Name is the ConfigMap name. - type: string - namespace: - description: Namespace is the ConfigMap - namespace. - type: string - required: - - name - type: object - globalReference: - description: GlobalContextEntryReference - is a reference to a cached global context - entry. - properties: - jmesPath: - description: |- - JMESPath is an optional JSON Match Expression that can be used to - transform the JSON response returned from the server. For example - a JMESPath of "items | length(@)" applied to the API server response - for the URLPath "/apis/apps/v1/deployments" will return the total count - of deployments across all namespaces. - type: string - name: - description: Name of the global context - entry - type: string - required: - - name - type: object - imageRegistry: - description: |- - ImageRegistry defines requests to an OCI/Docker V2 registry to fetch image - details. - properties: - imageRegistryCredentials: - description: ImageRegistryCredentials - provides credentials that will be - used for authentication with registry - properties: - allowInsecureRegistry: - description: AllowInsecureRegistry - allows insecure access to a registry. - type: boolean - providers: - description: |- - Providers specifies a list of OCI Registry names, whose authentication providers are provided. - It can be of one of these values: default,google,azure,amazon,github. - items: - description: ImageRegistryCredentialsProvidersType - provides the list of credential - providers required. - enum: - - default - - amazon - - azure - - google - - github - type: string - type: array - secrets: - description: |- - Secrets specifies a list of secrets that are provided for credentials. - Secrets must live in the Kyverno namespace. - items: - type: string - type: array - type: object - jmesPath: - description: |- - JMESPath is an optional JSON Match Expression that can be used to - transform the ImageData struct returned as a result of processing - the image reference. - type: string - reference: - description: |- - Reference is image reference to a container image in the registry. - Example: ghcr.io/kyverno/kyverno:latest - type: string - required: - - reference - type: object - name: - description: Name is the variable name. - type: string - variable: - description: Variable defines an arbitrary - JMESPath context variable that can be - defined inline. - properties: - default: - description: |- - Default is an optional arbitrary JSON object that the variable may take if the JMESPath - expression evaluates to nil - x-kubernetes-preserve-unknown-fields: true - jmesPath: - description: |- - JMESPath is an optional JMESPath Expression that can be used to - transform the variable. - type: string - value: - description: Value is any arbitrary - JSON object representable in YAML - or JSON form. - x-kubernetes-preserve-unknown-fields: true - type: object - required: - - name - type: object - type: array - data: - description: |- - Data provides the resource declaration used to populate each generated resource. - At most one of Data or Clone must be specified. If neither are provided, the generated - resource will be created with default data only. - x-kubernetes-preserve-unknown-fields: true - kind: - description: Kind specifies resource kind. - type: string - list: - description: |- - List specifies a JMESPath expression that results in one or more elements - to which the validation logic is applied. - type: string - name: - description: Name specifies the resource name. - type: string - namespace: - description: Namespace specifies resource namespace. - type: string - preconditions: - description: |- - AnyAllConditions are used to determine if a policy rule should be applied by evaluating a - set of conditions. The declaration can contain nested `any` or `all` statements. - See: https://kyverno.io/docs/writing-policies/preconditions/ - properties: - all: - description: |- - AllConditions enable variable-based conditional rule execution. This is useful for - finer control of when an rule is applied. A condition can reference object data - using JMESPath notation. - Here, all of the conditions need to pass - items: - description: Condition defines variable-based - conditional criteria for rule execution. - properties: - key: - description: Key is the context entry - (using JMESPath) for conditional rule - evaluation. - x-kubernetes-preserve-unknown-fields: true - message: - description: Message is an optional - display message - type: string - operator: - description: |- - Operator is the conditional operation to perform. Valid operators are: - Equals, NotEquals, In, AnyIn, AllIn, NotIn, AnyNotIn, AllNotIn, GreaterThanOrEquals, - GreaterThan, LessThanOrEquals, LessThan, DurationGreaterThanOrEquals, DurationGreaterThan, - DurationLessThanOrEquals, DurationLessThan - enum: - - Equals - - NotEquals - - In - - AnyIn - - AllIn - - NotIn - - AnyNotIn - - AllNotIn - - GreaterThanOrEquals - - GreaterThan - - LessThanOrEquals - - LessThan - - DurationGreaterThanOrEquals - - DurationGreaterThan - - DurationLessThanOrEquals - - DurationLessThan - type: string - value: - description: |- - Value is the conditional value, or set of values. The values can be fixed set - or can be variables declared using JMESPath. - x-kubernetes-preserve-unknown-fields: true - type: object - type: array - any: - description: |- - AnyConditions enable variable-based conditional rule execution. This is useful for - finer control of when an rule is applied. A condition can reference object data - using JMESPath notation. - Here, at least one of the conditions need to pass - items: - description: Condition defines variable-based - conditional criteria for rule execution. - properties: - key: - description: Key is the context entry - (using JMESPath) for conditional rule - evaluation. - x-kubernetes-preserve-unknown-fields: true - message: - description: Message is an optional - display message - type: string - operator: - description: |- - Operator is the conditional operation to perform. Valid operators are: - Equals, NotEquals, In, AnyIn, AllIn, NotIn, AnyNotIn, AllNotIn, GreaterThanOrEquals, - GreaterThan, LessThanOrEquals, LessThan, DurationGreaterThanOrEquals, DurationGreaterThan, - DurationLessThanOrEquals, DurationLessThan - enum: - - Equals - - NotEquals - - In - - AnyIn - - AllIn - - NotIn - - AnyNotIn - - AllNotIn - - GreaterThanOrEquals - - GreaterThan - - LessThanOrEquals - - LessThan - - DurationGreaterThanOrEquals - - DurationGreaterThan - - DurationLessThanOrEquals - - DurationLessThan - type: string - value: - description: |- - Value is the conditional value, or set of values. The values can be fixed set - or can be variables declared using JMESPath. - x-kubernetes-preserve-unknown-fields: true - type: object - type: array - type: object - x-kubernetes-preserve-unknown-fields: true - uid: - description: UID specifies the resource uid. - type: string - type: object - type: array - generateExisting: - description: |- - GenerateExisting controls whether to trigger the rule in existing resources - If is set to "true" the rule will be triggered and applied to existing matched resources. - type: boolean - kind: - description: Kind specifies resource kind. - type: string - name: - description: Name specifies the resource name. - type: string - namespace: - description: Namespace specifies resource namespace. - type: string - orphanDownstreamOnPolicyDelete: - description: |- - OrphanDownstreamOnPolicyDelete controls whether generated resources should be deleted when the rule that generated - them is deleted with synchronization enabled. This option is only applicable to generate rules of the data type. - See https://kyverno.io/docs/writing-policies/generate/#data-examples. - Defaults to "false" if not specified. - type: boolean - synchronize: - description: |- - Synchronize controls if generated resources should be kept in-sync with their source resource. - If Synchronize is set to "true" changes to generated resources will be overwritten with resource - data from Data or the resource specified in the Clone declaration. - Optional. Defaults to "false" if not specified. - type: boolean - uid: - description: UID specifies the resource uid. - type: string - type: object - imageExtractors: - additionalProperties: - items: - properties: - jmesPath: - description: |- - JMESPath is an optional JMESPath expression to apply to the image value. - This is useful when the extracted image begins with a prefix like 'docker://'. - The 'trim_prefix' function may be used to trim the prefix: trim_prefix(@, 'docker://'). - Note - Image digest mutation may not be used when applying a JMESPAth to an image. - type: string - key: - description: |- - Key is an optional name of the field within 'path' that will be used to uniquely identify an image. - Note - this field MUST be unique. - type: string - name: - description: |- - Name is the entry the image will be available under 'images.' in the context. - If this field is not defined, image entries will appear under 'images.custom'. - type: string - path: - description: |- - Path is the path to the object containing the image field in a custom resource. - It should be slash-separated. Each slash-separated key must be a valid YAML key or a wildcard '*'. - Wildcard keys are expanded in case of arrays or objects. - type: string - value: - description: |- - Value is an optional name of the field within 'path' that points to the image URI. - This is useful when a custom 'key' is also defined. - type: string - required: - - path - type: object - type: array - description: |- - ImageExtractors defines a mapping from kinds to ImageExtractorConfigs. - This config is only valid for verifyImages rules. - type: object - match: - description: |- - MatchResources defines when this policy rule should be applied. The match - criteria can include resource information (e.g. kind, name, namespace, labels) - and admission review request information like the user name or role. - At least one kind is required. - not: - required: - - any - - all - properties: - all: - description: All allows specifying resources which will - be ANDed - items: - description: ResourceFilter allow users to "AND" or - "OR" between resources - properties: - clusterRoles: - description: ClusterRoles is the list of cluster-wide - role names for the user. - items: - type: string - type: array - resources: - description: ResourceDescription contains information - about the resource being created or modified. - not: - required: - - name - - names - properties: - annotations: - additionalProperties: - type: string - description: |- - Annotations is a map of annotations (key-value pairs of type string). Annotation keys - and values support the wildcard characters "*" (matches zero or many characters) and - "?" (matches at least one character). - type: object - kinds: - description: Kinds is a list of resource kinds. - items: - type: string - type: array - name: - description: |- - Name is the name of the resource. The name supports wildcard characters - "*" (matches zero or many characters) and "?" (at least one character). - NOTE: "Name" is being deprecated in favor of "Names". - type: string - names: - description: |- - Names are the names of the resources. Each name supports wildcard characters - "*" (matches zero or many characters) and "?" (at least one character). - items: - type: string - type: array - namespaceSelector: - description: |- - NamespaceSelector is a label selector for the resource namespace. Label keys and values - in `matchLabels` support the wildcard characters `*` (matches zero or many characters) - and `?` (matches one character).Wildcards allows writing label selectors like - ["storage.k8s.io/*": "*"]. Note that using ["*" : "*"] matches any key and value but - does not match an empty label set. - properties: - matchExpressions: - description: matchExpressions is a list - of label selector requirements. The - requirements are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key - that the selector applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - namespaces: - description: |- - Namespaces is a list of namespaces names. Each name supports wildcard characters - "*" (matches zero or many characters) and "?" (at least one character). - items: - type: string - type: array - operations: - description: Operations can contain values - ["CREATE, "UPDATE", "CONNECT", "DELETE"], - which are used to match a specific action. - items: - description: AdmissionOperation can have - one of the values CREATE, UPDATE, CONNECT, - DELETE, which are used to match a specific - action. - enum: - - CREATE - - CONNECT - - UPDATE - - DELETE - type: string - type: array - selector: - description: |- - Selector is a label selector. Label keys and values in `matchLabels` support the wildcard - characters `*` (matches zero or many characters) and `?` (matches one character). - Wildcards allows writing label selectors like ["storage.k8s.io/*": "*"]. Note that - using ["*" : "*"] matches any key and value but does not match an empty label set. - properties: - matchExpressions: - description: matchExpressions is a list - of label selector requirements. The - requirements are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key - that the selector applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - type: object - roles: - description: Roles is the list of namespaced role - names for the user. - items: - type: string - type: array - subjects: - description: Subjects is the list of subject names - like users, user groups, and service accounts. - items: - description: |- - Subject contains a reference to the object or user identities a role binding applies to. This can either hold a direct API object reference, - or a value for non-objects such as user and group names. - properties: - apiGroup: - description: |- - APIGroup holds the API group of the referenced subject. - Defaults to "" for ServiceAccount subjects. - Defaults to "rbac.authorization.k8s.io" for User and Group subjects. - type: string - kind: - description: |- - Kind of object being referenced. Values defined by this API group are "User", "Group", and "ServiceAccount". - If the Authorizer does not recognized the kind value, the Authorizer should report an error. - type: string - name: - description: Name of the object being referenced. - type: string - namespace: - description: |- - Namespace of the referenced object. If the object kind is non-namespace, such as "User" or "Group", and this value is not empty - the Authorizer should report an error. - type: string - required: - - kind - - name - type: object - x-kubernetes-map-type: atomic - type: array - type: object - type: array - any: - description: Any allows specifying resources which will - be ORed - items: - description: ResourceFilter allow users to "AND" or - "OR" between resources - properties: - clusterRoles: - description: ClusterRoles is the list of cluster-wide - role names for the user. - items: - type: string - type: array - resources: - description: ResourceDescription contains information - about the resource being created or modified. - not: - required: - - name - - names - properties: - annotations: - additionalProperties: - type: string - description: |- - Annotations is a map of annotations (key-value pairs of type string). Annotation keys - and values support the wildcard characters "*" (matches zero or many characters) and - "?" (matches at least one character). - type: object - kinds: - description: Kinds is a list of resource kinds. - items: - type: string - type: array - name: - description: |- - Name is the name of the resource. The name supports wildcard characters - "*" (matches zero or many characters) and "?" (at least one character). - NOTE: "Name" is being deprecated in favor of "Names". - type: string - names: - description: |- - Names are the names of the resources. Each name supports wildcard characters - "*" (matches zero or many characters) and "?" (at least one character). - items: - type: string - type: array - namespaceSelector: - description: |- - NamespaceSelector is a label selector for the resource namespace. Label keys and values - in `matchLabels` support the wildcard characters `*` (matches zero or many characters) - and `?` (matches one character).Wildcards allows writing label selectors like - ["storage.k8s.io/*": "*"]. Note that using ["*" : "*"] matches any key and value but - does not match an empty label set. - properties: - matchExpressions: - description: matchExpressions is a list - of label selector requirements. The - requirements are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key - that the selector applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - namespaces: - description: |- - Namespaces is a list of namespaces names. Each name supports wildcard characters - "*" (matches zero or many characters) and "?" (at least one character). - items: - type: string - type: array - operations: - description: Operations can contain values - ["CREATE, "UPDATE", "CONNECT", "DELETE"], - which are used to match a specific action. - items: - description: AdmissionOperation can have - one of the values CREATE, UPDATE, CONNECT, - DELETE, which are used to match a specific - action. - enum: - - CREATE - - CONNECT - - UPDATE - - DELETE - type: string - type: array - selector: - description: |- - Selector is a label selector. Label keys and values in `matchLabels` support the wildcard - characters `*` (matches zero or many characters) and `?` (matches one character). - Wildcards allows writing label selectors like ["storage.k8s.io/*": "*"]. Note that - using ["*" : "*"] matches any key and value but does not match an empty label set. - properties: - matchExpressions: - description: matchExpressions is a list - of label selector requirements. The - requirements are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key - that the selector applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - type: object - roles: - description: Roles is the list of namespaced role - names for the user. - items: - type: string - type: array - subjects: - description: Subjects is the list of subject names - like users, user groups, and service accounts. - items: - description: |- - Subject contains a reference to the object or user identities a role binding applies to. This can either hold a direct API object reference, - or a value for non-objects such as user and group names. - properties: - apiGroup: - description: |- - APIGroup holds the API group of the referenced subject. - Defaults to "" for ServiceAccount subjects. - Defaults to "rbac.authorization.k8s.io" for User and Group subjects. - type: string - kind: - description: |- - Kind of object being referenced. Values defined by this API group are "User", "Group", and "ServiceAccount". - If the Authorizer does not recognized the kind value, the Authorizer should report an error. - type: string - name: - description: Name of the object being referenced. - type: string - namespace: - description: |- - Namespace of the referenced object. If the object kind is non-namespace, such as "User" or "Group", and this value is not empty - the Authorizer should report an error. - type: string - required: - - kind - - name - type: object - x-kubernetes-map-type: atomic - type: array - type: object - type: array - clusterRoles: - description: ClusterRoles is the list of cluster-wide - role names for the user. - items: - type: string - type: array - resources: - description: |- - ResourceDescription contains information about the resource being created or modified. - Requires at least one tag to be specified when under MatchResources. - Specifying ResourceDescription directly under match is being deprecated. - Please specify under "any" or "all" instead. - not: - required: - - name - - names - properties: - annotations: - additionalProperties: - type: string - description: |- - Annotations is a map of annotations (key-value pairs of type string). Annotation keys - and values support the wildcard characters "*" (matches zero or many characters) and - "?" (matches at least one character). - type: object - kinds: - description: Kinds is a list of resource kinds. - items: - type: string - type: array - name: - description: |- - Name is the name of the resource. The name supports wildcard characters - "*" (matches zero or many characters) and "?" (at least one character). - NOTE: "Name" is being deprecated in favor of "Names". - type: string - names: - description: |- - Names are the names of the resources. Each name supports wildcard characters - "*" (matches zero or many characters) and "?" (at least one character). - items: - type: string - type: array - namespaceSelector: - description: |- - NamespaceSelector is a label selector for the resource namespace. Label keys and values - in `matchLabels` support the wildcard characters `*` (matches zero or many characters) - and `?` (matches one character).Wildcards allows writing label selectors like - ["storage.k8s.io/*": "*"]. Note that using ["*" : "*"] matches any key and value but - does not match an empty label set. - properties: - matchExpressions: - description: matchExpressions is a list of label - selector requirements. The requirements are - ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key that - the selector applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - namespaces: - description: |- - Namespaces is a list of namespaces names. Each name supports wildcard characters - "*" (matches zero or many characters) and "?" (at least one character). - items: - type: string - type: array - operations: - description: Operations can contain values ["CREATE, - "UPDATE", "CONNECT", "DELETE"], which are used - to match a specific action. - items: - description: AdmissionOperation can have one of - the values CREATE, UPDATE, CONNECT, DELETE, - which are used to match a specific action. - enum: - - CREATE - - CONNECT - - UPDATE - - DELETE - type: string - type: array - selector: - description: |- - Selector is a label selector. Label keys and values in `matchLabels` support the wildcard - characters `*` (matches zero or many characters) and `?` (matches one character). - Wildcards allows writing label selectors like ["storage.k8s.io/*": "*"]. Note that - using ["*" : "*"] matches any key and value but does not match an empty label set. - properties: - matchExpressions: - description: matchExpressions is a list of label - selector requirements. The requirements are - ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key that - the selector applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - type: object - roles: - description: Roles is the list of namespaced role names - for the user. - items: - type: string - type: array - subjects: - description: Subjects is the list of subject names like - users, user groups, and service accounts. - items: - description: |- - Subject contains a reference to the object or user identities a role binding applies to. This can either hold a direct API object reference, - or a value for non-objects such as user and group names. - properties: - apiGroup: - description: |- - APIGroup holds the API group of the referenced subject. - Defaults to "" for ServiceAccount subjects. - Defaults to "rbac.authorization.k8s.io" for User and Group subjects. - type: string - kind: - description: |- - Kind of object being referenced. Values defined by this API group are "User", "Group", and "ServiceAccount". - If the Authorizer does not recognized the kind value, the Authorizer should report an error. - type: string - name: - description: Name of the object being referenced. - type: string - namespace: - description: |- - Namespace of the referenced object. If the object kind is non-namespace, such as "User" or "Group", and this value is not empty - the Authorizer should report an error. - type: string - required: - - kind - - name - type: object - x-kubernetes-map-type: atomic - type: array - type: object - mutate: - description: Mutation is used to modify matching resources. - properties: - foreach: - description: ForEach applies mutation rules to a list - of sub-elements by creating a context for each entry - in the list and looping over it to apply the specified - logic. - items: - description: ForEachMutation applies mutation rules - to a list of sub-elements by creating a context - for each entry in the list and looping over it to - apply the specified logic. - properties: - context: - description: Context defines variables and data - sources that can be used during rule execution. - items: - description: |- - ContextEntry adds variables and data sources to a rule Context. Either a - ConfigMap reference or a APILookup must be provided. - oneOf: - - required: - - configMap - - required: - - apiCall - - required: - - imageRegistry - - required: - - variable - - required: - - globalReference - properties: - apiCall: - description: |- - APICall is an HTTP request to the Kubernetes API server, or other JSON web service. - The data returned is stored in the context with the name for the context entry. - properties: - data: - description: |- - The data object specifies the POST data sent to the server. - Only applicable when the method field is set to POST. - items: - description: RequestData contains - the HTTP POST data - properties: - key: - description: Key is a unique identifier - for the data value - type: string - value: - description: Value is the data - value - x-kubernetes-preserve-unknown-fields: true - required: - - key - - value - type: object - type: array - default: - description: |- - Default is an optional arbitrary JSON object that the context - value is set to, if the apiCall returns error. - x-kubernetes-preserve-unknown-fields: true - jmesPath: - description: |- - JMESPath is an optional JSON Match Expression that can be used to - transform the JSON response returned from the server. For example - a JMESPath of "items | length(@)" applied to the API server response - for the URLPath "/apis/apps/v1/deployments" will return the total count - of deployments across all namespaces. - type: string - method: - default: GET - description: Method is the HTTP request - type (GET or POST). Defaults to GET. - enum: - - GET - - POST - type: string - service: - description: |- - Service is an API call to a JSON web service. - This is used for non-Kubernetes API server calls. - It's mutually exclusive with the URLPath field. - properties: - caBundle: - description: |- - CABundle is a PEM encoded CA bundle which will be used to validate - the server certificate. - type: string - headers: - description: Headers is a list of - optional HTTP headers to be included - in the request. - items: - properties: - key: - description: Key is the header - key - type: string - value: - description: Value is the - header value - type: string - required: - - key - - value - type: object - type: array - url: - description: |- - URL is the JSON web service URL. A typical form is - `https://{service}.{namespace}:{port}/{path}`. - type: string - required: - - url - type: object - urlPath: - description: |- - URLPath is the URL path to be used in the HTTP GET or POST request to the - Kubernetes API server (e.g. "/api/v1/namespaces" or "/apis/apps/v1/deployments"). - The format required is the same format used by the `kubectl get --raw` command. - See https://kyverno.io/docs/writing-policies/external-data-sources/#variables-from-kubernetes-api-server-calls - for details. - It's mutually exclusive with the Service field. - type: string - type: object - configMap: - description: ConfigMap is the ConfigMap - reference. - properties: - name: - description: Name is the ConfigMap name. - type: string - namespace: - description: Namespace is the ConfigMap - namespace. - type: string - required: - - name - type: object - globalReference: - description: GlobalContextEntryReference - is a reference to a cached global context - entry. - properties: - jmesPath: - description: |- - JMESPath is an optional JSON Match Expression that can be used to - transform the JSON response returned from the server. For example - a JMESPath of "items | length(@)" applied to the API server response - for the URLPath "/apis/apps/v1/deployments" will return the total count - of deployments across all namespaces. - type: string - name: - description: Name of the global context - entry - type: string - required: - - name - type: object - imageRegistry: - description: |- - ImageRegistry defines requests to an OCI/Docker V2 registry to fetch image - details. - properties: - imageRegistryCredentials: - description: ImageRegistryCredentials - provides credentials that will be - used for authentication with registry - properties: - allowInsecureRegistry: - description: AllowInsecureRegistry - allows insecure access to a registry. - type: boolean - providers: - description: |- - Providers specifies a list of OCI Registry names, whose authentication providers are provided. - It can be of one of these values: default,google,azure,amazon,github. - items: - description: ImageRegistryCredentialsProvidersType - provides the list of credential - providers required. - enum: - - default - - amazon - - azure - - google - - github - type: string - type: array - secrets: - description: |- - Secrets specifies a list of secrets that are provided for credentials. - Secrets must live in the Kyverno namespace. - items: - type: string - type: array - type: object - jmesPath: - description: |- - JMESPath is an optional JSON Match Expression that can be used to - transform the ImageData struct returned as a result of processing - the image reference. - type: string - reference: - description: |- - Reference is image reference to a container image in the registry. - Example: ghcr.io/kyverno/kyverno:latest - type: string - required: - - reference - type: object - name: - description: Name is the variable name. - type: string - variable: - description: Variable defines an arbitrary - JMESPath context variable that can be - defined inline. - properties: - default: - description: |- - Default is an optional arbitrary JSON object that the variable may take if the JMESPath - expression evaluates to nil - x-kubernetes-preserve-unknown-fields: true - jmesPath: - description: |- - JMESPath is an optional JMESPath Expression that can be used to - transform the variable. - type: string - value: - description: Value is any arbitrary - JSON object representable in YAML - or JSON form. - x-kubernetes-preserve-unknown-fields: true - type: object - required: - - name - type: object - type: array - foreach: - description: Foreach declares a nested foreach - iterator - x-kubernetes-preserve-unknown-fields: true - list: - description: |- - List specifies a JMESPath expression that results in one or more elements - to which the validation logic is applied. - type: string - order: - description: |- - Order defines the iteration order on the list. - Can be Ascending to iterate from first to last element or Descending to iterate in from last to first element. - enum: - - Ascending - - Descending - type: string - patchStrategicMerge: - description: |- - PatchStrategicMerge is a strategic merge patch used to modify resources. - See https://kubernetes.io/docs/tasks/manage-kubernetes-objects/update-api-object-kubectl-patch/ - and https://kubectl.docs.kubernetes.io/references/kustomize/kustomization/patchesstrategicmerge/. - x-kubernetes-preserve-unknown-fields: true - patchesJson6902: - description: |- - PatchesJSON6902 is a list of RFC 6902 JSON Patch declarations used to modify resources. - See https://tools.ietf.org/html/rfc6902 and https://kubectl.docs.kubernetes.io/references/kustomize/kustomization/patchesjson6902/. - type: string - preconditions: - description: |- - AnyAllConditions are used to determine if a policy rule should be applied by evaluating a - set of conditions. The declaration can contain nested `any` or `all` statements. - See: https://kyverno.io/docs/writing-policies/preconditions/ - properties: - all: - description: |- - AllConditions enable variable-based conditional rule execution. This is useful for - finer control of when an rule is applied. A condition can reference object data - using JMESPath notation. - Here, all of the conditions need to pass - items: - description: Condition defines variable-based - conditional criteria for rule execution. - properties: - key: - description: Key is the context entry - (using JMESPath) for conditional rule - evaluation. - x-kubernetes-preserve-unknown-fields: true - message: - description: Message is an optional - display message - type: string - operator: - description: |- - Operator is the conditional operation to perform. Valid operators are: - Equals, NotEquals, In, AnyIn, AllIn, NotIn, AnyNotIn, AllNotIn, GreaterThanOrEquals, - GreaterThan, LessThanOrEquals, LessThan, DurationGreaterThanOrEquals, DurationGreaterThan, - DurationLessThanOrEquals, DurationLessThan - enum: - - Equals - - NotEquals - - In - - AnyIn - - AllIn - - NotIn - - AnyNotIn - - AllNotIn - - GreaterThanOrEquals - - GreaterThan - - LessThanOrEquals - - LessThan - - DurationGreaterThanOrEquals - - DurationGreaterThan - - DurationLessThanOrEquals - - DurationLessThan - type: string - value: - description: |- - Value is the conditional value, or set of values. The values can be fixed set - or can be variables declared using JMESPath. - x-kubernetes-preserve-unknown-fields: true - type: object - type: array - any: - description: |- - AnyConditions enable variable-based conditional rule execution. This is useful for - finer control of when an rule is applied. A condition can reference object data - using JMESPath notation. - Here, at least one of the conditions need to pass - items: - description: Condition defines variable-based - conditional criteria for rule execution. - properties: - key: - description: Key is the context entry - (using JMESPath) for conditional rule - evaluation. - x-kubernetes-preserve-unknown-fields: true - message: - description: Message is an optional - display message - type: string - operator: - description: |- - Operator is the conditional operation to perform. Valid operators are: - Equals, NotEquals, In, AnyIn, AllIn, NotIn, AnyNotIn, AllNotIn, GreaterThanOrEquals, - GreaterThan, LessThanOrEquals, LessThan, DurationGreaterThanOrEquals, DurationGreaterThan, - DurationLessThanOrEquals, DurationLessThan - enum: - - Equals - - NotEquals - - In - - AnyIn - - AllIn - - NotIn - - AnyNotIn - - AllNotIn - - GreaterThanOrEquals - - GreaterThan - - LessThanOrEquals - - LessThan - - DurationGreaterThanOrEquals - - DurationGreaterThan - - DurationLessThanOrEquals - - DurationLessThan - type: string - value: - description: |- - Value is the conditional value, or set of values. The values can be fixed set - or can be variables declared using JMESPath. - x-kubernetes-preserve-unknown-fields: true - type: object - type: array - type: object - x-kubernetes-preserve-unknown-fields: true - type: object - type: array - mutateExistingOnPolicyUpdate: - description: MutateExistingOnPolicyUpdate controls if - the mutateExisting rule will be applied on policy - events. - type: boolean - patchStrategicMerge: - description: |- - PatchStrategicMerge is a strategic merge patch used to modify resources. - See https://kubernetes.io/docs/tasks/manage-kubernetes-objects/update-api-object-kubectl-patch/ - and https://kubectl.docs.kubernetes.io/references/kustomize/kustomization/patchesstrategicmerge/. - x-kubernetes-preserve-unknown-fields: true - patchesJson6902: - description: |- - PatchesJSON6902 is a list of RFC 6902 JSON Patch declarations used to modify resources. - See https://tools.ietf.org/html/rfc6902 and https://kubectl.docs.kubernetes.io/references/kustomize/kustomization/patchesjson6902/. - type: string - targets: - description: Targets defines the target resources to - be mutated. - items: - description: TargetResourceSpec defines targets for - mutating existing resources. - properties: - apiVersion: - description: APIVersion specifies resource apiVersion. - type: string - context: - description: Context defines variables and data - sources that can be used during rule execution. - items: - description: |- - ContextEntry adds variables and data sources to a rule Context. Either a - ConfigMap reference or a APILookup must be provided. - oneOf: - - required: - - configMap - - required: - - apiCall - - required: - - imageRegistry - - required: - - variable - - required: - - globalReference - properties: - apiCall: - description: |- - APICall is an HTTP request to the Kubernetes API server, or other JSON web service. - The data returned is stored in the context with the name for the context entry. - properties: - data: - description: |- - The data object specifies the POST data sent to the server. - Only applicable when the method field is set to POST. - items: - description: RequestData contains - the HTTP POST data - properties: - key: - description: Key is a unique identifier - for the data value - type: string - value: - description: Value is the data - value - x-kubernetes-preserve-unknown-fields: true - required: - - key - - value - type: object - type: array - default: - description: |- - Default is an optional arbitrary JSON object that the context - value is set to, if the apiCall returns error. - x-kubernetes-preserve-unknown-fields: true - jmesPath: - description: |- - JMESPath is an optional JSON Match Expression that can be used to - transform the JSON response returned from the server. For example - a JMESPath of "items | length(@)" applied to the API server response - for the URLPath "/apis/apps/v1/deployments" will return the total count - of deployments across all namespaces. - type: string - method: - default: GET - description: Method is the HTTP request - type (GET or POST). Defaults to GET. - enum: - - GET - - POST - type: string - service: - description: |- - Service is an API call to a JSON web service. - This is used for non-Kubernetes API server calls. - It's mutually exclusive with the URLPath field. - properties: - caBundle: - description: |- - CABundle is a PEM encoded CA bundle which will be used to validate - the server certificate. - type: string - headers: - description: Headers is a list of - optional HTTP headers to be included - in the request. - items: - properties: - key: - description: Key is the header - key - type: string - value: - description: Value is the - header value - type: string - required: - - key - - value - type: object - type: array - url: - description: |- - URL is the JSON web service URL. A typical form is - `https://{service}.{namespace}:{port}/{path}`. - type: string - required: - - url - type: object - urlPath: - description: |- - URLPath is the URL path to be used in the HTTP GET or POST request to the - Kubernetes API server (e.g. "/api/v1/namespaces" or "/apis/apps/v1/deployments"). - The format required is the same format used by the `kubectl get --raw` command. - See https://kyverno.io/docs/writing-policies/external-data-sources/#variables-from-kubernetes-api-server-calls - for details. - It's mutually exclusive with the Service field. - type: string - type: object - configMap: - description: ConfigMap is the ConfigMap - reference. - properties: - name: - description: Name is the ConfigMap name. - type: string - namespace: - description: Namespace is the ConfigMap - namespace. - type: string - required: - - name - type: object - globalReference: - description: GlobalContextEntryReference - is a reference to a cached global context - entry. - properties: - jmesPath: - description: |- - JMESPath is an optional JSON Match Expression that can be used to - transform the JSON response returned from the server. For example - a JMESPath of "items | length(@)" applied to the API server response - for the URLPath "/apis/apps/v1/deployments" will return the total count - of deployments across all namespaces. - type: string - name: - description: Name of the global context - entry - type: string - required: - - name - type: object - imageRegistry: - description: |- - ImageRegistry defines requests to an OCI/Docker V2 registry to fetch image - details. - properties: - imageRegistryCredentials: - description: ImageRegistryCredentials - provides credentials that will be - used for authentication with registry - properties: - allowInsecureRegistry: - description: AllowInsecureRegistry - allows insecure access to a registry. - type: boolean - providers: - description: |- - Providers specifies a list of OCI Registry names, whose authentication providers are provided. - It can be of one of these values: default,google,azure,amazon,github. - items: - description: ImageRegistryCredentialsProvidersType - provides the list of credential - providers required. - enum: - - default - - amazon - - azure - - google - - github - type: string - type: array - secrets: - description: |- - Secrets specifies a list of secrets that are provided for credentials. - Secrets must live in the Kyverno namespace. - items: - type: string - type: array - type: object - jmesPath: - description: |- - JMESPath is an optional JSON Match Expression that can be used to - transform the ImageData struct returned as a result of processing - the image reference. - type: string - reference: - description: |- - Reference is image reference to a container image in the registry. - Example: ghcr.io/kyverno/kyverno:latest - type: string - required: - - reference - type: object - name: - description: Name is the variable name. - type: string - variable: - description: Variable defines an arbitrary - JMESPath context variable that can be - defined inline. - properties: - default: - description: |- - Default is an optional arbitrary JSON object that the variable may take if the JMESPath - expression evaluates to nil - x-kubernetes-preserve-unknown-fields: true - jmesPath: - description: |- - JMESPath is an optional JMESPath Expression that can be used to - transform the variable. - type: string - value: - description: Value is any arbitrary - JSON object representable in YAML - or JSON form. - x-kubernetes-preserve-unknown-fields: true - type: object - required: - - name - type: object - type: array - kind: - description: Kind specifies resource kind. - type: string - name: - description: Name specifies the resource name. - type: string - namespace: - description: Namespace specifies resource namespace. - type: string - preconditions: - description: |- - Preconditions are used to determine if a policy rule should be applied by evaluating a - set of conditions. The declaration can contain nested `any` or `all` statements. A direct list - of conditions (without `any` or `all` statements is supported for backwards compatibility but - will be deprecated in the next major release. - See: https://kyverno.io/docs/writing-policies/preconditions/ - x-kubernetes-preserve-unknown-fields: true - selector: - description: Selector allows you to select target - resources with their labels. - properties: - matchExpressions: - description: matchExpressions is a list of - label selector requirements. The requirements - are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key that - the selector applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - uid: - description: UID specifies the resource uid. - type: string - type: object - type: array - type: object - name: - description: Name is a label to identify the rule, It must - be unique within the policy. - maxLength: 63 - type: string - preconditions: - description: |- - Preconditions are used to determine if a policy rule should be applied by evaluating a - set of conditions. The declaration can contain nested `any` or `all` statements. A direct list - of conditions (without `any` or `all` statements is supported for backwards compatibility but - will be deprecated in the next major release. - See: https://kyverno.io/docs/writing-policies/preconditions/ - x-kubernetes-preserve-unknown-fields: true - reportProperties: - additionalProperties: - type: string - description: ReportProperties are the additional properties - from the rule that will be added to the policy report - result - type: object - skipBackgroundRequests: - default: true - description: |- - SkipBackgroundRequests bypasses admission requests that are sent by the background controller. - The default value is set to "true", it must be set to "false" to apply - generate and mutateExisting rules to those requests. - type: boolean - validate: - description: Validation is used to validate matching resources. - properties: - allowExistingViolations: - default: true - description: AllowExistingViolations allows prexisting - violating resources to continue violating a policy. - type: boolean - anyPattern: - description: |- - AnyPattern specifies list of validation patterns. At least one of the patterns - must be satisfied for the validation rule to succeed. - x-kubernetes-preserve-unknown-fields: true - assert: - description: Assert defines a kyverno-json assertion - tree. - type: object - x-kubernetes-preserve-unknown-fields: true - cel: - description: CEL allows validation checks using the - Common Expression Language (https://kubernetes.io/docs/reference/using-api/cel/). - properties: - auditAnnotations: - description: AuditAnnotations contains CEL expressions - which are used to produce audit annotations for - the audit event of the API request. - items: - description: AuditAnnotation describes how to - produce an audit annotation for an API request. - properties: - key: - description: |- - key specifies the audit annotation key. The audit annotation keys of - a ValidatingAdmissionPolicy must be unique. The key must be a qualified - name ([A-Za-z0-9][-A-Za-z0-9_.]*) no more than 63 bytes in length. - - The key is combined with the resource name of the - ValidatingAdmissionPolicy to construct an audit annotation key: - "{ValidatingAdmissionPolicy name}/{key}". - - If an admission webhook uses the same resource name as this ValidatingAdmissionPolicy - and the same audit annotation key, the annotation key will be identical. - In this case, the first annotation written with the key will be included - in the audit event and all subsequent annotations with the same key - will be discarded. - - Required. - type: string - valueExpression: - description: |- - valueExpression represents the expression which is evaluated by CEL to - produce an audit annotation value. The expression must evaluate to either - a string or null value. If the expression evaluates to a string, the - audit annotation is included with the string value. If the expression - evaluates to null or empty string the audit annotation will be omitted. - The valueExpression may be no longer than 5kb in length. - If the result of the valueExpression is more than 10kb in length, it - will be truncated to 10kb. - - If multiple ValidatingAdmissionPolicyBinding resources match an - API request, then the valueExpression will be evaluated for - each binding. All unique values produced by the valueExpressions - will be joined together in a comma-separated list. - - Required. - type: string - required: - - key - - valueExpression - type: object - type: array - expressions: - description: Expressions is a list of CELExpression - types. - items: - description: Validation specifies the CEL expression - which is used to apply the validation. - properties: - expression: - description: "Expression represents the expression - which will be evaluated by CEL.\nref: https://github.com/google/cel-spec\nCEL - expressions have access to the contents - of the API request/response, organized into - CEL variables as well as some other useful - variables:\n\n- 'object' - The object from - the incoming request. The value is null - for DELETE requests.\n- 'oldObject' - The - existing object. The value is null for CREATE - requests.\n- 'request' - Attributes of the - API request([ref](/pkg/apis/admission/types.go#AdmissionRequest)).\n- - 'params' - Parameter resource referred to - by the policy binding being evaluated. Only - populated if the policy has a ParamKind.\n- - 'namespaceObject' - The namespace object - that the incoming object belongs to. The - value is null for cluster-scoped resources.\n- - 'variables' - Map of composited variables, - from its name to its lazily evaluated value.\n - \ For example, a variable named 'foo' can - be accessed as 'variables.foo'.\n- 'authorizer' - - A CEL Authorizer. May be used to perform - authorization checks for the principal (user - or service account) of the request.\n See - https://pkg.go.dev/k8s.io/apiserver/pkg/cel/library#Authz\n- - 'authorizer.requestResource' - A CEL ResourceCheck - constructed from the 'authorizer' and configured - with the\n request resource.\n\nThe `apiVersion`, - `kind`, `metadata.name` and `metadata.generateName` - are always accessible from the root of the\nobject. - No other metadata properties are accessible.\n\nOnly - property names of the form `[a-zA-Z_.-/][a-zA-Z0-9_.-/]*` - are accessible.\nAccessible property names - are escaped according to the following rules - when accessed in the expression:\n- '__' - escapes to '__underscores__'\n- '.' escapes - to '__dot__'\n- '-' escapes to '__dash__'\n- - '/' escapes to '__slash__'\n- Property names - that exactly match a CEL RESERVED keyword - escape to '__{keyword}__'. The keywords - are:\n\t \"true\", \"false\", \"null\", - \"in\", \"as\", \"break\", \"const\", \"continue\", - \"else\", \"for\", \"function\", \"if\",\n\t - \ \"import\", \"let\", \"loop\", \"package\", - \"namespace\", \"return\".\nExamples:\n - \ - Expression accessing a property named - \"namespace\": {\"Expression\": \"object.__namespace__ - > 0\"}\n - Expression accessing a property - named \"x-prop\": {\"Expression\": \"object.x__dash__prop - > 0\"}\n - Expression accessing a property - named \"redact__d\": {\"Expression\": \"object.redact__underscores__d - > 0\"}\n\nEquality on arrays with list type - of 'set' or 'map' ignores element order, - i.e. [1, 2] == [2, 1].\nConcatenation on - arrays with x-kubernetes-list-type use the - semantics of the list type:\n - 'set': - `X + Y` performs a union where the array - positions of all elements in `X` are preserved - and\n non-intersecting elements in `Y` - are appended, retaining their partial order.\n - \ - 'map': `X + Y` performs a merge where - the array positions of all keys in `X` are - preserved but the values\n are overwritten - by values in `Y` when the key sets of `X` - and `Y` intersect. Elements in `Y` with\n - \ non-intersecting keys are appended, - retaining their partial order.\nRequired." - type: string - message: - description: |- - Message represents the message displayed when validation fails. The message is required if the Expression contains - line breaks. The message must not contain line breaks. - If unset, the message is "failed rule: {Rule}". - e.g. "must be a URL with the host matching spec.host" - If the Expression contains line breaks. Message is required. - The message must not contain line breaks. - If unset, the message is "failed Expression: {Expression}". - type: string - messageExpression: - description: |- - messageExpression declares a CEL expression that evaluates to the validation failure message that is returned when this rule fails. - Since messageExpression is used as a failure message, it must evaluate to a string. - If both message and messageExpression are present on a validation, then messageExpression will be used if validation fails. - If messageExpression results in a runtime error, the runtime error is logged, and the validation failure message is produced - as if the messageExpression field were unset. If messageExpression evaluates to an empty string, a string with only spaces, or a string - that contains line breaks, then the validation failure message will also be produced as if the messageExpression field were unset, and - the fact that messageExpression produced an empty string/string with only spaces/string with line breaks will be logged. - messageExpression has access to all the same variables as the `expression` except for 'authorizer' and 'authorizer.requestResource'. - Example: - "object.x must be less than max ("+string(params.max)+")" - type: string - reason: - description: |- - Reason represents a machine-readable description of why this validation failed. - If this is the first validation in the list to fail, this reason, as well as the - corresponding HTTP response code, are used in the - HTTP response to the client. - The currently supported reasons are: "Unauthorized", "Forbidden", "Invalid", "RequestEntityTooLarge". - If not set, StatusReasonInvalid is used in the response to the client. - type: string - required: - - expression - type: object - type: array - generate: - default: false - description: |- - Generate specifies whether to generate a Kubernetes ValidatingAdmissionPolicy from the rule. - Optional. Defaults to "false" if not specified. - type: boolean - paramKind: - description: ParamKind is a tuple of Group Kind - and Version. - properties: - apiVersion: - description: |- - APIVersion is the API group version the resources belong to. - In format of "group/version". - Required. - type: string - kind: - description: |- - Kind is the API kind the resources belong to. - Required. - type: string - type: object - x-kubernetes-map-type: atomic - paramRef: - description: ParamRef references a parameter resource. - properties: - name: - description: |- - name is the name of the resource being referenced. - - One of `name` or `selector` must be set, but `name` and `selector` are - mutually exclusive properties. If one is set, the other must be unset. - - A single parameter used for all admission requests can be configured - by setting the `name` field, leaving `selector` blank, and setting namespace - if `paramKind` is namespace-scoped. - type: string - namespace: - description: |- - namespace is the namespace of the referenced resource. Allows limiting - the search for params to a specific namespace. Applies to both `name` and - `selector` fields. - - A per-namespace parameter may be used by specifying a namespace-scoped - `paramKind` in the policy and leaving this field empty. - - - If `paramKind` is cluster-scoped, this field MUST be unset. Setting this - field results in a configuration error. - - - If `paramKind` is namespace-scoped, the namespace of the object being - evaluated for admission will be used when this field is left unset. Take - care that if this is left empty the binding must not match any cluster-scoped - resources, which will result in an error. - type: string - parameterNotFoundAction: - description: |- - `parameterNotFoundAction` controls the behavior of the binding when the resource - exists, and name or selector is valid, but there are no parameters - matched by the binding. If the value is set to `Allow`, then no - matched parameters will be treated as successful validation by the binding. - If set to `Deny`, then no matched parameters will be subject to the - `failurePolicy` of the policy. - - Allowed values are `Allow` or `Deny` - - Required - type: string - selector: - description: |- - selector can be used to match multiple param objects based on their labels. - Supply selector: {} to match all resources of the ParamKind. - - If multiple params are found, they are all evaluated with the policy expressions - and the results are ANDed together. - - One of `name` or `selector` must be set, but `name` and `selector` are - mutually exclusive properties. If one is set, the other must be unset. - properties: - matchExpressions: - description: matchExpressions is a list - of label selector requirements. The requirements - are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key - that the selector applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - type: object - x-kubernetes-map-type: atomic - variables: - description: |- - Variables contain definitions of variables that can be used in composition of other expressions. - Each variable is defined as a named CEL expression. - The variables defined here will be available under `variables` in other expressions of the policy. - items: - description: Variable is the definition of a variable - that is used for composition. A variable is - defined as a named expression. - properties: - expression: - description: |- - Expression is the expression that will be evaluated as the value of the variable. - The CEL expression has access to the same identifiers as the CEL expressions in Validation. - type: string - name: - description: |- - Name is the name of the variable. The name must be a valid CEL identifier and unique among all variables. - The variable can be accessed in other expressions through `variables` - For example, if name is "foo", the variable will be available as `variables.foo` - type: string - required: - - expression - - name - type: object - x-kubernetes-map-type: atomic - type: array - type: object - deny: - description: Deny defines conditions used to pass or - fail a validation rule. - properties: - conditions: - description: |- - Multiple conditions can be declared under an `any` or `all` statement. A direct list - of conditions (without `any` or `all` statements) is also supported for backwards compatibility - but will be deprecated in the next major release. - See: https://kyverno.io/docs/writing-policies/validate/#deny-rules - x-kubernetes-preserve-unknown-fields: true - type: object - failureAction: - description: |- - FailureAction defines if a validation policy rule violation should block - the admission review request (Enforce), or allow (Audit) the admission review request - and report an error in a policy report. Optional. - Allowed values are Audit or Enforce. - enum: - - Audit - - Enforce - type: string - failureActionOverrides: - description: |- - FailureActionOverrides is a Cluster Policy attribute that specifies FailureAction - namespace-wise. It overrides FailureAction for the specified namespaces. - items: - properties: - action: - description: ValidationFailureAction defines the - policy validation failure action - enum: - - audit - - enforce - - Audit - - Enforce - type: string - namespaceSelector: - description: |- - A label selector is a label query over a set of resources. The result of matchLabels and - matchExpressions are ANDed. An empty label selector matches all objects. A null - label selector matches no objects. - properties: - matchExpressions: - description: matchExpressions is a list of - label selector requirements. The requirements - are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key that - the selector applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - namespaces: - items: - type: string - type: array - type: object - type: array - foreach: - description: ForEach applies validate rules to a list - of sub-elements by creating a context for each entry - in the list and looping over it to apply the specified - logic. - items: - description: ForEachValidation applies validate rules - to a list of sub-elements by creating a context - for each entry in the list and looping over it to - apply the specified logic. - properties: - anyPattern: - description: |- - AnyPattern specifies list of validation patterns. At least one of the patterns - must be satisfied for the validation rule to succeed. - x-kubernetes-preserve-unknown-fields: true - context: - description: Context defines variables and data - sources that can be used during rule execution. - items: - description: |- - ContextEntry adds variables and data sources to a rule Context. Either a - ConfigMap reference or a APILookup must be provided. - oneOf: - - required: - - configMap - - required: - - apiCall - - required: - - imageRegistry - - required: - - variable - - required: - - globalReference - properties: - apiCall: - description: |- - APICall is an HTTP request to the Kubernetes API server, or other JSON web service. - The data returned is stored in the context with the name for the context entry. - properties: - data: - description: |- - The data object specifies the POST data sent to the server. - Only applicable when the method field is set to POST. - items: - description: RequestData contains - the HTTP POST data - properties: - key: - description: Key is a unique identifier - for the data value - type: string - value: - description: Value is the data - value - x-kubernetes-preserve-unknown-fields: true - required: - - key - - value - type: object - type: array - default: - description: |- - Default is an optional arbitrary JSON object that the context - value is set to, if the apiCall returns error. - x-kubernetes-preserve-unknown-fields: true - jmesPath: - description: |- - JMESPath is an optional JSON Match Expression that can be used to - transform the JSON response returned from the server. For example - a JMESPath of "items | length(@)" applied to the API server response - for the URLPath "/apis/apps/v1/deployments" will return the total count - of deployments across all namespaces. - type: string - method: - default: GET - description: Method is the HTTP request - type (GET or POST). Defaults to GET. - enum: - - GET - - POST - type: string - service: - description: |- - Service is an API call to a JSON web service. - This is used for non-Kubernetes API server calls. - It's mutually exclusive with the URLPath field. - properties: - caBundle: - description: |- - CABundle is a PEM encoded CA bundle which will be used to validate - the server certificate. - type: string - headers: - description: Headers is a list of - optional HTTP headers to be included - in the request. - items: - properties: - key: - description: Key is the header - key - type: string - value: - description: Value is the - header value - type: string - required: - - key - - value - type: object - type: array - url: - description: |- - URL is the JSON web service URL. A typical form is - `https://{service}.{namespace}:{port}/{path}`. - type: string - required: - - url - type: object - urlPath: - description: |- - URLPath is the URL path to be used in the HTTP GET or POST request to the - Kubernetes API server (e.g. "/api/v1/namespaces" or "/apis/apps/v1/deployments"). - The format required is the same format used by the `kubectl get --raw` command. - See https://kyverno.io/docs/writing-policies/external-data-sources/#variables-from-kubernetes-api-server-calls - for details. - It's mutually exclusive with the Service field. - type: string - type: object - configMap: - description: ConfigMap is the ConfigMap - reference. - properties: - name: - description: Name is the ConfigMap name. - type: string - namespace: - description: Namespace is the ConfigMap - namespace. - type: string - required: - - name - type: object - globalReference: - description: GlobalContextEntryReference - is a reference to a cached global context - entry. - properties: - jmesPath: - description: |- - JMESPath is an optional JSON Match Expression that can be used to - transform the JSON response returned from the server. For example - a JMESPath of "items | length(@)" applied to the API server response - for the URLPath "/apis/apps/v1/deployments" will return the total count - of deployments across all namespaces. - type: string - name: - description: Name of the global context - entry - type: string - required: - - name - type: object - imageRegistry: - description: |- - ImageRegistry defines requests to an OCI/Docker V2 registry to fetch image - details. - properties: - imageRegistryCredentials: - description: ImageRegistryCredentials - provides credentials that will be - used for authentication with registry - properties: - allowInsecureRegistry: - description: AllowInsecureRegistry - allows insecure access to a registry. - type: boolean - providers: - description: |- - Providers specifies a list of OCI Registry names, whose authentication providers are provided. - It can be of one of these values: default,google,azure,amazon,github. - items: - description: ImageRegistryCredentialsProvidersType - provides the list of credential - providers required. - enum: - - default - - amazon - - azure - - google - - github - type: string - type: array - secrets: - description: |- - Secrets specifies a list of secrets that are provided for credentials. - Secrets must live in the Kyverno namespace. - items: - type: string - type: array - type: object - jmesPath: - description: |- - JMESPath is an optional JSON Match Expression that can be used to - transform the ImageData struct returned as a result of processing - the image reference. - type: string - reference: - description: |- - Reference is image reference to a container image in the registry. - Example: ghcr.io/kyverno/kyverno:latest - type: string - required: - - reference - type: object - name: - description: Name is the variable name. - type: string - variable: - description: Variable defines an arbitrary - JMESPath context variable that can be - defined inline. - properties: - default: - description: |- - Default is an optional arbitrary JSON object that the variable may take if the JMESPath - expression evaluates to nil - x-kubernetes-preserve-unknown-fields: true - jmesPath: - description: |- - JMESPath is an optional JMESPath Expression that can be used to - transform the variable. - type: string - value: - description: Value is any arbitrary - JSON object representable in YAML - or JSON form. - x-kubernetes-preserve-unknown-fields: true - type: object - required: - - name - type: object - type: array - deny: - description: Deny defines conditions used to pass - or fail a validation rule. - properties: - conditions: - description: |- - Multiple conditions can be declared under an `any` or `all` statement. A direct list - of conditions (without `any` or `all` statements) is also supported for backwards compatibility - but will be deprecated in the next major release. - See: https://kyverno.io/docs/writing-policies/validate/#deny-rules - x-kubernetes-preserve-unknown-fields: true - type: object - elementScope: - description: |- - ElementScope specifies whether to use the current list element as the scope for validation. Defaults to "true" if not specified. - When set to "false", "request.object" is used as the validation scope within the foreach - block to allow referencing other elements in the subtree. - type: boolean - foreach: - description: Foreach declares a nested foreach - iterator - x-kubernetes-preserve-unknown-fields: true - list: - description: |- - List specifies a JMESPath expression that results in one or more elements - to which the validation logic is applied. - type: string - pattern: - description: Pattern specifies an overlay-style - pattern used to check resources. - x-kubernetes-preserve-unknown-fields: true - preconditions: - description: |- - AnyAllConditions are used to determine if a policy rule should be applied by evaluating a - set of conditions. The declaration can contain nested `any` or `all` statements. - See: https://kyverno.io/docs/writing-policies/preconditions/ - properties: - all: - description: |- - AllConditions enable variable-based conditional rule execution. This is useful for - finer control of when an rule is applied. A condition can reference object data - using JMESPath notation. - Here, all of the conditions need to pass - items: - description: Condition defines variable-based - conditional criteria for rule execution. - properties: - key: - description: Key is the context entry - (using JMESPath) for conditional rule - evaluation. - x-kubernetes-preserve-unknown-fields: true - message: - description: Message is an optional - display message - type: string - operator: - description: |- - Operator is the conditional operation to perform. Valid operators are: - Equals, NotEquals, In, AnyIn, AllIn, NotIn, AnyNotIn, AllNotIn, GreaterThanOrEquals, - GreaterThan, LessThanOrEquals, LessThan, DurationGreaterThanOrEquals, DurationGreaterThan, - DurationLessThanOrEquals, DurationLessThan - enum: - - Equals - - NotEquals - - In - - AnyIn - - AllIn - - NotIn - - AnyNotIn - - AllNotIn - - GreaterThanOrEquals - - GreaterThan - - LessThanOrEquals - - LessThan - - DurationGreaterThanOrEquals - - DurationGreaterThan - - DurationLessThanOrEquals - - DurationLessThan - type: string - value: - description: |- - Value is the conditional value, or set of values. The values can be fixed set - or can be variables declared using JMESPath. - x-kubernetes-preserve-unknown-fields: true - type: object - type: array - any: - description: |- - AnyConditions enable variable-based conditional rule execution. This is useful for - finer control of when an rule is applied. A condition can reference object data - using JMESPath notation. - Here, at least one of the conditions need to pass - items: - description: Condition defines variable-based - conditional criteria for rule execution. - properties: - key: - description: Key is the context entry - (using JMESPath) for conditional rule - evaluation. - x-kubernetes-preserve-unknown-fields: true - message: - description: Message is an optional - display message - type: string - operator: - description: |- - Operator is the conditional operation to perform. Valid operators are: - Equals, NotEquals, In, AnyIn, AllIn, NotIn, AnyNotIn, AllNotIn, GreaterThanOrEquals, - GreaterThan, LessThanOrEquals, LessThan, DurationGreaterThanOrEquals, DurationGreaterThan, - DurationLessThanOrEquals, DurationLessThan - enum: - - Equals - - NotEquals - - In - - AnyIn - - AllIn - - NotIn - - AnyNotIn - - AllNotIn - - GreaterThanOrEquals - - GreaterThan - - LessThanOrEquals - - LessThan - - DurationGreaterThanOrEquals - - DurationGreaterThan - - DurationLessThanOrEquals - - DurationLessThan - type: string - value: - description: |- - Value is the conditional value, or set of values. The values can be fixed set - or can be variables declared using JMESPath. - x-kubernetes-preserve-unknown-fields: true - type: object - type: array - type: object - x-kubernetes-preserve-unknown-fields: true - type: object - type: array - manifests: - description: Manifest specifies conditions for manifest - verification - properties: - annotationDomain: - description: AnnotationDomain is custom domain of - annotation for message and signature. Default - is "cosign.sigstore.dev". - type: string - attestors: - description: Attestors specified the required attestors - (i.e. authorities) - items: - properties: - count: - description: |- - Count specifies the required number of entries that must match. If the count is null, all entries must match - (a logical AND). If the count is 1, at least one entry must match (a logical OR). If the count contains a - value N, then N must be less than or equal to the size of entries, and at least N entries must match. - minimum: 1 - type: integer - entries: - description: |- - Entries contains the available attestors. An attestor can be a static key, - attributes for keyless verification, or a nested attestor declaration. - items: - properties: - annotations: - additionalProperties: - type: string - description: |- - Annotations are used for image verification. - Every specified key-value pair must exist and match in the verified payload. - The payload may contain other key-value pairs. - type: object - attestor: - description: Attestor is a nested set - of Attestor used to specify a more - complex set of match authorities. - x-kubernetes-preserve-unknown-fields: true - certificates: - description: Certificates specifies - one or more certificates. - properties: - cert: - description: Cert is an optional - PEM-encoded public certificate. - type: string - certChain: - description: CertChain is an optional - PEM encoded set of certificates - used to verify. - type: string - ctlog: - description: |- - CTLog (certificate timestamp log) provides a configuration for validation of Signed Certificate - Timestamps (SCTs). If the value is unset, the default behavior by Cosign is used. - properties: - ignoreSCT: - description: |- - IgnoreSCT defines whether to use the Signed Certificate Timestamp (SCT) log to check for a certificate - timestamp. Default is false. Set to true if this was opted out during signing. - type: boolean - pubkey: - description: PubKey, if set, - is used to validate SCTs against - a custom source. - type: string - tsaCertChain: - description: |- - TSACertChain, if set, is the PEM-encoded certificate chain file for the RFC3161 timestamp authority. Must - contain the root CA certificate. Optionally may contain intermediate CA certificates, and - may contain the leaf TSA certificate if not present in the timestamurce. - type: string - type: object - rekor: - description: |- - Rekor provides configuration for the Rekor transparency log service. If an empty object - is provided the public instance of Rekor (https://rekor.sigstore.dev) is used. - properties: - ignoreTlog: - description: IgnoreTlog skips - transparency log verification. - type: boolean - pubkey: - description: |- - RekorPubKey is an optional PEM-encoded public key to use for a custom Rekor. - If set, this will be used to validate transparency log signatures from a custom Rekor. - type: string - url: - description: URL is the address - of the transparency log. Defaults - to the public Rekor log instance - https://rekor.sigstore.dev. - type: string - type: object - type: object - keyless: - description: |- - Keyless is a set of attribute used to verify a Sigstore keyless attestor. - See https://github.com/sigstore/cosign/blob/main/KEYLESS.md. - properties: - additionalExtensions: - additionalProperties: - type: string - description: AdditionalExtensions - are certificate-extensions used - for keyless signing. - type: object - ctlog: - description: |- - CTLog (certificate timestamp log) provides a configuration for validation of Signed Certificate - Timestamps (SCTs). If the value is unset, the default behavior by Cosign is used. - properties: - ignoreSCT: - description: |- - IgnoreSCT defines whether to use the Signed Certificate Timestamp (SCT) log to check for a certificate - timestamp. Default is false. Set to true if this was opted out during signing. - type: boolean - pubkey: - description: PubKey, if set, - is used to validate SCTs against - a custom source. - type: string - tsaCertChain: - description: |- - TSACertChain, if set, is the PEM-encoded certificate chain file for the RFC3161 timestamp authority. Must - contain the root CA certificate. Optionally may contain intermediate CA certificates, and - may contain the leaf TSA certificate if not present in the timestamurce. - type: string - type: object - issuer: - description: Issuer is the certificate - issuer used for keyless signing. - type: string - issuerRegExp: - description: IssuerRegExp is the - regular expression to match certificate - issuer used for keyless signing. - type: string - rekor: - description: |- - Rekor provides configuration for the Rekor transparency log service. If an empty object - is provided the public instance of Rekor (https://rekor.sigstore.dev) is used. - properties: - ignoreTlog: - description: IgnoreTlog skips - transparency log verification. - type: boolean - pubkey: - description: |- - RekorPubKey is an optional PEM-encoded public key to use for a custom Rekor. - If set, this will be used to validate transparency log signatures from a custom Rekor. - type: string - url: - description: URL is the address - of the transparency log. Defaults - to the public Rekor log instance - https://rekor.sigstore.dev. - type: string - type: object - roots: - description: |- - Roots is an optional set of PEM encoded trusted root certificates. - If not provided, the system roots are used. - type: string - subject: - description: Subject is the verified - identity used for keyless signing, - for example the email address. - type: string - subjectRegExp: - description: SubjectRegExp is the - regular expression to match identity - used for keyless signing, for - example the email address. - type: string - type: object - keys: - description: Keys specifies one or more - public keys. - properties: - ctlog: - description: |- - CTLog (certificate timestamp log) provides a configuration for validation of Signed Certificate - Timestamps (SCTs). If the value is unset, the default behavior by Cosign is used. - properties: - ignoreSCT: - description: |- - IgnoreSCT defines whether to use the Signed Certificate Timestamp (SCT) log to check for a certificate - timestamp. Default is false. Set to true if this was opted out during signing. - type: boolean - pubkey: - description: PubKey, if set, - is used to validate SCTs against - a custom source. - type: string - tsaCertChain: - description: |- - TSACertChain, if set, is the PEM-encoded certificate chain file for the RFC3161 timestamp authority. Must - contain the root CA certificate. Optionally may contain intermediate CA certificates, and - may contain the leaf TSA certificate if not present in the timestamurce. - type: string - type: object - kms: - description: |- - KMS provides the URI to the public key stored in a Key Management System. See: - https://github.com/sigstore/cosign/blob/main/KMS.md - type: string - publicKeys: - description: |- - Keys is a set of X.509 public keys used to verify image signatures. The keys can be directly - specified or can be a variable reference to a key specified in a ConfigMap (see - https://kyverno.io/docs/writing-policies/variables/), or reference a standard Kubernetes Secret - elsewhere in the cluster by specifying it in the format "k8s:///". - The named Secret must specify a key `cosign.pub` containing the public key used for - verification, (see https://github.com/sigstore/cosign/blob/main/KMS.md#kubernetes-secret). - When multiple keys are specified each key is processed as a separate staticKey entry - (.attestors[*].entries.keys) within the set of attestors and the count is applied across the keys. - type: string - rekor: - description: |- - Rekor provides configuration for the Rekor transparency log service. If an empty object - is provided the public instance of Rekor (https://rekor.sigstore.dev) is used. - properties: - ignoreTlog: - description: IgnoreTlog skips - transparency log verification. - type: boolean - pubkey: - description: |- - RekorPubKey is an optional PEM-encoded public key to use for a custom Rekor. - If set, this will be used to validate transparency log signatures from a custom Rekor. - type: string - url: - description: URL is the address - of the transparency log. Defaults - to the public Rekor log instance - https://rekor.sigstore.dev. - type: string - type: object - secret: - description: Reference to a Secret - resource that contains a public - key - properties: - name: - description: Name of the secret. - The provided secret must contain - a key named cosign.pub. - type: string - namespace: - description: Namespace name - where the Secret exists. - type: string - required: - - name - - namespace - type: object - signatureAlgorithm: - default: sha256 - description: Deprecated. Use attestor.signatureAlgorithm - instead. - type: string - type: object - repository: - description: |- - Repository is an optional alternate OCI repository to use for signatures and attestations that match this rule. - If specified Repository will override other OCI image repository locations for this Attestor. - type: string - signatureAlgorithm: - default: sha256 - description: Specify signature algorithm - for public keys. Supported values - are sha224, sha256, sha384 and sha512. - type: string - type: object - type: array - type: object - type: array - dryRun: - description: DryRun configuration - properties: - enable: - type: boolean - namespace: - type: string - type: object - ignoreFields: - description: Fields which will be ignored while - comparing manifests. - items: - properties: - fields: - items: - type: string - type: array - objects: - items: - properties: - group: - type: string - kind: - type: string - name: - type: string - namespace: - type: string - version: - type: string - type: object - type: array - type: object - type: array - repository: - description: |- - Repository is an optional alternate OCI repository to use for resource bundle reference. - The repository can be overridden per Attestor or Attestation. - type: string - type: object - message: - description: Message specifies a custom message to be - displayed on failure. - type: string - pattern: - description: Pattern specifies an overlay-style pattern - used to check resources. - x-kubernetes-preserve-unknown-fields: true - podSecurity: - description: |- - PodSecurity applies exemptions for Kubernetes Pod Security admission - by specifying exclusions for Pod Security Standards controls. - properties: - exclude: - description: Exclude specifies the Pod Security - Standard controls to be excluded. - items: - description: PodSecurityStandard specifies the - Pod Security Standard controls to be excluded. - properties: - controlName: - description: |- - ControlName specifies the name of the Pod Security Standard control. - See: https://kubernetes.io/docs/concepts/security/pod-security-standards/ - enum: - - HostProcess - - Host Namespaces - - Privileged Containers - - Capabilities - - HostPath Volumes - - Host Ports - - AppArmor - - SELinux - - /proc Mount Type - - Seccomp - - Sysctls - - Volume Types - - Privilege Escalation - - Running as Non-root - - Running as Non-root user - type: string - images: - description: |- - Images selects matching containers and applies the container level PSS. - Each image is the image name consisting of the registry address, repository, image, and tag. - Empty list matches no containers, PSS checks are applied at the pod level only. - Wildcards ('*' and '?') are allowed. See: https://kubernetes.io/docs/concepts/containers/images. - items: - type: string - type: array - restrictedField: - description: |- - RestrictedField selects the field for the given Pod Security Standard control. - When not set, all restricted fields for the control are selected. - type: string - values: - description: Values defines the allowed values - that can be excluded. - items: - type: string - type: array - required: - - controlName - type: object - type: array - level: - description: |- - Level defines the Pod Security Standard level to be applied to workloads. - Allowed values are privileged, baseline, and restricted. - enum: - - privileged - - baseline - - restricted - type: string - version: - description: |- - Version defines the Pod Security Standard versions that Kubernetes supports. - Allowed values are v1.19, v1.20, v1.21, v1.22, v1.23, v1.24, v1.25, v1.26, v1.27, v1.28, v1.29, latest. Defaults to latest. - enum: - - v1.19 - - v1.20 - - v1.21 - - v1.22 - - v1.23 - - v1.24 - - v1.25 - - v1.26 - - v1.27 - - v1.28 - - v1.29 - - latest - type: string - type: object - type: object - verifyImages: - description: VerifyImages is used to verify image signatures - and mutate them to add a digest - items: - description: |- - ImageVerification validates that images that match the specified pattern - are signed with the supplied public key. Once the image is verified it is - mutated to include the SHA digest retrieved during the registration. - properties: - additionalExtensions: - additionalProperties: - type: string - description: Deprecated. - type: object - annotations: - additionalProperties: - type: string - description: Deprecated. Use annotations per Attestor - instead. - type: object - attestations: - description: |- - Attestations are optional checks for signed in-toto Statements used to verify the image. - See https://github.com/in-toto/attestation. Kyverno fetches signed attestations from the - OCI registry and decodes them into a list of Statement declarations. - items: - description: |- - Attestation are checks for signed in-toto Statements that are used to verify the image. - See https://github.com/in-toto/attestation. Kyverno fetches signed attestations from the - OCI registry and decodes them into a list of Statements. - properties: - attestors: - description: Attestors specify the required - attestors (i.e. authorities). - items: - properties: - count: - description: |- - Count specifies the required number of entries that must match. If the count is null, all entries must match - (a logical AND). If the count is 1, at least one entry must match (a logical OR). If the count contains a - value N, then N must be less than or equal to the size of entries, and at least N entries must match. - minimum: 1 - type: integer - entries: - description: |- - Entries contains the available attestors. An attestor can be a static key, - attributes for keyless verification, or a nested attestor declaration. - items: - properties: - annotations: - additionalProperties: - type: string - description: |- - Annotations are used for image verification. - Every specified key-value pair must exist and match in the verified payload. - The payload may contain other key-value pairs. - type: object - attestor: - description: Attestor is a nested - set of Attestor used to specify - a more complex set of match authorities. - x-kubernetes-preserve-unknown-fields: true - certificates: - description: Certificates specifies - one or more certificates. - properties: - cert: - description: Cert is an optional - PEM-encoded public certificate. - type: string - certChain: - description: CertChain is an - optional PEM encoded set of - certificates used to verify. - type: string - ctlog: - description: |- - CTLog (certificate timestamp log) provides a configuration for validation of Signed Certificate - Timestamps (SCTs). If the value is unset, the default behavior by Cosign is used. - properties: - ignoreSCT: - description: |- - IgnoreSCT defines whether to use the Signed Certificate Timestamp (SCT) log to check for a certificate - timestamp. Default is false. Set to true if this was opted out during signing. - type: boolean - pubkey: - description: PubKey, if - set, is used to validate - SCTs against a custom - source. - type: string - tsaCertChain: - description: |- - TSACertChain, if set, is the PEM-encoded certificate chain file for the RFC3161 timestamp authority. Must - contain the root CA certificate. Optionally may contain intermediate CA certificates, and - may contain the leaf TSA certificate if not present in the timestamurce. - type: string - type: object - rekor: - description: |- - Rekor provides configuration for the Rekor transparency log service. If an empty object - is provided the public instance of Rekor (https://rekor.sigstore.dev) is used. - properties: - ignoreTlog: - description: IgnoreTlog - skips transparency log - verification. - type: boolean - pubkey: - description: |- - RekorPubKey is an optional PEM-encoded public key to use for a custom Rekor. - If set, this will be used to validate transparency log signatures from a custom Rekor. - type: string - url: - description: URL is the - address of the transparency - log. Defaults to the public - Rekor log instance https://rekor.sigstore.dev. - type: string - type: object - type: object - keyless: - description: |- - Keyless is a set of attribute used to verify a Sigstore keyless attestor. - See https://github.com/sigstore/cosign/blob/main/KEYLESS.md. - properties: - additionalExtensions: - additionalProperties: - type: string - description: AdditionalExtensions - are certificate-extensions - used for keyless signing. - type: object - ctlog: - description: |- - CTLog (certificate timestamp log) provides a configuration for validation of Signed Certificate - Timestamps (SCTs). If the value is unset, the default behavior by Cosign is used. - properties: - ignoreSCT: - description: |- - IgnoreSCT defines whether to use the Signed Certificate Timestamp (SCT) log to check for a certificate - timestamp. Default is false. Set to true if this was opted out during signing. - type: boolean - pubkey: - description: PubKey, if - set, is used to validate - SCTs against a custom - source. - type: string - tsaCertChain: - description: |- - TSACertChain, if set, is the PEM-encoded certificate chain file for the RFC3161 timestamp authority. Must - contain the root CA certificate. Optionally may contain intermediate CA certificates, and - may contain the leaf TSA certificate if not present in the timestamurce. - type: string - type: object - issuer: - description: Issuer is the certificate - issuer used for keyless signing. - type: string - issuerRegExp: - description: IssuerRegExp is - the regular expression to - match certificate issuer used - for keyless signing. - type: string - rekor: - description: |- - Rekor provides configuration for the Rekor transparency log service. If an empty object - is provided the public instance of Rekor (https://rekor.sigstore.dev) is used. - properties: - ignoreTlog: - description: IgnoreTlog - skips transparency log - verification. - type: boolean - pubkey: - description: |- - RekorPubKey is an optional PEM-encoded public key to use for a custom Rekor. - If set, this will be used to validate transparency log signatures from a custom Rekor. - type: string - url: - description: URL is the - address of the transparency - log. Defaults to the public - Rekor log instance https://rekor.sigstore.dev. - type: string - type: object - roots: - description: |- - Roots is an optional set of PEM encoded trusted root certificates. - If not provided, the system roots are used. - type: string - subject: - description: Subject is the - verified identity used for - keyless signing, for example - the email address. - type: string - subjectRegExp: - description: SubjectRegExp is - the regular expression to - match identity used for keyless - signing, for example the email - address. - type: string - type: object - keys: - description: Keys specifies one - or more public keys. - properties: - ctlog: - description: |- - CTLog (certificate timestamp log) provides a configuration for validation of Signed Certificate - Timestamps (SCTs). If the value is unset, the default behavior by Cosign is used. - properties: - ignoreSCT: - description: |- - IgnoreSCT defines whether to use the Signed Certificate Timestamp (SCT) log to check for a certificate - timestamp. Default is false. Set to true if this was opted out during signing. - type: boolean - pubkey: - description: PubKey, if - set, is used to validate - SCTs against a custom - source. - type: string - tsaCertChain: - description: |- - TSACertChain, if set, is the PEM-encoded certificate chain file for the RFC3161 timestamp authority. Must - contain the root CA certificate. Optionally may contain intermediate CA certificates, and - may contain the leaf TSA certificate if not present in the timestamurce. - type: string - type: object - kms: - description: |- - KMS provides the URI to the public key stored in a Key Management System. See: - https://github.com/sigstore/cosign/blob/main/KMS.md - type: string - publicKeys: - description: |- - Keys is a set of X.509 public keys used to verify image signatures. The keys can be directly - specified or can be a variable reference to a key specified in a ConfigMap (see - https://kyverno.io/docs/writing-policies/variables/), or reference a standard Kubernetes Secret - elsewhere in the cluster by specifying it in the format "k8s:///". - The named Secret must specify a key `cosign.pub` containing the public key used for - verification, (see https://github.com/sigstore/cosign/blob/main/KMS.md#kubernetes-secret). - When multiple keys are specified each key is processed as a separate staticKey entry - (.attestors[*].entries.keys) within the set of attestors and the count is applied across the keys. - type: string - rekor: - description: |- - Rekor provides configuration for the Rekor transparency log service. If an empty object - is provided the public instance of Rekor (https://rekor.sigstore.dev) is used. - properties: - ignoreTlog: - description: IgnoreTlog - skips transparency log - verification. - type: boolean - pubkey: - description: |- - RekorPubKey is an optional PEM-encoded public key to use for a custom Rekor. - If set, this will be used to validate transparency log signatures from a custom Rekor. - type: string - url: - description: URL is the - address of the transparency - log. Defaults to the public - Rekor log instance https://rekor.sigstore.dev. - type: string - type: object - secret: - description: Reference to a - Secret resource that contains - a public key - properties: - name: - description: Name of the - secret. The provided secret - must contain a key named - cosign.pub. - type: string - namespace: - description: Namespace name - where the Secret exists. - type: string - required: - - name - - namespace - type: object - signatureAlgorithm: - default: sha256 - description: Deprecated. Use - attestor.signatureAlgorithm - instead. - type: string - type: object - repository: - description: |- - Repository is an optional alternate OCI repository to use for signatures and attestations that match this rule. - If specified Repository will override other OCI image repository locations for this Attestor. - type: string - signatureAlgorithm: - default: sha256 - description: Specify signature algorithm - for public keys. Supported values - are sha224, sha256, sha384 and - sha512. - type: string - type: object - type: array - type: object - type: array - conditions: - description: |- - Conditions are used to verify attributes within a Predicate. If no Conditions are specified - the attestation check is satisfied as long there are predicates that match the predicate type. - items: - description: |- - AnyAllConditions consists of conditions wrapped denoting a logical criteria to be fulfilled. - AnyConditions get fulfilled when at least one of its sub-conditions passes. - AllConditions get fulfilled only when all of its sub-conditions pass. - properties: - all: - description: |- - AllConditions enable variable-based conditional rule execution. This is useful for - finer control of when an rule is applied. A condition can reference object data - using JMESPath notation. - Here, all of the conditions need to pass - items: - description: Condition defines variable-based - conditional criteria for rule execution. - properties: - key: - description: Key is the context - entry (using JMESPath) for conditional - rule evaluation. - x-kubernetes-preserve-unknown-fields: true - message: - description: Message is an optional - display message - type: string - operator: - description: |- - Operator is the conditional operation to perform. Valid operators are: - Equals, NotEquals, In, AnyIn, AllIn, NotIn, AnyNotIn, AllNotIn, GreaterThanOrEquals, - GreaterThan, LessThanOrEquals, LessThan, DurationGreaterThanOrEquals, DurationGreaterThan, - DurationLessThanOrEquals, DurationLessThan - enum: - - Equals - - NotEquals - - In - - AnyIn - - AllIn - - NotIn - - AnyNotIn - - AllNotIn - - GreaterThanOrEquals - - GreaterThan - - LessThanOrEquals - - LessThan - - DurationGreaterThanOrEquals - - DurationGreaterThan - - DurationLessThanOrEquals - - DurationLessThan - type: string - value: - description: |- - Value is the conditional value, or set of values. The values can be fixed set - or can be variables declared using JMESPath. - x-kubernetes-preserve-unknown-fields: true - type: object - type: array - any: - description: |- - AnyConditions enable variable-based conditional rule execution. This is useful for - finer control of when an rule is applied. A condition can reference object data - using JMESPath notation. - Here, at least one of the conditions need to pass - items: - description: Condition defines variable-based - conditional criteria for rule execution. - properties: - key: - description: Key is the context - entry (using JMESPath) for conditional - rule evaluation. - x-kubernetes-preserve-unknown-fields: true - message: - description: Message is an optional - display message - type: string - operator: - description: |- - Operator is the conditional operation to perform. Valid operators are: - Equals, NotEquals, In, AnyIn, AllIn, NotIn, AnyNotIn, AllNotIn, GreaterThanOrEquals, - GreaterThan, LessThanOrEquals, LessThan, DurationGreaterThanOrEquals, DurationGreaterThan, - DurationLessThanOrEquals, DurationLessThan - enum: - - Equals - - NotEquals - - In - - AnyIn - - AllIn - - NotIn - - AnyNotIn - - AllNotIn - - GreaterThanOrEquals - - GreaterThan - - LessThanOrEquals - - LessThan - - DurationGreaterThanOrEquals - - DurationGreaterThan - - DurationLessThanOrEquals - - DurationLessThan - type: string - value: - description: |- - Value is the conditional value, or set of values. The values can be fixed set - or can be variables declared using JMESPath. - x-kubernetes-preserve-unknown-fields: true - type: object - type: array - type: object - type: array - name: - description: Name is the variable name. - type: string - predicateType: - description: Deprecated in favour of 'Type', - to be removed soon - type: string - type: - description: Type defines the type of attestation - contained within the Statement. - type: string - type: object - type: array - attestors: - description: Attestors specified the required attestors - (i.e. authorities) - items: - properties: - count: - description: |- - Count specifies the required number of entries that must match. If the count is null, all entries must match - (a logical AND). If the count is 1, at least one entry must match (a logical OR). If the count contains a - value N, then N must be less than or equal to the size of entries, and at least N entries must match. - minimum: 1 - type: integer - entries: - description: |- - Entries contains the available attestors. An attestor can be a static key, - attributes for keyless verification, or a nested attestor declaration. - items: - properties: - annotations: - additionalProperties: - type: string - description: |- - Annotations are used for image verification. - Every specified key-value pair must exist and match in the verified payload. - The payload may contain other key-value pairs. - type: object - attestor: - description: Attestor is a nested set - of Attestor used to specify a more complex - set of match authorities. - x-kubernetes-preserve-unknown-fields: true - certificates: - description: Certificates specifies one - or more certificates. - properties: - cert: - description: Cert is an optional PEM-encoded - public certificate. - type: string - certChain: - description: CertChain is an optional - PEM encoded set of certificates - used to verify. - type: string - ctlog: - description: |- - CTLog (certificate timestamp log) provides a configuration for validation of Signed Certificate - Timestamps (SCTs). If the value is unset, the default behavior by Cosign is used. - properties: - ignoreSCT: - description: |- - IgnoreSCT defines whether to use the Signed Certificate Timestamp (SCT) log to check for a certificate - timestamp. Default is false. Set to true if this was opted out during signing. - type: boolean - pubkey: - description: PubKey, if set, is - used to validate SCTs against - a custom source. - type: string - tsaCertChain: - description: |- - TSACertChain, if set, is the PEM-encoded certificate chain file for the RFC3161 timestamp authority. Must - contain the root CA certificate. Optionally may contain intermediate CA certificates, and - may contain the leaf TSA certificate if not present in the timestamurce. - type: string - type: object - rekor: - description: |- - Rekor provides configuration for the Rekor transparency log service. If an empty object - is provided the public instance of Rekor (https://rekor.sigstore.dev) is used. - properties: - ignoreTlog: - description: IgnoreTlog skips - transparency log verification. - type: boolean - pubkey: - description: |- - RekorPubKey is an optional PEM-encoded public key to use for a custom Rekor. - If set, this will be used to validate transparency log signatures from a custom Rekor. - type: string - url: - description: URL is the address - of the transparency log. Defaults - to the public Rekor log instance - https://rekor.sigstore.dev. - type: string - type: object - type: object - keyless: - description: |- - Keyless is a set of attribute used to verify a Sigstore keyless attestor. - See https://github.com/sigstore/cosign/blob/main/KEYLESS.md. - properties: - additionalExtensions: - additionalProperties: - type: string - description: AdditionalExtensions - are certificate-extensions used - for keyless signing. - type: object - ctlog: - description: |- - CTLog (certificate timestamp log) provides a configuration for validation of Signed Certificate - Timestamps (SCTs). If the value is unset, the default behavior by Cosign is used. - properties: - ignoreSCT: - description: |- - IgnoreSCT defines whether to use the Signed Certificate Timestamp (SCT) log to check for a certificate - timestamp. Default is false. Set to true if this was opted out during signing. - type: boolean - pubkey: - description: PubKey, if set, is - used to validate SCTs against - a custom source. - type: string - tsaCertChain: - description: |- - TSACertChain, if set, is the PEM-encoded certificate chain file for the RFC3161 timestamp authority. Must - contain the root CA certificate. Optionally may contain intermediate CA certificates, and - may contain the leaf TSA certificate if not present in the timestamurce. - type: string - type: object - issuer: - description: Issuer is the certificate - issuer used for keyless signing. - type: string - issuerRegExp: - description: IssuerRegExp is the regular - expression to match certificate - issuer used for keyless signing. - type: string - rekor: - description: |- - Rekor provides configuration for the Rekor transparency log service. If an empty object - is provided the public instance of Rekor (https://rekor.sigstore.dev) is used. - properties: - ignoreTlog: - description: IgnoreTlog skips - transparency log verification. - type: boolean - pubkey: - description: |- - RekorPubKey is an optional PEM-encoded public key to use for a custom Rekor. - If set, this will be used to validate transparency log signatures from a custom Rekor. - type: string - url: - description: URL is the address - of the transparency log. Defaults - to the public Rekor log instance - https://rekor.sigstore.dev. - type: string - type: object - roots: - description: |- - Roots is an optional set of PEM encoded trusted root certificates. - If not provided, the system roots are used. - type: string - subject: - description: Subject is the verified - identity used for keyless signing, - for example the email address. - type: string - subjectRegExp: - description: SubjectRegExp is the - regular expression to match identity - used for keyless signing, for example - the email address. - type: string - type: object - keys: - description: Keys specifies one or more - public keys. - properties: - ctlog: - description: |- - CTLog (certificate timestamp log) provides a configuration for validation of Signed Certificate - Timestamps (SCTs). If the value is unset, the default behavior by Cosign is used. - properties: - ignoreSCT: - description: |- - IgnoreSCT defines whether to use the Signed Certificate Timestamp (SCT) log to check for a certificate - timestamp. Default is false. Set to true if this was opted out during signing. - type: boolean - pubkey: - description: PubKey, if set, is - used to validate SCTs against - a custom source. - type: string - tsaCertChain: - description: |- - TSACertChain, if set, is the PEM-encoded certificate chain file for the RFC3161 timestamp authority. Must - contain the root CA certificate. Optionally may contain intermediate CA certificates, and - may contain the leaf TSA certificate if not present in the timestamurce. - type: string - type: object - kms: - description: |- - KMS provides the URI to the public key stored in a Key Management System. See: - https://github.com/sigstore/cosign/blob/main/KMS.md - type: string - publicKeys: - description: |- - Keys is a set of X.509 public keys used to verify image signatures. The keys can be directly - specified or can be a variable reference to a key specified in a ConfigMap (see - https://kyverno.io/docs/writing-policies/variables/), or reference a standard Kubernetes Secret - elsewhere in the cluster by specifying it in the format "k8s:///". - The named Secret must specify a key `cosign.pub` containing the public key used for - verification, (see https://github.com/sigstore/cosign/blob/main/KMS.md#kubernetes-secret). - When multiple keys are specified each key is processed as a separate staticKey entry - (.attestors[*].entries.keys) within the set of attestors and the count is applied across the keys. - type: string - rekor: - description: |- - Rekor provides configuration for the Rekor transparency log service. If an empty object - is provided the public instance of Rekor (https://rekor.sigstore.dev) is used. - properties: - ignoreTlog: - description: IgnoreTlog skips - transparency log verification. - type: boolean - pubkey: - description: |- - RekorPubKey is an optional PEM-encoded public key to use for a custom Rekor. - If set, this will be used to validate transparency log signatures from a custom Rekor. - type: string - url: - description: URL is the address - of the transparency log. Defaults - to the public Rekor log instance - https://rekor.sigstore.dev. - type: string - type: object - secret: - description: Reference to a Secret - resource that contains a public - key - properties: - name: - description: Name of the secret. - The provided secret must contain - a key named cosign.pub. - type: string - namespace: - description: Namespace name where - the Secret exists. - type: string - required: - - name - - namespace - type: object - signatureAlgorithm: - default: sha256 - description: Deprecated. Use attestor.signatureAlgorithm - instead. - type: string - type: object - repository: - description: |- - Repository is an optional alternate OCI repository to use for signatures and attestations that match this rule. - If specified Repository will override other OCI image repository locations for this Attestor. - type: string - signatureAlgorithm: - default: sha256 - description: Specify signature algorithm - for public keys. Supported values are - sha224, sha256, sha384 and sha512. - type: string - type: object - type: array - type: object - type: array - cosignOCI11: - description: |- - CosignOCI11 enables the experimental OCI 1.1 behaviour in cosign image verification. - Defaults to false. - type: boolean - failureAction: - description: Allowed values are Audit or Enforce. - enum: - - Audit - - Enforce - type: string - image: - description: Deprecated. Use ImageReferences instead. - type: string - imageReferences: - description: |- - ImageReferences is a list of matching image reference patterns. At least one pattern in the - list must match the image for the rule to apply. Each image reference consists of a registry - address (defaults to docker.io), repository, image, and tag (defaults to latest). - Wildcards ('*' and '?') are allowed. See: https://kubernetes.io/docs/concepts/containers/images. - items: - type: string - type: array - imageRegistryCredentials: - description: ImageRegistryCredentials provides credentials - that will be used for authentication with registry. - properties: - allowInsecureRegistry: - description: AllowInsecureRegistry allows insecure - access to a registry. - type: boolean - providers: - description: |- - Providers specifies a list of OCI Registry names, whose authentication providers are provided. - It can be of one of these values: default,google,azure,amazon,github. - items: - description: ImageRegistryCredentialsProvidersType - provides the list of credential providers - required. - enum: - - default - - amazon - - azure - - google - - github - type: string - type: array - secrets: - description: |- - Secrets specifies a list of secrets that are provided for credentials. - Secrets must live in the Kyverno namespace. - items: - type: string - type: array - type: object - issuer: - description: Deprecated. Use KeylessAttestor instead. - type: string - key: - description: Deprecated. Use StaticKeyAttestor instead. - type: string - mutateDigest: - default: true - description: |- - MutateDigest enables replacement of image tags with digests. - Defaults to true. - type: boolean - repository: - description: |- - Repository is an optional alternate OCI repository to use for image signatures and attestations that match this rule. - If specified Repository will override the default OCI image repository configured for the installation. - The repository can also be overridden per Attestor or Attestation. - type: string - required: - default: true - description: Required validates that images are verified - i.e. have matched passed a signature or attestation - check. - type: boolean - roots: - description: Deprecated. Use KeylessAttestor instead. - type: string - skipImageReferences: - description: |- - SkipImageReferences is a list of matching image reference patterns that should be skipped. - At least one pattern in the list must match the image for the rule to be skipped. Each image reference - consists of a registry address (defaults to docker.io), repository, image, and tag (defaults to latest). - Wildcards ('*' and '?') are allowed. See: https://kubernetes.io/docs/concepts/containers/images. - items: - type: string - type: array - subject: - description: Deprecated. Use KeylessAttestor instead. - type: string - type: - description: |- - Type specifies the method of signature validation. The allowed options - are Cosign, Sigstore Bundle and Notary. By default Cosign is used if a type is not specified. - enum: - - Cosign - - SigstoreBundle - - Notary - type: string - useCache: - default: true - description: UseCache enables caching of image verify - responses for this rule. - type: boolean - validate: - description: |- - Validation checks conditions across multiple image - verification attestations or context entries - properties: - deny: - description: Deny defines conditions used to pass - or fail a validation rule. - properties: - conditions: - description: |- - Multiple conditions can be declared under an `any` or `all` statement. A direct list - of conditions (without `any` or `all` statements) is also supported for backwards compatibility - but will be deprecated in the next major release. - See: https://kyverno.io/docs/writing-policies/validate/#deny-rules - x-kubernetes-preserve-unknown-fields: true - type: object - message: - description: Message specifies a custom message - to be displayed on failure. - type: string - type: object - verifyDigest: - default: true - description: VerifyDigest validates that images have - a digest. - type: boolean - type: object - type: array - required: - - match - - name - type: object - type: array - type: object - conditions: - items: - description: Condition contains details for one aspect of the current - state of this API Resource. - properties: - lastTransitionTime: - description: |- - lastTransitionTime is the last time the condition transitioned from one status to another. - This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable. - format: date-time - type: string - message: - description: |- - message is a human readable message indicating details about the transition. - This may be an empty string. - maxLength: 32768 - type: string - observedGeneration: - description: |- - observedGeneration represents the .metadata.generation that the condition was set based upon. - For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date - with respect to the current state of the instance. - format: int64 - minimum: 0 - type: integer - reason: - description: |- - reason contains a programmatic identifier indicating the reason for the condition's last transition. - Producers of specific condition types may define expected values and meanings for this field, - and whether the values are considered a guaranteed API. - The value should be a CamelCase string. - This field may not be empty. - maxLength: 1024 - minLength: 1 - pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ - type: string - status: - description: status of the condition, one of True, False, Unknown. - enum: - - "True" - - "False" - - Unknown - type: string - type: - description: type of condition in CamelCase or in foo.example.com/CamelCase. - maxLength: 316 - pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ - type: string - required: - - lastTransitionTime - - message - - reason - - status - - type - type: object - type: array - ready: - description: Deprecated in favor of Conditions - type: boolean - rulecount: - description: |- - RuleCountStatus contains four variables which describes counts for - validate, generate, mutate and verify images rules - properties: - generate: - description: Count for generate rules in policy - type: integer - mutate: - description: Count for mutate rules in policy - type: integer - validate: - description: Count for validate rules in policy - type: integer - verifyimages: - description: Count for verify image rules in policy - type: integer - required: - - generate - - mutate - - validate - - verifyimages - type: object - validatingadmissionpolicy: - description: ValidatingAdmissionPolicy contains status information - properties: - generated: - description: Generated indicates whether a validating admission - policy is generated from the policy or not - type: boolean - message: - description: |- - Message is a human readable message indicating details about the generation of validating admission policy - It is an empty string when validating admission policy is successfully generated. - type: string - required: - - generated - - message - type: object - type: object - required: - - spec - type: object - served: true - storage: true - subresources: - status: {} - - additionalPrinterColumns: - - jsonPath: .spec.admission - name: ADMISSION - type: boolean - - jsonPath: .spec.background - name: BACKGROUND - type: boolean - - jsonPath: .status.conditions[?(@.type == "Ready")].status - name: READY - type: string - - jsonPath: .metadata.creationTimestamp - name: AGE - type: date - - jsonPath: .spec.failurePolicy - name: FAILURE POLICY - priority: 1 - type: string - - jsonPath: .status.rulecount.validate - name: VALIDATE - priority: 1 - type: integer - - jsonPath: .status.rulecount.mutate - name: MUTATE - priority: 1 - type: integer - - jsonPath: .status.rulecount.generate - name: GENERATE - priority: 1 - type: integer - - jsonPath: .status.rulecount.verifyimages - name: VERIFY IMAGES - priority: 1 - type: integer - - jsonPath: .status.conditions[?(@.type == "Ready")].message - name: MESSAGE - type: string - name: v2beta1 - schema: - openAPIV3Schema: - description: ClusterPolicy declares validation, mutation, and generation behaviors - for matching resources. - properties: - apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - type: string - kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - metadata: - type: object - spec: - description: Spec declares policy behaviors. - properties: - admission: - default: true - description: |- - Admission controls if rules are applied during admission. - Optional. Default value is "true". - type: boolean - applyRules: - description: |- - ApplyRules controls how rules in a policy are applied. Rule are processed in - the order of declaration. When set to `One` processing stops after a rule has - been applied i.e. the rule matches and results in a pass, fail, or error. When - set to `All` all rules in the policy are processed. The default is `All`. - enum: - - All - - One - type: string - background: - default: true - description: |- - Background controls if rules are applied to existing resources during a background scan. - Optional. Default value is "true". The value must be set to "false" if the policy rule - uses variables that are only available in the admission review request (e.g. user name). - type: boolean - emitWarning: - default: false - description: |- - EmitWarning enables API response warnings for mutate policy rules or validate policy rules with validationFailureAction set to Audit. - Enabling this option will extend admission request processing times. The default value is "false". - type: boolean - failurePolicy: - description: Deprecated, use failurePolicy under the webhookConfiguration - instead. - enum: - - Ignore - - Fail - type: string - generateExisting: - description: Deprecated, use generateExisting under the generate rule - instead - type: boolean - generateExistingOnPolicyUpdate: - description: Deprecated, use generateExisting instead - type: boolean - mutateExistingOnPolicyUpdate: - description: Deprecated, use mutateExistingOnPolicyUpdate under the - mutate rule instead - type: boolean - rules: - description: |- - Rules is a list of Rule instances. A Policy contains multiple rules and - each rule can validate, mutate, or generate resources. - items: - description: |- - Rule defines a validation, mutation, or generation control for matching resources. - Each rules contains a match declaration to select resources, and an optional exclude - declaration to specify which resources to exclude. - properties: - celPreconditions: - description: |- - CELPreconditions are used to determine if a policy rule should be applied by evaluating a - set of CEL conditions. It can only be used with the validate.cel subrule - items: - description: MatchCondition represents a condition which must - by fulfilled for a request to be sent to a webhook. - properties: - expression: - description: |- - Expression represents the expression which will be evaluated by CEL. Must evaluate to bool. - CEL expressions have access to the contents of the AdmissionRequest and Authorizer, organized into CEL variables: - - 'object' - The object from the incoming request. The value is null for DELETE requests. - 'oldObject' - The existing object. The value is null for CREATE requests. - 'request' - Attributes of the admission request(/pkg/apis/admission/types.go#AdmissionRequest). - 'authorizer' - A CEL Authorizer. May be used to perform authorization checks for the principal (user or service account) of the request. - See https://pkg.go.dev/k8s.io/apiserver/pkg/cel/library#Authz - 'authorizer.requestResource' - A CEL ResourceCheck constructed from the 'authorizer' and configured with the - request resource. - Documentation on CEL: https://kubernetes.io/docs/reference/using-api/cel/ - - Required. - type: string - name: - description: |- - Name is an identifier for this match condition, used for strategic merging of MatchConditions, - as well as providing an identifier for logging purposes. A good name should be descriptive of - the associated expression. - Name must be a qualified name consisting of alphanumeric characters, '-', '_' or '.', and - must start and end with an alphanumeric character (e.g. 'MyName', or 'my.name', or - '123-abc', regex used for validation is '([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9]') with an - optional DNS subdomain prefix and '/' (e.g. 'example.com/MyName') - - Required. - type: string - required: - - expression - - name - type: object - type: array - context: - description: Context defines variables and data sources that - can be used during rule execution. - items: - description: |- - ContextEntry adds variables and data sources to a rule Context. Either a - ConfigMap reference or a APILookup must be provided. - oneOf: - - required: - - configMap - - required: - - apiCall - - required: - - imageRegistry - - required: - - variable - - required: - - globalReference - properties: - apiCall: - description: |- - APICall is an HTTP request to the Kubernetes API server, or other JSON web service. - The data returned is stored in the context with the name for the context entry. - properties: - data: - description: |- - The data object specifies the POST data sent to the server. - Only applicable when the method field is set to POST. - items: - description: RequestData contains the HTTP POST - data - properties: - key: - description: Key is a unique identifier for - the data value - type: string - value: - description: Value is the data value - x-kubernetes-preserve-unknown-fields: true - required: - - key - - value - type: object - type: array - default: - description: |- - Default is an optional arbitrary JSON object that the context - value is set to, if the apiCall returns error. - x-kubernetes-preserve-unknown-fields: true - jmesPath: - description: |- - JMESPath is an optional JSON Match Expression that can be used to - transform the JSON response returned from the server. For example - a JMESPath of "items | length(@)" applied to the API server response - for the URLPath "/apis/apps/v1/deployments" will return the total count - of deployments across all namespaces. - type: string - method: - default: GET - description: Method is the HTTP request type (GET - or POST). Defaults to GET. - enum: - - GET - - POST - type: string - service: - description: |- - Service is an API call to a JSON web service. - This is used for non-Kubernetes API server calls. - It's mutually exclusive with the URLPath field. - properties: - caBundle: - description: |- - CABundle is a PEM encoded CA bundle which will be used to validate - the server certificate. - type: string - headers: - description: Headers is a list of optional HTTP - headers to be included in the request. - items: - properties: - key: - description: Key is the header key - type: string - value: - description: Value is the header value - type: string - required: - - key - - value - type: object - type: array - url: - description: |- - URL is the JSON web service URL. A typical form is - `https://{service}.{namespace}:{port}/{path}`. - type: string - required: - - url - type: object - urlPath: - description: |- - URLPath is the URL path to be used in the HTTP GET or POST request to the - Kubernetes API server (e.g. "/api/v1/namespaces" or "/apis/apps/v1/deployments"). - The format required is the same format used by the `kubectl get --raw` command. - See https://kyverno.io/docs/writing-policies/external-data-sources/#variables-from-kubernetes-api-server-calls - for details. - It's mutually exclusive with the Service field. - type: string - type: object - configMap: - description: ConfigMap is the ConfigMap reference. - properties: - name: - description: Name is the ConfigMap name. - type: string - namespace: - description: Namespace is the ConfigMap namespace. - type: string - required: - - name - type: object - globalReference: - description: GlobalContextEntryReference is a reference - to a cached global context entry. - properties: - jmesPath: - description: |- - JMESPath is an optional JSON Match Expression that can be used to - transform the JSON response returned from the server. For example - a JMESPath of "items | length(@)" applied to the API server response - for the URLPath "/apis/apps/v1/deployments" will return the total count - of deployments across all namespaces. - type: string - name: - description: Name of the global context entry - type: string - required: - - name - type: object - imageRegistry: - description: |- - ImageRegistry defines requests to an OCI/Docker V2 registry to fetch image - details. - properties: - imageRegistryCredentials: - description: ImageRegistryCredentials provides credentials - that will be used for authentication with registry - properties: - allowInsecureRegistry: - description: AllowInsecureRegistry allows insecure - access to a registry. - type: boolean - providers: - description: |- - Providers specifies a list of OCI Registry names, whose authentication providers are provided. - It can be of one of these values: default,google,azure,amazon,github. - items: - description: ImageRegistryCredentialsProvidersType - provides the list of credential providers - required. - enum: - - default - - amazon - - azure - - google - - github - type: string - type: array - secrets: - description: |- - Secrets specifies a list of secrets that are provided for credentials. - Secrets must live in the Kyverno namespace. - items: - type: string - type: array - type: object - jmesPath: - description: |- - JMESPath is an optional JSON Match Expression that can be used to - transform the ImageData struct returned as a result of processing - the image reference. - type: string - reference: - description: |- - Reference is image reference to a container image in the registry. - Example: ghcr.io/kyverno/kyverno:latest - type: string - required: - - reference - type: object - name: - description: Name is the variable name. - type: string - variable: - description: Variable defines an arbitrary JMESPath context - variable that can be defined inline. - properties: - default: - description: |- - Default is an optional arbitrary JSON object that the variable may take if the JMESPath - expression evaluates to nil - x-kubernetes-preserve-unknown-fields: true - jmesPath: - description: |- - JMESPath is an optional JMESPath Expression that can be used to - transform the variable. - type: string - value: - description: Value is any arbitrary JSON object representable - in YAML or JSON form. - x-kubernetes-preserve-unknown-fields: true - type: object - required: - - name - type: object - type: array - exclude: - description: |- - ExcludeResources defines when this policy rule should not be applied. The exclude - criteria can include resource information (e.g. kind, name, namespace, labels) - and admission review request information like the name or role. - not: - required: - - any - - all - properties: - all: - description: All allows specifying resources which will - be ANDed - items: - description: ResourceFilter allow users to "AND" or "OR" - between resources - properties: - clusterRoles: - description: ClusterRoles is the list of cluster-wide - role names for the user. - items: - type: string - type: array - resources: - description: ResourceDescription contains information - about the resource being created or modified. - not: - required: - - name - - names - properties: - annotations: - additionalProperties: - type: string - description: |- - Annotations is a map of annotations (key-value pairs of type string). Annotation keys - and values support the wildcard characters "*" (matches zero or many characters) and - "?" (matches at least one character). - type: object - kinds: - description: Kinds is a list of resource kinds. - items: - type: string - type: array - name: - description: |- - Name is the name of the resource. The name supports wildcard characters - "*" (matches zero or many characters) and "?" (at least one character). - NOTE: "Name" is being deprecated in favor of "Names". - type: string - names: - description: |- - Names are the names of the resources. Each name supports wildcard characters - "*" (matches zero or many characters) and "?" (at least one character). - items: - type: string - type: array - namespaceSelector: - description: |- - NamespaceSelector is a label selector for the resource namespace. Label keys and values - in `matchLabels` support the wildcard characters `*` (matches zero or many characters) - and `?` (matches one character).Wildcards allows writing label selectors like - ["storage.k8s.io/*": "*"]. Note that using ["*" : "*"] matches any key and value but - does not match an empty label set. - properties: - matchExpressions: - description: matchExpressions is a list of - label selector requirements. The requirements - are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key that - the selector applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - namespaces: - description: |- - Namespaces is a list of namespaces names. Each name supports wildcard characters - "*" (matches zero or many characters) and "?" (at least one character). - items: - type: string - type: array - operations: - description: Operations can contain values ["CREATE, - "UPDATE", "CONNECT", "DELETE"], which are used - to match a specific action. - items: - description: AdmissionOperation can have one - of the values CREATE, UPDATE, CONNECT, DELETE, - which are used to match a specific action. - enum: - - CREATE - - CONNECT - - UPDATE - - DELETE - type: string - type: array - selector: - description: |- - Selector is a label selector. Label keys and values in `matchLabels` support the wildcard - characters `*` (matches zero or many characters) and `?` (matches one character). - Wildcards allows writing label selectors like ["storage.k8s.io/*": "*"]. Note that - using ["*" : "*"] matches any key and value but does not match an empty label set. - properties: - matchExpressions: - description: matchExpressions is a list of - label selector requirements. The requirements - are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key that - the selector applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - type: object - roles: - description: Roles is the list of namespaced role - names for the user. - items: - type: string - type: array - subjects: - description: Subjects is the list of subject names - like users, user groups, and service accounts. - items: - description: |- - Subject contains a reference to the object or user identities a role binding applies to. This can either hold a direct API object reference, - or a value for non-objects such as user and group names. - properties: - apiGroup: - description: |- - APIGroup holds the API group of the referenced subject. - Defaults to "" for ServiceAccount subjects. - Defaults to "rbac.authorization.k8s.io" for User and Group subjects. - type: string - kind: - description: |- - Kind of object being referenced. Values defined by this API group are "User", "Group", and "ServiceAccount". - If the Authorizer does not recognized the kind value, the Authorizer should report an error. - type: string - name: - description: Name of the object being referenced. - type: string - namespace: - description: |- - Namespace of the referenced object. If the object kind is non-namespace, such as "User" or "Group", and this value is not empty - the Authorizer should report an error. - type: string - required: - - kind - - name - type: object - x-kubernetes-map-type: atomic - type: array - type: object - type: array - any: - description: Any allows specifying resources which will - be ORed - items: - description: ResourceFilter allow users to "AND" or "OR" - between resources - properties: - clusterRoles: - description: ClusterRoles is the list of cluster-wide - role names for the user. - items: - type: string - type: array - resources: - description: ResourceDescription contains information - about the resource being created or modified. - not: - required: - - name - - names - properties: - annotations: - additionalProperties: - type: string - description: |- - Annotations is a map of annotations (key-value pairs of type string). Annotation keys - and values support the wildcard characters "*" (matches zero or many characters) and - "?" (matches at least one character). - type: object - kinds: - description: Kinds is a list of resource kinds. - items: - type: string - type: array - name: - description: |- - Name is the name of the resource. The name supports wildcard characters - "*" (matches zero or many characters) and "?" (at least one character). - NOTE: "Name" is being deprecated in favor of "Names". - type: string - names: - description: |- - Names are the names of the resources. Each name supports wildcard characters - "*" (matches zero or many characters) and "?" (at least one character). - items: - type: string - type: array - namespaceSelector: - description: |- - NamespaceSelector is a label selector for the resource namespace. Label keys and values - in `matchLabels` support the wildcard characters `*` (matches zero or many characters) - and `?` (matches one character).Wildcards allows writing label selectors like - ["storage.k8s.io/*": "*"]. Note that using ["*" : "*"] matches any key and value but - does not match an empty label set. - properties: - matchExpressions: - description: matchExpressions is a list of - label selector requirements. The requirements - are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key that - the selector applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - namespaces: - description: |- - Namespaces is a list of namespaces names. Each name supports wildcard characters - "*" (matches zero or many characters) and "?" (at least one character). - items: - type: string - type: array - operations: - description: Operations can contain values ["CREATE, - "UPDATE", "CONNECT", "DELETE"], which are used - to match a specific action. - items: - description: AdmissionOperation can have one - of the values CREATE, UPDATE, CONNECT, DELETE, - which are used to match a specific action. - enum: - - CREATE - - CONNECT - - UPDATE - - DELETE - type: string - type: array - selector: - description: |- - Selector is a label selector. Label keys and values in `matchLabels` support the wildcard - characters `*` (matches zero or many characters) and `?` (matches one character). - Wildcards allows writing label selectors like ["storage.k8s.io/*": "*"]. Note that - using ["*" : "*"] matches any key and value but does not match an empty label set. - properties: - matchExpressions: - description: matchExpressions is a list of - label selector requirements. The requirements - are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key that - the selector applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - type: object - roles: - description: Roles is the list of namespaced role - names for the user. - items: - type: string - type: array - subjects: - description: Subjects is the list of subject names - like users, user groups, and service accounts. - items: - description: |- - Subject contains a reference to the object or user identities a role binding applies to. This can either hold a direct API object reference, - or a value for non-objects such as user and group names. - properties: - apiGroup: - description: |- - APIGroup holds the API group of the referenced subject. - Defaults to "" for ServiceAccount subjects. - Defaults to "rbac.authorization.k8s.io" for User and Group subjects. - type: string - kind: - description: |- - Kind of object being referenced. Values defined by this API group are "User", "Group", and "ServiceAccount". - If the Authorizer does not recognized the kind value, the Authorizer should report an error. - type: string - name: - description: Name of the object being referenced. - type: string - namespace: - description: |- - Namespace of the referenced object. If the object kind is non-namespace, such as "User" or "Group", and this value is not empty - the Authorizer should report an error. - type: string - required: - - kind - - name - type: object - x-kubernetes-map-type: atomic - type: array - type: object - type: array - type: object - generate: - description: Generation is used to create new resources. - properties: - apiVersion: - description: APIVersion specifies resource apiVersion. - type: string - clone: - description: |- - Clone specifies the source resource used to populate each generated resource. - At most one of Data or Clone can be specified. If neither are provided, the generated - resource will be created with default data only. - properties: - name: - description: Name specifies name of the resource. - type: string - namespace: - description: Namespace specifies source resource namespace. - type: string - type: object - cloneList: - description: CloneList specifies the list of source resource - used to populate each generated resource. - properties: - kinds: - description: Kinds is a list of resource kinds. - items: - type: string - type: array - namespace: - description: Namespace specifies source resource namespace. - type: string - selector: - description: |- - Selector is a label selector. Label keys and values in `matchLabels`. - wildcard characters are not supported. - properties: - matchExpressions: - description: matchExpressions is a list of label - selector requirements. The requirements are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key that the - selector applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - type: object - data: - description: |- - Data provides the resource declaration used to populate each generated resource. - At most one of Data or Clone must be specified. If neither are provided, the generated - resource will be created with default data only. - x-kubernetes-preserve-unknown-fields: true - foreach: - description: ForEach applies generate rules to a list of - sub-elements by creating a context for each entry in the - list and looping over it to apply the specified logic. - items: - properties: - apiVersion: - description: APIVersion specifies resource apiVersion. - type: string - clone: - description: |- - Clone specifies the source resource used to populate each generated resource. - At most one of Data or Clone can be specified. If neither are provided, the generated - resource will be created with default data only. - properties: - name: - description: Name specifies name of the resource. - type: string - namespace: - description: Namespace specifies source resource - namespace. - type: string - type: object - cloneList: - description: CloneList specifies the list of source - resource used to populate each generated resource. - properties: - kinds: - description: Kinds is a list of resource kinds. - items: - type: string - type: array - namespace: - description: Namespace specifies source resource - namespace. - type: string - selector: - description: |- - Selector is a label selector. Label keys and values in `matchLabels`. - wildcard characters are not supported. - properties: - matchExpressions: - description: matchExpressions is a list of - label selector requirements. The requirements - are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key that - the selector applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - type: object - context: - description: Context defines variables and data sources - that can be used during rule execution. - items: - description: |- - ContextEntry adds variables and data sources to a rule Context. Either a - ConfigMap reference or a APILookup must be provided. - oneOf: - - required: - - configMap - - required: - - apiCall - - required: - - imageRegistry - - required: - - variable - - required: - - globalReference - properties: - apiCall: - description: |- - APICall is an HTTP request to the Kubernetes API server, or other JSON web service. - The data returned is stored in the context with the name for the context entry. - properties: - data: - description: |- - The data object specifies the POST data sent to the server. - Only applicable when the method field is set to POST. - items: - description: RequestData contains the - HTTP POST data - properties: - key: - description: Key is a unique identifier - for the data value - type: string - value: - description: Value is the data value - x-kubernetes-preserve-unknown-fields: true - required: - - key - - value - type: object - type: array - default: - description: |- - Default is an optional arbitrary JSON object that the context - value is set to, if the apiCall returns error. - x-kubernetes-preserve-unknown-fields: true - jmesPath: - description: |- - JMESPath is an optional JSON Match Expression that can be used to - transform the JSON response returned from the server. For example - a JMESPath of "items | length(@)" applied to the API server response - for the URLPath "/apis/apps/v1/deployments" will return the total count - of deployments across all namespaces. - type: string - method: - default: GET - description: Method is the HTTP request - type (GET or POST). Defaults to GET. - enum: - - GET - - POST - type: string - service: - description: |- - Service is an API call to a JSON web service. - This is used for non-Kubernetes API server calls. - It's mutually exclusive with the URLPath field. - properties: - caBundle: - description: |- - CABundle is a PEM encoded CA bundle which will be used to validate - the server certificate. - type: string - headers: - description: Headers is a list of optional - HTTP headers to be included in the - request. - items: - properties: - key: - description: Key is the header - key - type: string - value: - description: Value is the header - value - type: string - required: - - key - - value - type: object - type: array - url: - description: |- - URL is the JSON web service URL. A typical form is - `https://{service}.{namespace}:{port}/{path}`. - type: string - required: - - url - type: object - urlPath: - description: |- - URLPath is the URL path to be used in the HTTP GET or POST request to the - Kubernetes API server (e.g. "/api/v1/namespaces" or "/apis/apps/v1/deployments"). - The format required is the same format used by the `kubectl get --raw` command. - See https://kyverno.io/docs/writing-policies/external-data-sources/#variables-from-kubernetes-api-server-calls - for details. - It's mutually exclusive with the Service field. - type: string - type: object - configMap: - description: ConfigMap is the ConfigMap reference. - properties: - name: - description: Name is the ConfigMap name. - type: string - namespace: - description: Namespace is the ConfigMap - namespace. - type: string - required: - - name - type: object - globalReference: - description: GlobalContextEntryReference is - a reference to a cached global context entry. - properties: - jmesPath: - description: |- - JMESPath is an optional JSON Match Expression that can be used to - transform the JSON response returned from the server. For example - a JMESPath of "items | length(@)" applied to the API server response - for the URLPath "/apis/apps/v1/deployments" will return the total count - of deployments across all namespaces. - type: string - name: - description: Name of the global context - entry - type: string - required: - - name - type: object - imageRegistry: - description: |- - ImageRegistry defines requests to an OCI/Docker V2 registry to fetch image - details. - properties: - imageRegistryCredentials: - description: ImageRegistryCredentials provides - credentials that will be used for authentication - with registry - properties: - allowInsecureRegistry: - description: AllowInsecureRegistry allows - insecure access to a registry. - type: boolean - providers: - description: |- - Providers specifies a list of OCI Registry names, whose authentication providers are provided. - It can be of one of these values: default,google,azure,amazon,github. - items: - description: ImageRegistryCredentialsProvidersType - provides the list of credential - providers required. - enum: - - default - - amazon - - azure - - google - - github - type: string - type: array - secrets: - description: |- - Secrets specifies a list of secrets that are provided for credentials. - Secrets must live in the Kyverno namespace. - items: - type: string - type: array - type: object - jmesPath: - description: |- - JMESPath is an optional JSON Match Expression that can be used to - transform the ImageData struct returned as a result of processing - the image reference. - type: string - reference: - description: |- - Reference is image reference to a container image in the registry. - Example: ghcr.io/kyverno/kyverno:latest - type: string - required: - - reference - type: object - name: - description: Name is the variable name. - type: string - variable: - description: Variable defines an arbitrary JMESPath - context variable that can be defined inline. - properties: - default: - description: |- - Default is an optional arbitrary JSON object that the variable may take if the JMESPath - expression evaluates to nil - x-kubernetes-preserve-unknown-fields: true - jmesPath: - description: |- - JMESPath is an optional JMESPath Expression that can be used to - transform the variable. - type: string - value: - description: Value is any arbitrary JSON - object representable in YAML or JSON form. - x-kubernetes-preserve-unknown-fields: true - type: object - required: - - name - type: object - type: array - data: - description: |- - Data provides the resource declaration used to populate each generated resource. - At most one of Data or Clone must be specified. If neither are provided, the generated - resource will be created with default data only. - x-kubernetes-preserve-unknown-fields: true - kind: - description: Kind specifies resource kind. - type: string - list: - description: |- - List specifies a JMESPath expression that results in one or more elements - to which the validation logic is applied. - type: string - name: - description: Name specifies the resource name. - type: string - namespace: - description: Namespace specifies resource namespace. - type: string - preconditions: - description: |- - AnyAllConditions are used to determine if a policy rule should be applied by evaluating a - set of conditions. The declaration can contain nested `any` or `all` statements. - See: https://kyverno.io/docs/writing-policies/preconditions/ - properties: - all: - description: |- - AllConditions enable variable-based conditional rule execution. This is useful for - finer control of when an rule is applied. A condition can reference object data - using JMESPath notation. - Here, all of the conditions need to pass - items: - description: Condition defines variable-based - conditional criteria for rule execution. - properties: - key: - description: Key is the context entry (using - JMESPath) for conditional rule evaluation. - x-kubernetes-preserve-unknown-fields: true - message: - description: Message is an optional display - message - type: string - operator: - description: |- - Operator is the conditional operation to perform. Valid operators are: - Equals, NotEquals, In, AnyIn, AllIn, NotIn, AnyNotIn, AllNotIn, GreaterThanOrEquals, - GreaterThan, LessThanOrEquals, LessThan, DurationGreaterThanOrEquals, DurationGreaterThan, - DurationLessThanOrEquals, DurationLessThan - enum: - - Equals - - NotEquals - - In - - AnyIn - - AllIn - - NotIn - - AnyNotIn - - AllNotIn - - GreaterThanOrEquals - - GreaterThan - - LessThanOrEquals - - LessThan - - DurationGreaterThanOrEquals - - DurationGreaterThan - - DurationLessThanOrEquals - - DurationLessThan - type: string - value: - description: |- - Value is the conditional value, or set of values. The values can be fixed set - or can be variables declared using JMESPath. - x-kubernetes-preserve-unknown-fields: true - type: object - type: array - any: - description: |- - AnyConditions enable variable-based conditional rule execution. This is useful for - finer control of when an rule is applied. A condition can reference object data - using JMESPath notation. - Here, at least one of the conditions need to pass - items: - description: Condition defines variable-based - conditional criteria for rule execution. - properties: - key: - description: Key is the context entry (using - JMESPath) for conditional rule evaluation. - x-kubernetes-preserve-unknown-fields: true - message: - description: Message is an optional display - message - type: string - operator: - description: |- - Operator is the conditional operation to perform. Valid operators are: - Equals, NotEquals, In, AnyIn, AllIn, NotIn, AnyNotIn, AllNotIn, GreaterThanOrEquals, - GreaterThan, LessThanOrEquals, LessThan, DurationGreaterThanOrEquals, DurationGreaterThan, - DurationLessThanOrEquals, DurationLessThan - enum: - - Equals - - NotEquals - - In - - AnyIn - - AllIn - - NotIn - - AnyNotIn - - AllNotIn - - GreaterThanOrEquals - - GreaterThan - - LessThanOrEquals - - LessThan - - DurationGreaterThanOrEquals - - DurationGreaterThan - - DurationLessThanOrEquals - - DurationLessThan - type: string - value: - description: |- - Value is the conditional value, or set of values. The values can be fixed set - or can be variables declared using JMESPath. - x-kubernetes-preserve-unknown-fields: true - type: object - type: array - type: object - x-kubernetes-preserve-unknown-fields: true - uid: - description: UID specifies the resource uid. - type: string - type: object - type: array - generateExisting: - description: |- - GenerateExisting controls whether to trigger the rule in existing resources - If is set to "true" the rule will be triggered and applied to existing matched resources. - type: boolean - kind: - description: Kind specifies resource kind. - type: string - name: - description: Name specifies the resource name. - type: string - namespace: - description: Namespace specifies resource namespace. - type: string - orphanDownstreamOnPolicyDelete: - description: |- - OrphanDownstreamOnPolicyDelete controls whether generated resources should be deleted when the rule that generated - them is deleted with synchronization enabled. This option is only applicable to generate rules of the data type. - See https://kyverno.io/docs/writing-policies/generate/#data-examples. - Defaults to "false" if not specified. - type: boolean - synchronize: - description: |- - Synchronize controls if generated resources should be kept in-sync with their source resource. - If Synchronize is set to "true" changes to generated resources will be overwritten with resource - data from Data or the resource specified in the Clone declaration. - Optional. Defaults to "false" if not specified. - type: boolean - uid: - description: UID specifies the resource uid. - type: string - type: object - imageExtractors: - additionalProperties: - items: - properties: - jmesPath: - description: |- - JMESPath is an optional JMESPath expression to apply to the image value. - This is useful when the extracted image begins with a prefix like 'docker://'. - The 'trim_prefix' function may be used to trim the prefix: trim_prefix(@, 'docker://'). - Note - Image digest mutation may not be used when applying a JMESPAth to an image. - type: string - key: - description: |- - Key is an optional name of the field within 'path' that will be used to uniquely identify an image. - Note - this field MUST be unique. - type: string - name: - description: |- - Name is the entry the image will be available under 'images.' in the context. - If this field is not defined, image entries will appear under 'images.custom'. - type: string - path: - description: |- - Path is the path to the object containing the image field in a custom resource. - It should be slash-separated. Each slash-separated key must be a valid YAML key or a wildcard '*'. - Wildcard keys are expanded in case of arrays or objects. - type: string - value: - description: |- - Value is an optional name of the field within 'path' that points to the image URI. - This is useful when a custom 'key' is also defined. - type: string - required: - - path - type: object - type: array - description: |- - ImageExtractors defines a mapping from kinds to ImageExtractorConfigs. - This config is only valid for verifyImages rules. - type: object - match: - description: |- - MatchResources defines when this policy rule should be applied. The match - criteria can include resource information (e.g. kind, name, namespace, labels) - and admission review request information like the user name or role. - At least one kind is required. - not: - required: - - any - - all - properties: - all: - description: All allows specifying resources which will - be ANDed - items: - description: ResourceFilter allow users to "AND" or "OR" - between resources - properties: - clusterRoles: - description: ClusterRoles is the list of cluster-wide - role names for the user. - items: - type: string - type: array - resources: - description: ResourceDescription contains information - about the resource being created or modified. - not: - required: - - name - - names - properties: - annotations: - additionalProperties: - type: string - description: |- - Annotations is a map of annotations (key-value pairs of type string). Annotation keys - and values support the wildcard characters "*" (matches zero or many characters) and - "?" (matches at least one character). - type: object - kinds: - description: Kinds is a list of resource kinds. - items: - type: string - type: array - name: - description: |- - Name is the name of the resource. The name supports wildcard characters - "*" (matches zero or many characters) and "?" (at least one character). - NOTE: "Name" is being deprecated in favor of "Names". - type: string - names: - description: |- - Names are the names of the resources. Each name supports wildcard characters - "*" (matches zero or many characters) and "?" (at least one character). - items: - type: string - type: array - namespaceSelector: - description: |- - NamespaceSelector is a label selector for the resource namespace. Label keys and values - in `matchLabels` support the wildcard characters `*` (matches zero or many characters) - and `?` (matches one character).Wildcards allows writing label selectors like - ["storage.k8s.io/*": "*"]. Note that using ["*" : "*"] matches any key and value but - does not match an empty label set. - properties: - matchExpressions: - description: matchExpressions is a list of - label selector requirements. The requirements - are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key that - the selector applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - namespaces: - description: |- - Namespaces is a list of namespaces names. Each name supports wildcard characters - "*" (matches zero or many characters) and "?" (at least one character). - items: - type: string - type: array - operations: - description: Operations can contain values ["CREATE, - "UPDATE", "CONNECT", "DELETE"], which are used - to match a specific action. - items: - description: AdmissionOperation can have one - of the values CREATE, UPDATE, CONNECT, DELETE, - which are used to match a specific action. - enum: - - CREATE - - CONNECT - - UPDATE - - DELETE - type: string - type: array - selector: - description: |- - Selector is a label selector. Label keys and values in `matchLabels` support the wildcard - characters `*` (matches zero or many characters) and `?` (matches one character). - Wildcards allows writing label selectors like ["storage.k8s.io/*": "*"]. Note that - using ["*" : "*"] matches any key and value but does not match an empty label set. - properties: - matchExpressions: - description: matchExpressions is a list of - label selector requirements. The requirements - are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key that - the selector applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - type: object - roles: - description: Roles is the list of namespaced role - names for the user. - items: - type: string - type: array - subjects: - description: Subjects is the list of subject names - like users, user groups, and service accounts. - items: - description: |- - Subject contains a reference to the object or user identities a role binding applies to. This can either hold a direct API object reference, - or a value for non-objects such as user and group names. - properties: - apiGroup: - description: |- - APIGroup holds the API group of the referenced subject. - Defaults to "" for ServiceAccount subjects. - Defaults to "rbac.authorization.k8s.io" for User and Group subjects. - type: string - kind: - description: |- - Kind of object being referenced. Values defined by this API group are "User", "Group", and "ServiceAccount". - If the Authorizer does not recognized the kind value, the Authorizer should report an error. - type: string - name: - description: Name of the object being referenced. - type: string - namespace: - description: |- - Namespace of the referenced object. If the object kind is non-namespace, such as "User" or "Group", and this value is not empty - the Authorizer should report an error. - type: string - required: - - kind - - name - type: object - x-kubernetes-map-type: atomic - type: array - type: object - type: array - any: - description: Any allows specifying resources which will - be ORed - items: - description: ResourceFilter allow users to "AND" or "OR" - between resources - properties: - clusterRoles: - description: ClusterRoles is the list of cluster-wide - role names for the user. - items: - type: string - type: array - resources: - description: ResourceDescription contains information - about the resource being created or modified. - not: - required: - - name - - names - properties: - annotations: - additionalProperties: - type: string - description: |- - Annotations is a map of annotations (key-value pairs of type string). Annotation keys - and values support the wildcard characters "*" (matches zero or many characters) and - "?" (matches at least one character). - type: object - kinds: - description: Kinds is a list of resource kinds. - items: - type: string - type: array - name: - description: |- - Name is the name of the resource. The name supports wildcard characters - "*" (matches zero or many characters) and "?" (at least one character). - NOTE: "Name" is being deprecated in favor of "Names". - type: string - names: - description: |- - Names are the names of the resources. Each name supports wildcard characters - "*" (matches zero or many characters) and "?" (at least one character). - items: - type: string - type: array - namespaceSelector: - description: |- - NamespaceSelector is a label selector for the resource namespace. Label keys and values - in `matchLabels` support the wildcard characters `*` (matches zero or many characters) - and `?` (matches one character).Wildcards allows writing label selectors like - ["storage.k8s.io/*": "*"]. Note that using ["*" : "*"] matches any key and value but - does not match an empty label set. - properties: - matchExpressions: - description: matchExpressions is a list of - label selector requirements. The requirements - are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key that - the selector applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - namespaces: - description: |- - Namespaces is a list of namespaces names. Each name supports wildcard characters - "*" (matches zero or many characters) and "?" (at least one character). - items: - type: string - type: array - operations: - description: Operations can contain values ["CREATE, - "UPDATE", "CONNECT", "DELETE"], which are used - to match a specific action. - items: - description: AdmissionOperation can have one - of the values CREATE, UPDATE, CONNECT, DELETE, - which are used to match a specific action. - enum: - - CREATE - - CONNECT - - UPDATE - - DELETE - type: string - type: array - selector: - description: |- - Selector is a label selector. Label keys and values in `matchLabels` support the wildcard - characters `*` (matches zero or many characters) and `?` (matches one character). - Wildcards allows writing label selectors like ["storage.k8s.io/*": "*"]. Note that - using ["*" : "*"] matches any key and value but does not match an empty label set. - properties: - matchExpressions: - description: matchExpressions is a list of - label selector requirements. The requirements - are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key that - the selector applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - type: object - roles: - description: Roles is the list of namespaced role - names for the user. - items: - type: string - type: array - subjects: - description: Subjects is the list of subject names - like users, user groups, and service accounts. - items: - description: |- - Subject contains a reference to the object or user identities a role binding applies to. This can either hold a direct API object reference, - or a value for non-objects such as user and group names. - properties: - apiGroup: - description: |- - APIGroup holds the API group of the referenced subject. - Defaults to "" for ServiceAccount subjects. - Defaults to "rbac.authorization.k8s.io" for User and Group subjects. - type: string - kind: - description: |- - Kind of object being referenced. Values defined by this API group are "User", "Group", and "ServiceAccount". - If the Authorizer does not recognized the kind value, the Authorizer should report an error. - type: string - name: - description: Name of the object being referenced. - type: string - namespace: - description: |- - Namespace of the referenced object. If the object kind is non-namespace, such as "User" or "Group", and this value is not empty - the Authorizer should report an error. - type: string - required: - - kind - - name - type: object - x-kubernetes-map-type: atomic - type: array - type: object - type: array - type: object - mutate: - description: Mutation is used to modify matching resources. - properties: - foreach: - description: ForEach applies mutation rules to a list of - sub-elements by creating a context for each entry in the - list and looping over it to apply the specified logic. - items: - description: ForEachMutation applies mutation rules to - a list of sub-elements by creating a context for each - entry in the list and looping over it to apply the specified - logic. - properties: - context: - description: Context defines variables and data sources - that can be used during rule execution. - items: - description: |- - ContextEntry adds variables and data sources to a rule Context. Either a - ConfigMap reference or a APILookup must be provided. - oneOf: - - required: - - configMap - - required: - - apiCall - - required: - - imageRegistry - - required: - - variable - - required: - - globalReference - properties: - apiCall: - description: |- - APICall is an HTTP request to the Kubernetes API server, or other JSON web service. - The data returned is stored in the context with the name for the context entry. - properties: - data: - description: |- - The data object specifies the POST data sent to the server. - Only applicable when the method field is set to POST. - items: - description: RequestData contains the - HTTP POST data - properties: - key: - description: Key is a unique identifier - for the data value - type: string - value: - description: Value is the data value - x-kubernetes-preserve-unknown-fields: true - required: - - key - - value - type: object - type: array - default: - description: |- - Default is an optional arbitrary JSON object that the context - value is set to, if the apiCall returns error. - x-kubernetes-preserve-unknown-fields: true - jmesPath: - description: |- - JMESPath is an optional JSON Match Expression that can be used to - transform the JSON response returned from the server. For example - a JMESPath of "items | length(@)" applied to the API server response - for the URLPath "/apis/apps/v1/deployments" will return the total count - of deployments across all namespaces. - type: string - method: - default: GET - description: Method is the HTTP request - type (GET or POST). Defaults to GET. - enum: - - GET - - POST - type: string - service: - description: |- - Service is an API call to a JSON web service. - This is used for non-Kubernetes API server calls. - It's mutually exclusive with the URLPath field. - properties: - caBundle: - description: |- - CABundle is a PEM encoded CA bundle which will be used to validate - the server certificate. - type: string - headers: - description: Headers is a list of optional - HTTP headers to be included in the - request. - items: - properties: - key: - description: Key is the header - key - type: string - value: - description: Value is the header - value - type: string - required: - - key - - value - type: object - type: array - url: - description: |- - URL is the JSON web service URL. A typical form is - `https://{service}.{namespace}:{port}/{path}`. - type: string - required: - - url - type: object - urlPath: - description: |- - URLPath is the URL path to be used in the HTTP GET or POST request to the - Kubernetes API server (e.g. "/api/v1/namespaces" or "/apis/apps/v1/deployments"). - The format required is the same format used by the `kubectl get --raw` command. - See https://kyverno.io/docs/writing-policies/external-data-sources/#variables-from-kubernetes-api-server-calls - for details. - It's mutually exclusive with the Service field. - type: string - type: object - configMap: - description: ConfigMap is the ConfigMap reference. - properties: - name: - description: Name is the ConfigMap name. - type: string - namespace: - description: Namespace is the ConfigMap - namespace. - type: string - required: - - name - type: object - globalReference: - description: GlobalContextEntryReference is - a reference to a cached global context entry. - properties: - jmesPath: - description: |- - JMESPath is an optional JSON Match Expression that can be used to - transform the JSON response returned from the server. For example - a JMESPath of "items | length(@)" applied to the API server response - for the URLPath "/apis/apps/v1/deployments" will return the total count - of deployments across all namespaces. - type: string - name: - description: Name of the global context - entry - type: string - required: - - name - type: object - imageRegistry: - description: |- - ImageRegistry defines requests to an OCI/Docker V2 registry to fetch image - details. - properties: - imageRegistryCredentials: - description: ImageRegistryCredentials provides - credentials that will be used for authentication - with registry - properties: - allowInsecureRegistry: - description: AllowInsecureRegistry allows - insecure access to a registry. - type: boolean - providers: - description: |- - Providers specifies a list of OCI Registry names, whose authentication providers are provided. - It can be of one of these values: default,google,azure,amazon,github. - items: - description: ImageRegistryCredentialsProvidersType - provides the list of credential - providers required. - enum: - - default - - amazon - - azure - - google - - github - type: string - type: array - secrets: - description: |- - Secrets specifies a list of secrets that are provided for credentials. - Secrets must live in the Kyverno namespace. - items: - type: string - type: array - type: object - jmesPath: - description: |- - JMESPath is an optional JSON Match Expression that can be used to - transform the ImageData struct returned as a result of processing - the image reference. - type: string - reference: - description: |- - Reference is image reference to a container image in the registry. - Example: ghcr.io/kyverno/kyverno:latest - type: string - required: - - reference - type: object - name: - description: Name is the variable name. - type: string - variable: - description: Variable defines an arbitrary JMESPath - context variable that can be defined inline. - properties: - default: - description: |- - Default is an optional arbitrary JSON object that the variable may take if the JMESPath - expression evaluates to nil - x-kubernetes-preserve-unknown-fields: true - jmesPath: - description: |- - JMESPath is an optional JMESPath Expression that can be used to - transform the variable. - type: string - value: - description: Value is any arbitrary JSON - object representable in YAML or JSON form. - x-kubernetes-preserve-unknown-fields: true - type: object - required: - - name - type: object - type: array - foreach: - description: Foreach declares a nested foreach iterator - x-kubernetes-preserve-unknown-fields: true - list: - description: |- - List specifies a JMESPath expression that results in one or more elements - to which the validation logic is applied. - type: string - order: - description: |- - Order defines the iteration order on the list. - Can be Ascending to iterate from first to last element or Descending to iterate in from last to first element. - enum: - - Ascending - - Descending - type: string - patchStrategicMerge: - description: |- - PatchStrategicMerge is a strategic merge patch used to modify resources. - See https://kubernetes.io/docs/tasks/manage-kubernetes-objects/update-api-object-kubectl-patch/ - and https://kubectl.docs.kubernetes.io/references/kustomize/kustomization/patchesstrategicmerge/. - x-kubernetes-preserve-unknown-fields: true - patchesJson6902: - description: |- - PatchesJSON6902 is a list of RFC 6902 JSON Patch declarations used to modify resources. - See https://tools.ietf.org/html/rfc6902 and https://kubectl.docs.kubernetes.io/references/kustomize/kustomization/patchesjson6902/. - type: string - preconditions: - description: |- - AnyAllConditions are used to determine if a policy rule should be applied by evaluating a - set of conditions. The declaration can contain nested `any` or `all` statements. - See: https://kyverno.io/docs/writing-policies/preconditions/ - properties: - all: - description: |- - AllConditions enable variable-based conditional rule execution. This is useful for - finer control of when an rule is applied. A condition can reference object data - using JMESPath notation. - Here, all of the conditions need to pass - items: - description: Condition defines variable-based - conditional criteria for rule execution. - properties: - key: - description: Key is the context entry (using - JMESPath) for conditional rule evaluation. - x-kubernetes-preserve-unknown-fields: true - message: - description: Message is an optional display - message - type: string - operator: - description: |- - Operator is the conditional operation to perform. Valid operators are: - Equals, NotEquals, In, AnyIn, AllIn, NotIn, AnyNotIn, AllNotIn, GreaterThanOrEquals, - GreaterThan, LessThanOrEquals, LessThan, DurationGreaterThanOrEquals, DurationGreaterThan, - DurationLessThanOrEquals, DurationLessThan - enum: - - Equals - - NotEquals - - In - - AnyIn - - AllIn - - NotIn - - AnyNotIn - - AllNotIn - - GreaterThanOrEquals - - GreaterThan - - LessThanOrEquals - - LessThan - - DurationGreaterThanOrEquals - - DurationGreaterThan - - DurationLessThanOrEquals - - DurationLessThan - type: string - value: - description: |- - Value is the conditional value, or set of values. The values can be fixed set - or can be variables declared using JMESPath. - x-kubernetes-preserve-unknown-fields: true - type: object - type: array - any: - description: |- - AnyConditions enable variable-based conditional rule execution. This is useful for - finer control of when an rule is applied. A condition can reference object data - using JMESPath notation. - Here, at least one of the conditions need to pass - items: - description: Condition defines variable-based - conditional criteria for rule execution. - properties: - key: - description: Key is the context entry (using - JMESPath) for conditional rule evaluation. - x-kubernetes-preserve-unknown-fields: true - message: - description: Message is an optional display - message - type: string - operator: - description: |- - Operator is the conditional operation to perform. Valid operators are: - Equals, NotEquals, In, AnyIn, AllIn, NotIn, AnyNotIn, AllNotIn, GreaterThanOrEquals, - GreaterThan, LessThanOrEquals, LessThan, DurationGreaterThanOrEquals, DurationGreaterThan, - DurationLessThanOrEquals, DurationLessThan - enum: - - Equals - - NotEquals - - In - - AnyIn - - AllIn - - NotIn - - AnyNotIn - - AllNotIn - - GreaterThanOrEquals - - GreaterThan - - LessThanOrEquals - - LessThan - - DurationGreaterThanOrEquals - - DurationGreaterThan - - DurationLessThanOrEquals - - DurationLessThan - type: string - value: - description: |- - Value is the conditional value, or set of values. The values can be fixed set - or can be variables declared using JMESPath. - x-kubernetes-preserve-unknown-fields: true - type: object - type: array - type: object - x-kubernetes-preserve-unknown-fields: true - type: object - type: array - mutateExistingOnPolicyUpdate: - description: MutateExistingOnPolicyUpdate controls if the - mutateExisting rule will be applied on policy events. - type: boolean - patchStrategicMerge: - description: |- - PatchStrategicMerge is a strategic merge patch used to modify resources. - See https://kubernetes.io/docs/tasks/manage-kubernetes-objects/update-api-object-kubectl-patch/ - and https://kubectl.docs.kubernetes.io/references/kustomize/kustomization/patchesstrategicmerge/. - x-kubernetes-preserve-unknown-fields: true - patchesJson6902: - description: |- - PatchesJSON6902 is a list of RFC 6902 JSON Patch declarations used to modify resources. - See https://tools.ietf.org/html/rfc6902 and https://kubectl.docs.kubernetes.io/references/kustomize/kustomization/patchesjson6902/. - type: string - targets: - description: Targets defines the target resources to be - mutated. - items: - description: TargetResourceSpec defines targets for mutating - existing resources. - properties: - apiVersion: - description: APIVersion specifies resource apiVersion. - type: string - context: - description: Context defines variables and data sources - that can be used during rule execution. - items: - description: |- - ContextEntry adds variables and data sources to a rule Context. Either a - ConfigMap reference or a APILookup must be provided. - oneOf: - - required: - - configMap - - required: - - apiCall - - required: - - imageRegistry - - required: - - variable - - required: - - globalReference - properties: - apiCall: - description: |- - APICall is an HTTP request to the Kubernetes API server, or other JSON web service. - The data returned is stored in the context with the name for the context entry. - properties: - data: - description: |- - The data object specifies the POST data sent to the server. - Only applicable when the method field is set to POST. - items: - description: RequestData contains the - HTTP POST data - properties: - key: - description: Key is a unique identifier - for the data value - type: string - value: - description: Value is the data value - x-kubernetes-preserve-unknown-fields: true - required: - - key - - value - type: object - type: array - default: - description: |- - Default is an optional arbitrary JSON object that the context - value is set to, if the apiCall returns error. - x-kubernetes-preserve-unknown-fields: true - jmesPath: - description: |- - JMESPath is an optional JSON Match Expression that can be used to - transform the JSON response returned from the server. For example - a JMESPath of "items | length(@)" applied to the API server response - for the URLPath "/apis/apps/v1/deployments" will return the total count - of deployments across all namespaces. - type: string - method: - default: GET - description: Method is the HTTP request - type (GET or POST). Defaults to GET. - enum: - - GET - - POST - type: string - service: - description: |- - Service is an API call to a JSON web service. - This is used for non-Kubernetes API server calls. - It's mutually exclusive with the URLPath field. - properties: - caBundle: - description: |- - CABundle is a PEM encoded CA bundle which will be used to validate - the server certificate. - type: string - headers: - description: Headers is a list of optional - HTTP headers to be included in the - request. - items: - properties: - key: - description: Key is the header - key - type: string - value: - description: Value is the header - value - type: string - required: - - key - - value - type: object - type: array - url: - description: |- - URL is the JSON web service URL. A typical form is - `https://{service}.{namespace}:{port}/{path}`. - type: string - required: - - url - type: object - urlPath: - description: |- - URLPath is the URL path to be used in the HTTP GET or POST request to the - Kubernetes API server (e.g. "/api/v1/namespaces" or "/apis/apps/v1/deployments"). - The format required is the same format used by the `kubectl get --raw` command. - See https://kyverno.io/docs/writing-policies/external-data-sources/#variables-from-kubernetes-api-server-calls - for details. - It's mutually exclusive with the Service field. - type: string - type: object - configMap: - description: ConfigMap is the ConfigMap reference. - properties: - name: - description: Name is the ConfigMap name. - type: string - namespace: - description: Namespace is the ConfigMap - namespace. - type: string - required: - - name - type: object - globalReference: - description: GlobalContextEntryReference is - a reference to a cached global context entry. - properties: - jmesPath: - description: |- - JMESPath is an optional JSON Match Expression that can be used to - transform the JSON response returned from the server. For example - a JMESPath of "items | length(@)" applied to the API server response - for the URLPath "/apis/apps/v1/deployments" will return the total count - of deployments across all namespaces. - type: string - name: - description: Name of the global context - entry - type: string - required: - - name - type: object - imageRegistry: - description: |- - ImageRegistry defines requests to an OCI/Docker V2 registry to fetch image - details. - properties: - imageRegistryCredentials: - description: ImageRegistryCredentials provides - credentials that will be used for authentication - with registry - properties: - allowInsecureRegistry: - description: AllowInsecureRegistry allows - insecure access to a registry. - type: boolean - providers: - description: |- - Providers specifies a list of OCI Registry names, whose authentication providers are provided. - It can be of one of these values: default,google,azure,amazon,github. - items: - description: ImageRegistryCredentialsProvidersType - provides the list of credential - providers required. - enum: - - default - - amazon - - azure - - google - - github - type: string - type: array - secrets: - description: |- - Secrets specifies a list of secrets that are provided for credentials. - Secrets must live in the Kyverno namespace. - items: - type: string - type: array - type: object - jmesPath: - description: |- - JMESPath is an optional JSON Match Expression that can be used to - transform the ImageData struct returned as a result of processing - the image reference. - type: string - reference: - description: |- - Reference is image reference to a container image in the registry. - Example: ghcr.io/kyverno/kyverno:latest - type: string - required: - - reference - type: object - name: - description: Name is the variable name. - type: string - variable: - description: Variable defines an arbitrary JMESPath - context variable that can be defined inline. - properties: - default: - description: |- - Default is an optional arbitrary JSON object that the variable may take if the JMESPath - expression evaluates to nil - x-kubernetes-preserve-unknown-fields: true - jmesPath: - description: |- - JMESPath is an optional JMESPath Expression that can be used to - transform the variable. - type: string - value: - description: Value is any arbitrary JSON - object representable in YAML or JSON form. - x-kubernetes-preserve-unknown-fields: true - type: object - required: - - name - type: object - type: array - kind: - description: Kind specifies resource kind. - type: string - name: - description: Name specifies the resource name. - type: string - namespace: - description: Namespace specifies resource namespace. - type: string - preconditions: - description: |- - Preconditions are used to determine if a policy rule should be applied by evaluating a - set of conditions. The declaration can contain nested `any` or `all` statements. A direct list - of conditions (without `any` or `all` statements is supported for backwards compatibility but - will be deprecated in the next major release. - See: https://kyverno.io/docs/writing-policies/preconditions/ - x-kubernetes-preserve-unknown-fields: true - selector: - description: Selector allows you to select target - resources with their labels. - properties: - matchExpressions: - description: matchExpressions is a list of label - selector requirements. The requirements are - ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key that the - selector applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - uid: - description: UID specifies the resource uid. - type: string - type: object - type: array - type: object - name: - description: Name is a label to identify the rule, It must be - unique within the policy. - maxLength: 63 - type: string - preconditions: - description: |- - Preconditions are used to determine if a policy rule should be applied by evaluating a - set of conditions. The declaration can contain nested `any` or `all` statements. - See: https://kyverno.io/docs/writing-policies/preconditions/ - properties: - all: - description: |- - AllConditions enable variable-based conditional rule execution. This is useful for - finer control of when an rule is applied. A condition can reference object data - using JMESPath notation. - Here, all of the conditions need to pass. - items: - properties: - key: - description: Key is the context entry (using JMESPath) - for conditional rule evaluation. - x-kubernetes-preserve-unknown-fields: true - message: - description: Message is an optional display message - type: string - operator: - description: |- - Operator is the conditional operation to perform. Valid operators are: - Equals, NotEquals, In, AnyIn, AllIn, NotIn, AnyNotIn, AllNotIn, GreaterThanOrEquals, - GreaterThan, LessThanOrEquals, LessThan, DurationGreaterThanOrEquals, DurationGreaterThan, - DurationLessThanOrEquals, DurationLessThan - enum: - - Equals - - NotEquals - - AnyIn - - AllIn - - AnyNotIn - - AllNotIn - - GreaterThanOrEquals - - GreaterThan - - LessThanOrEquals - - LessThan - - DurationGreaterThanOrEquals - - DurationGreaterThan - - DurationLessThanOrEquals - - DurationLessThan - type: string - value: - description: |- - Value is the conditional value, or set of values. The values can be fixed set - or can be variables declared using JMESPath. - x-kubernetes-preserve-unknown-fields: true - type: object - type: array - any: - description: |- - AnyConditions enable variable-based conditional rule execution. This is useful for - finer control of when an rule is applied. A condition can reference object data - using JMESPath notation. - Here, at least one of the conditions need to pass. - items: - properties: - key: - description: Key is the context entry (using JMESPath) - for conditional rule evaluation. - x-kubernetes-preserve-unknown-fields: true - message: - description: Message is an optional display message - type: string - operator: - description: |- - Operator is the conditional operation to perform. Valid operators are: - Equals, NotEquals, In, AnyIn, AllIn, NotIn, AnyNotIn, AllNotIn, GreaterThanOrEquals, - GreaterThan, LessThanOrEquals, LessThan, DurationGreaterThanOrEquals, DurationGreaterThan, - DurationLessThanOrEquals, DurationLessThan - enum: - - Equals - - NotEquals - - AnyIn - - AllIn - - AnyNotIn - - AllNotIn - - GreaterThanOrEquals - - GreaterThan - - LessThanOrEquals - - LessThan - - DurationGreaterThanOrEquals - - DurationGreaterThan - - DurationLessThanOrEquals - - DurationLessThan - type: string - value: - description: |- - Value is the conditional value, or set of values. The values can be fixed set - or can be variables declared using JMESPath. - x-kubernetes-preserve-unknown-fields: true - type: object - type: array - type: object - skipBackgroundRequests: - default: true - description: |- - SkipBackgroundRequests bypasses admission requests that are sent by the background controller. - The default value is set to "true", it must be set to "false" to apply - generate and mutateExisting rules to those requests. - type: boolean - validate: - description: Validation is used to validate matching resources. - properties: - anyPattern: - description: |- - AnyPattern specifies list of validation patterns. At least one of the patterns - must be satisfied for the validation rule to succeed. - x-kubernetes-preserve-unknown-fields: true - assert: - description: Assert defines a kyverno-json assertion tree. - type: object - x-kubernetes-preserve-unknown-fields: true - cel: - description: CEL allows validation checks using the Common - Expression Language (https://kubernetes.io/docs/reference/using-api/cel/). - properties: - auditAnnotations: - description: AuditAnnotations contains CEL expressions - which are used to produce audit annotations for the - audit event of the API request. - items: - description: AuditAnnotation describes how to produce - an audit annotation for an API request. - properties: - key: - description: |- - key specifies the audit annotation key. The audit annotation keys of - a ValidatingAdmissionPolicy must be unique. The key must be a qualified - name ([A-Za-z0-9][-A-Za-z0-9_.]*) no more than 63 bytes in length. - - The key is combined with the resource name of the - ValidatingAdmissionPolicy to construct an audit annotation key: - "{ValidatingAdmissionPolicy name}/{key}". - - If an admission webhook uses the same resource name as this ValidatingAdmissionPolicy - and the same audit annotation key, the annotation key will be identical. - In this case, the first annotation written with the key will be included - in the audit event and all subsequent annotations with the same key - will be discarded. - - Required. - type: string - valueExpression: - description: |- - valueExpression represents the expression which is evaluated by CEL to - produce an audit annotation value. The expression must evaluate to either - a string or null value. If the expression evaluates to a string, the - audit annotation is included with the string value. If the expression - evaluates to null or empty string the audit annotation will be omitted. - The valueExpression may be no longer than 5kb in length. - If the result of the valueExpression is more than 10kb in length, it - will be truncated to 10kb. - - If multiple ValidatingAdmissionPolicyBinding resources match an - API request, then the valueExpression will be evaluated for - each binding. All unique values produced by the valueExpressions - will be joined together in a comma-separated list. - - Required. - type: string - required: - - key - - valueExpression - type: object - type: array - expressions: - description: Expressions is a list of CELExpression - types. - items: - description: Validation specifies the CEL expression - which is used to apply the validation. - properties: - expression: - description: "Expression represents the expression - which will be evaluated by CEL.\nref: https://github.com/google/cel-spec\nCEL - expressions have access to the contents of the - API request/response, organized into CEL variables - as well as some other useful variables:\n\n- - 'object' - The object from the incoming request. - The value is null for DELETE requests.\n- 'oldObject' - - The existing object. The value is null for - CREATE requests.\n- 'request' - Attributes of - the API request([ref](/pkg/apis/admission/types.go#AdmissionRequest)).\n- - 'params' - Parameter resource referred to by - the policy binding being evaluated. Only populated - if the policy has a ParamKind.\n- 'namespaceObject' - - The namespace object that the incoming object - belongs to. The value is null for cluster-scoped - resources.\n- 'variables' - Map of composited - variables, from its name to its lazily evaluated - value.\n For example, a variable named 'foo' - can be accessed as 'variables.foo'.\n- 'authorizer' - - A CEL Authorizer. May be used to perform authorization - checks for the principal (user or service account) - of the request.\n See https://pkg.go.dev/k8s.io/apiserver/pkg/cel/library#Authz\n- - 'authorizer.requestResource' - A CEL ResourceCheck - constructed from the 'authorizer' and configured - with the\n request resource.\n\nThe `apiVersion`, - `kind`, `metadata.name` and `metadata.generateName` - are always accessible from the root of the\nobject. - No other metadata properties are accessible.\n\nOnly - property names of the form `[a-zA-Z_.-/][a-zA-Z0-9_.-/]*` - are accessible.\nAccessible property names are - escaped according to the following rules when - accessed in the expression:\n- '__' escapes - to '__underscores__'\n- '.' escapes to '__dot__'\n- - '-' escapes to '__dash__'\n- '/' escapes to - '__slash__'\n- Property names that exactly match - a CEL RESERVED keyword escape to '__{keyword}__'. - The keywords are:\n\t \"true\", \"false\", - \"null\", \"in\", \"as\", \"break\", \"const\", - \"continue\", \"else\", \"for\", \"function\", - \"if\",\n\t \"import\", \"let\", \"loop\", - \"package\", \"namespace\", \"return\".\nExamples:\n - \ - Expression accessing a property named \"namespace\": - {\"Expression\": \"object.__namespace__ > 0\"}\n - \ - Expression accessing a property named \"x-prop\": - {\"Expression\": \"object.x__dash__prop > 0\"}\n - \ - Expression accessing a property named \"redact__d\": - {\"Expression\": \"object.redact__underscores__d - > 0\"}\n\nEquality on arrays with list type - of 'set' or 'map' ignores element order, i.e. - [1, 2] == [2, 1].\nConcatenation on arrays with - x-kubernetes-list-type use the semantics of - the list type:\n - 'set': `X + Y` performs - a union where the array positions of all elements - in `X` are preserved and\n non-intersecting - elements in `Y` are appended, retaining their - partial order.\n - 'map': `X + Y` performs - a merge where the array positions of all keys - in `X` are preserved but the values\n are - overwritten by values in `Y` when the key sets - of `X` and `Y` intersect. Elements in `Y` with\n - \ non-intersecting keys are appended, retaining - their partial order.\nRequired." - type: string - message: - description: |- - Message represents the message displayed when validation fails. The message is required if the Expression contains - line breaks. The message must not contain line breaks. - If unset, the message is "failed rule: {Rule}". - e.g. "must be a URL with the host matching spec.host" - If the Expression contains line breaks. Message is required. - The message must not contain line breaks. - If unset, the message is "failed Expression: {Expression}". - type: string - messageExpression: - description: |- - messageExpression declares a CEL expression that evaluates to the validation failure message that is returned when this rule fails. - Since messageExpression is used as a failure message, it must evaluate to a string. - If both message and messageExpression are present on a validation, then messageExpression will be used if validation fails. - If messageExpression results in a runtime error, the runtime error is logged, and the validation failure message is produced - as if the messageExpression field were unset. If messageExpression evaluates to an empty string, a string with only spaces, or a string - that contains line breaks, then the validation failure message will also be produced as if the messageExpression field were unset, and - the fact that messageExpression produced an empty string/string with only spaces/string with line breaks will be logged. - messageExpression has access to all the same variables as the `expression` except for 'authorizer' and 'authorizer.requestResource'. - Example: - "object.x must be less than max ("+string(params.max)+")" - type: string - reason: - description: |- - Reason represents a machine-readable description of why this validation failed. - If this is the first validation in the list to fail, this reason, as well as the - corresponding HTTP response code, are used in the - HTTP response to the client. - The currently supported reasons are: "Unauthorized", "Forbidden", "Invalid", "RequestEntityTooLarge". - If not set, StatusReasonInvalid is used in the response to the client. - type: string - required: - - expression - type: object - type: array - generate: - default: false - description: |- - Generate specifies whether to generate a Kubernetes ValidatingAdmissionPolicy from the rule. - Optional. Defaults to "false" if not specified. - type: boolean - paramKind: - description: ParamKind is a tuple of Group Kind and - Version. - properties: - apiVersion: - description: |- - APIVersion is the API group version the resources belong to. - In format of "group/version". - Required. - type: string - kind: - description: |- - Kind is the API kind the resources belong to. - Required. - type: string - type: object - x-kubernetes-map-type: atomic - paramRef: - description: ParamRef references a parameter resource. - properties: - name: - description: |- - name is the name of the resource being referenced. - - One of `name` or `selector` must be set, but `name` and `selector` are - mutually exclusive properties. If one is set, the other must be unset. - - A single parameter used for all admission requests can be configured - by setting the `name` field, leaving `selector` blank, and setting namespace - if `paramKind` is namespace-scoped. - type: string - namespace: - description: |- - namespace is the namespace of the referenced resource. Allows limiting - the search for params to a specific namespace. Applies to both `name` and - `selector` fields. - - A per-namespace parameter may be used by specifying a namespace-scoped - `paramKind` in the policy and leaving this field empty. - - - If `paramKind` is cluster-scoped, this field MUST be unset. Setting this - field results in a configuration error. - - - If `paramKind` is namespace-scoped, the namespace of the object being - evaluated for admission will be used when this field is left unset. Take - care that if this is left empty the binding must not match any cluster-scoped - resources, which will result in an error. - type: string - parameterNotFoundAction: - description: |- - `parameterNotFoundAction` controls the behavior of the binding when the resource - exists, and name or selector is valid, but there are no parameters - matched by the binding. If the value is set to `Allow`, then no - matched parameters will be treated as successful validation by the binding. - If set to `Deny`, then no matched parameters will be subject to the - `failurePolicy` of the policy. - - Allowed values are `Allow` or `Deny` - - Required - type: string - selector: - description: |- - selector can be used to match multiple param objects based on their labels. - Supply selector: {} to match all resources of the ParamKind. - - If multiple params are found, they are all evaluated with the policy expressions - and the results are ANDed together. - - One of `name` or `selector` must be set, but `name` and `selector` are - mutually exclusive properties. If one is set, the other must be unset. - properties: - matchExpressions: - description: matchExpressions is a list of label - selector requirements. The requirements are - ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key that - the selector applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - type: object - x-kubernetes-map-type: atomic - variables: - description: |- - Variables contain definitions of variables that can be used in composition of other expressions. - Each variable is defined as a named CEL expression. - The variables defined here will be available under `variables` in other expressions of the policy. - items: - description: Variable is the definition of a variable - that is used for composition. A variable is defined - as a named expression. - properties: - expression: - description: |- - Expression is the expression that will be evaluated as the value of the variable. - The CEL expression has access to the same identifiers as the CEL expressions in Validation. - type: string - name: - description: |- - Name is the name of the variable. The name must be a valid CEL identifier and unique among all variables. - The variable can be accessed in other expressions through `variables` - For example, if name is "foo", the variable will be available as `variables.foo` - type: string - required: - - expression - - name - type: object - x-kubernetes-map-type: atomic - type: array - type: object - deny: - description: Deny defines conditions used to pass or fail - a validation rule. - properties: - conditions: - description: |- - Multiple conditions can be declared under an `any` or `all` statement. - See: https://kyverno.io/docs/writing-policies/validate/#deny-rules - properties: - all: - description: |- - AllConditions enable variable-based conditional rule execution. This is useful for - finer control of when an rule is applied. A condition can reference object data - using JMESPath notation. - Here, all of the conditions need to pass. - items: - properties: - key: - description: Key is the context entry (using - JMESPath) for conditional rule evaluation. - x-kubernetes-preserve-unknown-fields: true - message: - description: Message is an optional display - message - type: string - operator: - description: |- - Operator is the conditional operation to perform. Valid operators are: - Equals, NotEquals, In, AnyIn, AllIn, NotIn, AnyNotIn, AllNotIn, GreaterThanOrEquals, - GreaterThan, LessThanOrEquals, LessThan, DurationGreaterThanOrEquals, DurationGreaterThan, - DurationLessThanOrEquals, DurationLessThan - enum: - - Equals - - NotEquals - - AnyIn - - AllIn - - AnyNotIn - - AllNotIn - - GreaterThanOrEquals - - GreaterThan - - LessThanOrEquals - - LessThan - - DurationGreaterThanOrEquals - - DurationGreaterThan - - DurationLessThanOrEquals - - DurationLessThan - type: string - value: - description: |- - Value is the conditional value, or set of values. The values can be fixed set - or can be variables declared using JMESPath. - x-kubernetes-preserve-unknown-fields: true - type: object - type: array - any: - description: |- - AnyConditions enable variable-based conditional rule execution. This is useful for - finer control of when an rule is applied. A condition can reference object data - using JMESPath notation. - Here, at least one of the conditions need to pass. - items: - properties: - key: - description: Key is the context entry (using - JMESPath) for conditional rule evaluation. - x-kubernetes-preserve-unknown-fields: true - message: - description: Message is an optional display - message - type: string - operator: - description: |- - Operator is the conditional operation to perform. Valid operators are: - Equals, NotEquals, In, AnyIn, AllIn, NotIn, AnyNotIn, AllNotIn, GreaterThanOrEquals, - GreaterThan, LessThanOrEquals, LessThan, DurationGreaterThanOrEquals, DurationGreaterThan, - DurationLessThanOrEquals, DurationLessThan - enum: - - Equals - - NotEquals - - AnyIn - - AllIn - - AnyNotIn - - AllNotIn - - GreaterThanOrEquals - - GreaterThan - - LessThanOrEquals - - LessThan - - DurationGreaterThanOrEquals - - DurationGreaterThan - - DurationLessThanOrEquals - - DurationLessThan - type: string - value: - description: |- - Value is the conditional value, or set of values. The values can be fixed set - or can be variables declared using JMESPath. - x-kubernetes-preserve-unknown-fields: true - type: object - type: array - type: object - type: object - failureAction: - description: |- - FailureAction defines if a validation policy rule violation should block - the admission review request (Enforce), or allow (Audit) the admission review request - and report an error in a policy report. Optional. - Allowed values are Audit or Enforce. - enum: - - Audit - - Enforce - type: string - failureActionOverrides: - description: |- - FailureActionOverrides is a Cluster Policy attribute that specifies FailureAction - namespace-wise. It overrides FailureAction for the specified namespaces. - items: - properties: - action: - description: ValidationFailureAction defines the policy - validation failure action - enum: - - audit - - enforce - - Audit - - Enforce - type: string - namespaceSelector: - description: |- - A label selector is a label query over a set of resources. The result of matchLabels and - matchExpressions are ANDed. An empty label selector matches all objects. A null - label selector matches no objects. - properties: - matchExpressions: - description: matchExpressions is a list of label - selector requirements. The requirements are - ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key that the - selector applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - namespaces: - items: - type: string - type: array - type: object - type: array - foreach: - description: ForEach applies validate rules to a list of - sub-elements by creating a context for each entry in the - list and looping over it to apply the specified logic. - items: - description: ForEachValidation applies validate rules - to a list of sub-elements by creating a context for - each entry in the list and looping over it to apply - the specified logic. - properties: - anyPattern: - description: |- - AnyPattern specifies list of validation patterns. At least one of the patterns - must be satisfied for the validation rule to succeed. - x-kubernetes-preserve-unknown-fields: true - context: - description: Context defines variables and data sources - that can be used during rule execution. - items: - description: |- - ContextEntry adds variables and data sources to a rule Context. Either a - ConfigMap reference or a APILookup must be provided. - oneOf: - - required: - - configMap - - required: - - apiCall - - required: - - imageRegistry - - required: - - variable - - required: - - globalReference - properties: - apiCall: - description: |- - APICall is an HTTP request to the Kubernetes API server, or other JSON web service. - The data returned is stored in the context with the name for the context entry. - properties: - data: - description: |- - The data object specifies the POST data sent to the server. - Only applicable when the method field is set to POST. - items: - description: RequestData contains the - HTTP POST data - properties: - key: - description: Key is a unique identifier - for the data value - type: string - value: - description: Value is the data value - x-kubernetes-preserve-unknown-fields: true - required: - - key - - value - type: object - type: array - default: - description: |- - Default is an optional arbitrary JSON object that the context - value is set to, if the apiCall returns error. - x-kubernetes-preserve-unknown-fields: true - jmesPath: - description: |- - JMESPath is an optional JSON Match Expression that can be used to - transform the JSON response returned from the server. For example - a JMESPath of "items | length(@)" applied to the API server response - for the URLPath "/apis/apps/v1/deployments" will return the total count - of deployments across all namespaces. - type: string - method: - default: GET - description: Method is the HTTP request - type (GET or POST). Defaults to GET. - enum: - - GET - - POST - type: string - service: - description: |- - Service is an API call to a JSON web service. - This is used for non-Kubernetes API server calls. - It's mutually exclusive with the URLPath field. - properties: - caBundle: - description: |- - CABundle is a PEM encoded CA bundle which will be used to validate - the server certificate. - type: string - headers: - description: Headers is a list of optional - HTTP headers to be included in the - request. - items: - properties: - key: - description: Key is the header - key - type: string - value: - description: Value is the header - value - type: string - required: - - key - - value - type: object - type: array - url: - description: |- - URL is the JSON web service URL. A typical form is - `https://{service}.{namespace}:{port}/{path}`. - type: string - required: - - url - type: object - urlPath: - description: |- - URLPath is the URL path to be used in the HTTP GET or POST request to the - Kubernetes API server (e.g. "/api/v1/namespaces" or "/apis/apps/v1/deployments"). - The format required is the same format used by the `kubectl get --raw` command. - See https://kyverno.io/docs/writing-policies/external-data-sources/#variables-from-kubernetes-api-server-calls - for details. - It's mutually exclusive with the Service field. - type: string - type: object - configMap: - description: ConfigMap is the ConfigMap reference. - properties: - name: - description: Name is the ConfigMap name. - type: string - namespace: - description: Namespace is the ConfigMap - namespace. - type: string - required: - - name - type: object - globalReference: - description: GlobalContextEntryReference is - a reference to a cached global context entry. - properties: - jmesPath: - description: |- - JMESPath is an optional JSON Match Expression that can be used to - transform the JSON response returned from the server. For example - a JMESPath of "items | length(@)" applied to the API server response - for the URLPath "/apis/apps/v1/deployments" will return the total count - of deployments across all namespaces. - type: string - name: - description: Name of the global context - entry - type: string - required: - - name - type: object - imageRegistry: - description: |- - ImageRegistry defines requests to an OCI/Docker V2 registry to fetch image - details. - properties: - imageRegistryCredentials: - description: ImageRegistryCredentials provides - credentials that will be used for authentication - with registry - properties: - allowInsecureRegistry: - description: AllowInsecureRegistry allows - insecure access to a registry. - type: boolean - providers: - description: |- - Providers specifies a list of OCI Registry names, whose authentication providers are provided. - It can be of one of these values: default,google,azure,amazon,github. - items: - description: ImageRegistryCredentialsProvidersType - provides the list of credential - providers required. - enum: - - default - - amazon - - azure - - google - - github - type: string - type: array - secrets: - description: |- - Secrets specifies a list of secrets that are provided for credentials. - Secrets must live in the Kyverno namespace. - items: - type: string - type: array - type: object - jmesPath: - description: |- - JMESPath is an optional JSON Match Expression that can be used to - transform the ImageData struct returned as a result of processing - the image reference. - type: string - reference: - description: |- - Reference is image reference to a container image in the registry. - Example: ghcr.io/kyverno/kyverno:latest - type: string - required: - - reference - type: object - name: - description: Name is the variable name. - type: string - variable: - description: Variable defines an arbitrary JMESPath - context variable that can be defined inline. - properties: - default: - description: |- - Default is an optional arbitrary JSON object that the variable may take if the JMESPath - expression evaluates to nil - x-kubernetes-preserve-unknown-fields: true - jmesPath: - description: |- - JMESPath is an optional JMESPath Expression that can be used to - transform the variable. - type: string - value: - description: Value is any arbitrary JSON - object representable in YAML or JSON form. - x-kubernetes-preserve-unknown-fields: true - type: object - required: - - name - type: object - type: array - deny: - description: Deny defines conditions used to pass - or fail a validation rule. - properties: - conditions: - description: |- - Multiple conditions can be declared under an `any` or `all` statement. A direct list - of conditions (without `any` or `all` statements) is also supported for backwards compatibility - but will be deprecated in the next major release. - See: https://kyverno.io/docs/writing-policies/validate/#deny-rules - x-kubernetes-preserve-unknown-fields: true - type: object - elementScope: - description: |- - ElementScope specifies whether to use the current list element as the scope for validation. Defaults to "true" if not specified. - When set to "false", "request.object" is used as the validation scope within the foreach - block to allow referencing other elements in the subtree. - type: boolean - foreach: - description: Foreach declares a nested foreach iterator - x-kubernetes-preserve-unknown-fields: true - list: - description: |- - List specifies a JMESPath expression that results in one or more elements - to which the validation logic is applied. - type: string - pattern: - description: Pattern specifies an overlay-style pattern - used to check resources. - x-kubernetes-preserve-unknown-fields: true - preconditions: - description: |- - AnyAllConditions are used to determine if a policy rule should be applied by evaluating a - set of conditions. The declaration can contain nested `any` or `all` statements. - See: https://kyverno.io/docs/writing-policies/preconditions/ - properties: - all: - description: |- - AllConditions enable variable-based conditional rule execution. This is useful for - finer control of when an rule is applied. A condition can reference object data - using JMESPath notation. - Here, all of the conditions need to pass - items: - description: Condition defines variable-based - conditional criteria for rule execution. - properties: - key: - description: Key is the context entry (using - JMESPath) for conditional rule evaluation. - x-kubernetes-preserve-unknown-fields: true - message: - description: Message is an optional display - message - type: string - operator: - description: |- - Operator is the conditional operation to perform. Valid operators are: - Equals, NotEquals, In, AnyIn, AllIn, NotIn, AnyNotIn, AllNotIn, GreaterThanOrEquals, - GreaterThan, LessThanOrEquals, LessThan, DurationGreaterThanOrEquals, DurationGreaterThan, - DurationLessThanOrEquals, DurationLessThan - enum: - - Equals - - NotEquals - - In - - AnyIn - - AllIn - - NotIn - - AnyNotIn - - AllNotIn - - GreaterThanOrEquals - - GreaterThan - - LessThanOrEquals - - LessThan - - DurationGreaterThanOrEquals - - DurationGreaterThan - - DurationLessThanOrEquals - - DurationLessThan - type: string - value: - description: |- - Value is the conditional value, or set of values. The values can be fixed set - or can be variables declared using JMESPath. - x-kubernetes-preserve-unknown-fields: true - type: object - type: array - any: - description: |- - AnyConditions enable variable-based conditional rule execution. This is useful for - finer control of when an rule is applied. A condition can reference object data - using JMESPath notation. - Here, at least one of the conditions need to pass - items: - description: Condition defines variable-based - conditional criteria for rule execution. - properties: - key: - description: Key is the context entry (using - JMESPath) for conditional rule evaluation. - x-kubernetes-preserve-unknown-fields: true - message: - description: Message is an optional display - message - type: string - operator: - description: |- - Operator is the conditional operation to perform. Valid operators are: - Equals, NotEquals, In, AnyIn, AllIn, NotIn, AnyNotIn, AllNotIn, GreaterThanOrEquals, - GreaterThan, LessThanOrEquals, LessThan, DurationGreaterThanOrEquals, DurationGreaterThan, - DurationLessThanOrEquals, DurationLessThan - enum: - - Equals - - NotEquals - - In - - AnyIn - - AllIn - - NotIn - - AnyNotIn - - AllNotIn - - GreaterThanOrEquals - - GreaterThan - - LessThanOrEquals - - LessThan - - DurationGreaterThanOrEquals - - DurationGreaterThan - - DurationLessThanOrEquals - - DurationLessThan - type: string - value: - description: |- - Value is the conditional value, or set of values. The values can be fixed set - or can be variables declared using JMESPath. - x-kubernetes-preserve-unknown-fields: true - type: object - type: array - type: object - x-kubernetes-preserve-unknown-fields: true - type: object - type: array - manifests: - description: Manifest specifies conditions for manifest - verification - properties: - annotationDomain: - description: AnnotationDomain is custom domain of annotation - for message and signature. Default is "cosign.sigstore.dev". - type: string - attestors: - description: Attestors specified the required attestors - (i.e. authorities) - items: - properties: - count: - description: |- - Count specifies the required number of entries that must match. If the count is null, all entries must match - (a logical AND). If the count is 1, at least one entry must match (a logical OR). If the count contains a - value N, then N must be less than or equal to the size of entries, and at least N entries must match. - minimum: 1 - type: integer - entries: - description: |- - Entries contains the available attestors. An attestor can be a static key, - attributes for keyless verification, or a nested attestor declaration. - items: - properties: - annotations: - additionalProperties: - type: string - description: |- - Annotations are used for image verification. - Every specified key-value pair must exist and match in the verified payload. - The payload may contain other key-value pairs. - type: object - attestor: - description: Attestor is a nested set of - Attestor used to specify a more complex - set of match authorities. - x-kubernetes-preserve-unknown-fields: true - certificates: - description: Certificates specifies one - or more certificates. - properties: - cert: - description: Cert is an optional PEM-encoded - public certificate. - type: string - certChain: - description: CertChain is an optional - PEM encoded set of certificates used - to verify. - type: string - ctlog: - description: |- - CTLog (certificate timestamp log) provides a configuration for validation of Signed Certificate - Timestamps (SCTs). If the value is unset, the default behavior by Cosign is used. - properties: - ignoreSCT: - description: |- - IgnoreSCT defines whether to use the Signed Certificate Timestamp (SCT) log to check for a certificate - timestamp. Default is false. Set to true if this was opted out during signing. - type: boolean - pubkey: - description: PubKey, if set, is - used to validate SCTs against - a custom source. - type: string - tsaCertChain: - description: |- - TSACertChain, if set, is the PEM-encoded certificate chain file for the RFC3161 timestamp authority. Must - contain the root CA certificate. Optionally may contain intermediate CA certificates, and - may contain the leaf TSA certificate if not present in the timestamurce. - type: string - type: object - rekor: - description: |- - Rekor provides configuration for the Rekor transparency log service. If an empty object - is provided the public instance of Rekor (https://rekor.sigstore.dev) is used. - properties: - ignoreTlog: - description: IgnoreTlog skips transparency - log verification. - type: boolean - pubkey: - description: |- - RekorPubKey is an optional PEM-encoded public key to use for a custom Rekor. - If set, this will be used to validate transparency log signatures from a custom Rekor. - type: string - url: - description: URL is the address - of the transparency log. Defaults - to the public Rekor log instance - https://rekor.sigstore.dev. - type: string - type: object - type: object - keyless: - description: |- - Keyless is a set of attribute used to verify a Sigstore keyless attestor. - See https://github.com/sigstore/cosign/blob/main/KEYLESS.md. - properties: - additionalExtensions: - additionalProperties: - type: string - description: AdditionalExtensions are - certificate-extensions used for keyless - signing. - type: object - ctlog: - description: |- - CTLog (certificate timestamp log) provides a configuration for validation of Signed Certificate - Timestamps (SCTs). If the value is unset, the default behavior by Cosign is used. - properties: - ignoreSCT: - description: |- - IgnoreSCT defines whether to use the Signed Certificate Timestamp (SCT) log to check for a certificate - timestamp. Default is false. Set to true if this was opted out during signing. - type: boolean - pubkey: - description: PubKey, if set, is - used to validate SCTs against - a custom source. - type: string - tsaCertChain: - description: |- - TSACertChain, if set, is the PEM-encoded certificate chain file for the RFC3161 timestamp authority. Must - contain the root CA certificate. Optionally may contain intermediate CA certificates, and - may contain the leaf TSA certificate if not present in the timestamurce. - type: string - type: object - issuer: - description: Issuer is the certificate - issuer used for keyless signing. - type: string - issuerRegExp: - description: IssuerRegExp is the regular - expression to match certificate issuer - used for keyless signing. - type: string - rekor: - description: |- - Rekor provides configuration for the Rekor transparency log service. If an empty object - is provided the public instance of Rekor (https://rekor.sigstore.dev) is used. - properties: - ignoreTlog: - description: IgnoreTlog skips transparency - log verification. - type: boolean - pubkey: - description: |- - RekorPubKey is an optional PEM-encoded public key to use for a custom Rekor. - If set, this will be used to validate transparency log signatures from a custom Rekor. - type: string - url: - description: URL is the address - of the transparency log. Defaults - to the public Rekor log instance - https://rekor.sigstore.dev. - type: string - type: object - roots: - description: |- - Roots is an optional set of PEM encoded trusted root certificates. - If not provided, the system roots are used. - type: string - subject: - description: Subject is the verified - identity used for keyless signing, - for example the email address. - type: string - subjectRegExp: - description: SubjectRegExp is the regular - expression to match identity used - for keyless signing, for example the - email address. - type: string - type: object - keys: - description: Keys specifies one or more - public keys. - properties: - ctlog: - description: |- - CTLog (certificate timestamp log) provides a configuration for validation of Signed Certificate - Timestamps (SCTs). If the value is unset, the default behavior by Cosign is used. - properties: - ignoreSCT: - description: |- - IgnoreSCT defines whether to use the Signed Certificate Timestamp (SCT) log to check for a certificate - timestamp. Default is false. Set to true if this was opted out during signing. - type: boolean - pubkey: - description: PubKey, if set, is - used to validate SCTs against - a custom source. - type: string - tsaCertChain: - description: |- - TSACertChain, if set, is the PEM-encoded certificate chain file for the RFC3161 timestamp authority. Must - contain the root CA certificate. Optionally may contain intermediate CA certificates, and - may contain the leaf TSA certificate if not present in the timestamurce. - type: string - type: object - kms: - description: |- - KMS provides the URI to the public key stored in a Key Management System. See: - https://github.com/sigstore/cosign/blob/main/KMS.md - type: string - publicKeys: - description: |- - Keys is a set of X.509 public keys used to verify image signatures. The keys can be directly - specified or can be a variable reference to a key specified in a ConfigMap (see - https://kyverno.io/docs/writing-policies/variables/), or reference a standard Kubernetes Secret - elsewhere in the cluster by specifying it in the format "k8s:///". - The named Secret must specify a key `cosign.pub` containing the public key used for - verification, (see https://github.com/sigstore/cosign/blob/main/KMS.md#kubernetes-secret). - When multiple keys are specified each key is processed as a separate staticKey entry - (.attestors[*].entries.keys) within the set of attestors and the count is applied across the keys. - type: string - rekor: - description: |- - Rekor provides configuration for the Rekor transparency log service. If an empty object - is provided the public instance of Rekor (https://rekor.sigstore.dev) is used. - properties: - ignoreTlog: - description: IgnoreTlog skips transparency - log verification. - type: boolean - pubkey: - description: |- - RekorPubKey is an optional PEM-encoded public key to use for a custom Rekor. - If set, this will be used to validate transparency log signatures from a custom Rekor. - type: string - url: - description: URL is the address - of the transparency log. Defaults - to the public Rekor log instance - https://rekor.sigstore.dev. - type: string - type: object - secret: - description: Reference to a Secret resource - that contains a public key - properties: - name: - description: Name of the secret. - The provided secret must contain - a key named cosign.pub. - type: string - namespace: - description: Namespace name where - the Secret exists. - type: string - required: - - name - - namespace - type: object - signatureAlgorithm: - default: sha256 - description: Deprecated. Use attestor.signatureAlgorithm - instead. - type: string - type: object - repository: - description: |- - Repository is an optional alternate OCI repository to use for signatures and attestations that match this rule. - If specified Repository will override other OCI image repository locations for this Attestor. - type: string - signatureAlgorithm: - default: sha256 - description: Specify signature algorithm - for public keys. Supported values are - sha224, sha256, sha384 and sha512. - type: string - type: object - type: array - type: object - type: array - dryRun: - description: DryRun configuration - properties: - enable: - type: boolean - namespace: - type: string - type: object - ignoreFields: - description: Fields which will be ignored while comparing - manifests. - items: - properties: - fields: - items: - type: string - type: array - objects: - items: - properties: - group: - type: string - kind: - type: string - name: - type: string - namespace: - type: string - version: - type: string - type: object - type: array - type: object - type: array - repository: - description: |- - Repository is an optional alternate OCI repository to use for resource bundle reference. - The repository can be overridden per Attestor or Attestation. - type: string - type: object - message: - description: Message specifies a custom message to be displayed - on failure. - type: string - pattern: - description: Pattern specifies an overlay-style pattern - used to check resources. - x-kubernetes-preserve-unknown-fields: true - podSecurity: - description: |- - PodSecurity applies exemptions for Kubernetes Pod Security admission - by specifying exclusions for Pod Security Standards controls. - properties: - exclude: - description: Exclude specifies the Pod Security Standard - controls to be excluded. - items: - description: PodSecurityStandard specifies the Pod - Security Standard controls to be excluded. - properties: - controlName: - description: |- - ControlName specifies the name of the Pod Security Standard control. - See: https://kubernetes.io/docs/concepts/security/pod-security-standards/ - enum: - - HostProcess - - Host Namespaces - - Privileged Containers - - Capabilities - - HostPath Volumes - - Host Ports - - AppArmor - - SELinux - - /proc Mount Type - - Seccomp - - Sysctls - - Volume Types - - Privilege Escalation - - Running as Non-root - - Running as Non-root user - type: string - images: - description: |- - Images selects matching containers and applies the container level PSS. - Each image is the image name consisting of the registry address, repository, image, and tag. - Empty list matches no containers, PSS checks are applied at the pod level only. - Wildcards ('*' and '?') are allowed. See: https://kubernetes.io/docs/concepts/containers/images. - items: - type: string - type: array - restrictedField: - description: |- - RestrictedField selects the field for the given Pod Security Standard control. - When not set, all restricted fields for the control are selected. - type: string - values: - description: Values defines the allowed values - that can be excluded. - items: - type: string - type: array - required: - - controlName - type: object - type: array - level: - description: |- - Level defines the Pod Security Standard level to be applied to workloads. - Allowed values are privileged, baseline, and restricted. - enum: - - privileged - - baseline - - restricted - type: string - version: - description: |- - Version defines the Pod Security Standard versions that Kubernetes supports. - Allowed values are v1.19, v1.20, v1.21, v1.22, v1.23, v1.24, v1.25, v1.26, v1.27, v1.28, v1.29, latest. Defaults to latest. - enum: - - v1.19 - - v1.20 - - v1.21 - - v1.22 - - v1.23 - - v1.24 - - v1.25 - - v1.26 - - v1.27 - - v1.28 - - v1.29 - - latest - type: string - type: object - type: object - verifyImages: - description: VerifyImages is used to verify image signatures - and mutate them to add a digest - items: - description: |- - ImageVerification validates that images that match the specified pattern - are signed with the supplied public key. Once the image is verified it is - mutated to include the SHA digest retrieved during the registration. - properties: - attestations: - description: |- - Attestations are optional checks for signed in-toto Statements used to verify the image. - See https://github.com/in-toto/attestation. Kyverno fetches signed attestations from the - OCI registry and decodes them into a list of Statement declarations. - items: - description: |- - Attestation are checks for signed in-toto Statements that are used to verify the image. - See https://github.com/in-toto/attestation. Kyverno fetches signed attestations from the - OCI registry and decodes them into a list of Statements. - properties: - attestors: - description: Attestors specify the required attestors - (i.e. authorities). - items: - properties: - count: - description: |- - Count specifies the required number of entries that must match. If the count is null, all entries must match - (a logical AND). If the count is 1, at least one entry must match (a logical OR). If the count contains a - value N, then N must be less than or equal to the size of entries, and at least N entries must match. - minimum: 1 - type: integer - entries: - description: |- - Entries contains the available attestors. An attestor can be a static key, - attributes for keyless verification, or a nested attestor declaration. - items: - properties: - annotations: - additionalProperties: - type: string - description: |- - Annotations are used for image verification. - Every specified key-value pair must exist and match in the verified payload. - The payload may contain other key-value pairs. - type: object - attestor: - description: Attestor is a nested set - of Attestor used to specify a more - complex set of match authorities. - x-kubernetes-preserve-unknown-fields: true - certificates: - description: Certificates specifies - one or more certificates. - properties: - cert: - description: Cert is an optional - PEM-encoded public certificate. - type: string - certChain: - description: CertChain is an optional - PEM encoded set of certificates - used to verify. - type: string - ctlog: - description: |- - CTLog (certificate timestamp log) provides a configuration for validation of Signed Certificate - Timestamps (SCTs). If the value is unset, the default behavior by Cosign is used. - properties: - ignoreSCT: - description: |- - IgnoreSCT defines whether to use the Signed Certificate Timestamp (SCT) log to check for a certificate - timestamp. Default is false. Set to true if this was opted out during signing. - type: boolean - pubkey: - description: PubKey, if set, - is used to validate SCTs against - a custom source. - type: string - tsaCertChain: - description: |- - TSACertChain, if set, is the PEM-encoded certificate chain file for the RFC3161 timestamp authority. Must - contain the root CA certificate. Optionally may contain intermediate CA certificates, and - may contain the leaf TSA certificate if not present in the timestamurce. - type: string - type: object - rekor: - description: |- - Rekor provides configuration for the Rekor transparency log service. If an empty object - is provided the public instance of Rekor (https://rekor.sigstore.dev) is used. - properties: - ignoreTlog: - description: IgnoreTlog skips - transparency log verification. - type: boolean - pubkey: - description: |- - RekorPubKey is an optional PEM-encoded public key to use for a custom Rekor. - If set, this will be used to validate transparency log signatures from a custom Rekor. - type: string - url: - description: URL is the address - of the transparency log. Defaults - to the public Rekor log instance - https://rekor.sigstore.dev. - type: string - type: object - type: object - keyless: - description: |- - Keyless is a set of attribute used to verify a Sigstore keyless attestor. - See https://github.com/sigstore/cosign/blob/main/KEYLESS.md. - properties: - additionalExtensions: - additionalProperties: - type: string - description: AdditionalExtensions - are certificate-extensions used - for keyless signing. - type: object - ctlog: - description: |- - CTLog (certificate timestamp log) provides a configuration for validation of Signed Certificate - Timestamps (SCTs). If the value is unset, the default behavior by Cosign is used. - properties: - ignoreSCT: - description: |- - IgnoreSCT defines whether to use the Signed Certificate Timestamp (SCT) log to check for a certificate - timestamp. Default is false. Set to true if this was opted out during signing. - type: boolean - pubkey: - description: PubKey, if set, - is used to validate SCTs against - a custom source. - type: string - tsaCertChain: - description: |- - TSACertChain, if set, is the PEM-encoded certificate chain file for the RFC3161 timestamp authority. Must - contain the root CA certificate. Optionally may contain intermediate CA certificates, and - may contain the leaf TSA certificate if not present in the timestamurce. - type: string - type: object - issuer: - description: Issuer is the certificate - issuer used for keyless signing. - type: string - issuerRegExp: - description: IssuerRegExp is the - regular expression to match certificate - issuer used for keyless signing. - type: string - rekor: - description: |- - Rekor provides configuration for the Rekor transparency log service. If an empty object - is provided the public instance of Rekor (https://rekor.sigstore.dev) is used. - properties: - ignoreTlog: - description: IgnoreTlog skips - transparency log verification. - type: boolean - pubkey: - description: |- - RekorPubKey is an optional PEM-encoded public key to use for a custom Rekor. - If set, this will be used to validate transparency log signatures from a custom Rekor. - type: string - url: - description: URL is the address - of the transparency log. Defaults - to the public Rekor log instance - https://rekor.sigstore.dev. - type: string - type: object - roots: - description: |- - Roots is an optional set of PEM encoded trusted root certificates. - If not provided, the system roots are used. - type: string - subject: - description: Subject is the verified - identity used for keyless signing, - for example the email address. - type: string - subjectRegExp: - description: SubjectRegExp is the - regular expression to match identity - used for keyless signing, for - example the email address. - type: string - type: object - keys: - description: Keys specifies one or more - public keys. - properties: - ctlog: - description: |- - CTLog (certificate timestamp log) provides a configuration for validation of Signed Certificate - Timestamps (SCTs). If the value is unset, the default behavior by Cosign is used. - properties: - ignoreSCT: - description: |- - IgnoreSCT defines whether to use the Signed Certificate Timestamp (SCT) log to check for a certificate - timestamp. Default is false. Set to true if this was opted out during signing. - type: boolean - pubkey: - description: PubKey, if set, - is used to validate SCTs against - a custom source. - type: string - tsaCertChain: - description: |- - TSACertChain, if set, is the PEM-encoded certificate chain file for the RFC3161 timestamp authority. Must - contain the root CA certificate. Optionally may contain intermediate CA certificates, and - may contain the leaf TSA certificate if not present in the timestamurce. - type: string - type: object - kms: - description: |- - KMS provides the URI to the public key stored in a Key Management System. See: - https://github.com/sigstore/cosign/blob/main/KMS.md - type: string - publicKeys: - description: |- - Keys is a set of X.509 public keys used to verify image signatures. The keys can be directly - specified or can be a variable reference to a key specified in a ConfigMap (see - https://kyverno.io/docs/writing-policies/variables/), or reference a standard Kubernetes Secret - elsewhere in the cluster by specifying it in the format "k8s:///". - The named Secret must specify a key `cosign.pub` containing the public key used for - verification, (see https://github.com/sigstore/cosign/blob/main/KMS.md#kubernetes-secret). - When multiple keys are specified each key is processed as a separate staticKey entry - (.attestors[*].entries.keys) within the set of attestors and the count is applied across the keys. - type: string - rekor: - description: |- - Rekor provides configuration for the Rekor transparency log service. If an empty object - is provided the public instance of Rekor (https://rekor.sigstore.dev) is used. - properties: - ignoreTlog: - description: IgnoreTlog skips - transparency log verification. - type: boolean - pubkey: - description: |- - RekorPubKey is an optional PEM-encoded public key to use for a custom Rekor. - If set, this will be used to validate transparency log signatures from a custom Rekor. - type: string - url: - description: URL is the address - of the transparency log. Defaults - to the public Rekor log instance - https://rekor.sigstore.dev. - type: string - type: object - secret: - description: Reference to a Secret - resource that contains a public - key - properties: - name: - description: Name of the secret. - The provided secret must contain - a key named cosign.pub. - type: string - namespace: - description: Namespace name - where the Secret exists. - type: string - required: - - name - - namespace - type: object - signatureAlgorithm: - default: sha256 - description: Deprecated. Use attestor.signatureAlgorithm - instead. - type: string - type: object - repository: - description: |- - Repository is an optional alternate OCI repository to use for signatures and attestations that match this rule. - If specified Repository will override other OCI image repository locations for this Attestor. - type: string - signatureAlgorithm: - default: sha256 - description: Specify signature algorithm - for public keys. Supported values - are sha224, sha256, sha384 and sha512. - type: string - type: object - type: array - type: object - type: array - conditions: - description: |- - Conditions are used to verify attributes within a Predicate. If no Conditions are specified - the attestation check is satisfied as long there are predicates that match the predicate type. - items: - description: |- - AnyAllConditions consists of conditions wrapped denoting a logical criteria to be fulfilled. - AnyConditions get fulfilled when at least one of its sub-conditions passes. - AllConditions get fulfilled only when all of its sub-conditions pass. - properties: - all: - description: |- - AllConditions enable variable-based conditional rule execution. This is useful for - finer control of when an rule is applied. A condition can reference object data - using JMESPath notation. - Here, all of the conditions need to pass - items: - description: Condition defines variable-based - conditional criteria for rule execution. - properties: - key: - description: Key is the context entry - (using JMESPath) for conditional rule - evaluation. - x-kubernetes-preserve-unknown-fields: true - message: - description: Message is an optional - display message - type: string - operator: - description: |- - Operator is the conditional operation to perform. Valid operators are: - Equals, NotEquals, In, AnyIn, AllIn, NotIn, AnyNotIn, AllNotIn, GreaterThanOrEquals, - GreaterThan, LessThanOrEquals, LessThan, DurationGreaterThanOrEquals, DurationGreaterThan, - DurationLessThanOrEquals, DurationLessThan - enum: - - Equals - - NotEquals - - In - - AnyIn - - AllIn - - NotIn - - AnyNotIn - - AllNotIn - - GreaterThanOrEquals - - GreaterThan - - LessThanOrEquals - - LessThan - - DurationGreaterThanOrEquals - - DurationGreaterThan - - DurationLessThanOrEquals - - DurationLessThan - type: string - value: - description: |- - Value is the conditional value, or set of values. The values can be fixed set - or can be variables declared using JMESPath. - x-kubernetes-preserve-unknown-fields: true - type: object - type: array - any: - description: |- - AnyConditions enable variable-based conditional rule execution. This is useful for - finer control of when an rule is applied. A condition can reference object data - using JMESPath notation. - Here, at least one of the conditions need to pass - items: - description: Condition defines variable-based - conditional criteria for rule execution. - properties: - key: - description: Key is the context entry - (using JMESPath) for conditional rule - evaluation. - x-kubernetes-preserve-unknown-fields: true - message: - description: Message is an optional - display message - type: string - operator: - description: |- - Operator is the conditional operation to perform. Valid operators are: - Equals, NotEquals, In, AnyIn, AllIn, NotIn, AnyNotIn, AllNotIn, GreaterThanOrEquals, - GreaterThan, LessThanOrEquals, LessThan, DurationGreaterThanOrEquals, DurationGreaterThan, - DurationLessThanOrEquals, DurationLessThan - enum: - - Equals - - NotEquals - - In - - AnyIn - - AllIn - - NotIn - - AnyNotIn - - AllNotIn - - GreaterThanOrEquals - - GreaterThan - - LessThanOrEquals - - LessThan - - DurationGreaterThanOrEquals - - DurationGreaterThan - - DurationLessThanOrEquals - - DurationLessThan - type: string - value: - description: |- - Value is the conditional value, or set of values. The values can be fixed set - or can be variables declared using JMESPath. - x-kubernetes-preserve-unknown-fields: true - type: object - type: array - type: object - type: array - name: - description: Name is the variable name. - type: string - predicateType: - description: Deprecated in favour of 'Type', to - be removed soon - type: string - type: - description: Type defines the type of attestation - contained within the Statement. - type: string - type: object - type: array - attestors: - description: Attestors specified the required attestors - (i.e. authorities) - items: - properties: - count: - description: |- - Count specifies the required number of entries that must match. If the count is null, all entries must match - (a logical AND). If the count is 1, at least one entry must match (a logical OR). If the count contains a - value N, then N must be less than or equal to the size of entries, and at least N entries must match. - minimum: 1 - type: integer - entries: - description: |- - Entries contains the available attestors. An attestor can be a static key, - attributes for keyless verification, or a nested attestor declaration. - items: - properties: - annotations: - additionalProperties: - type: string - description: |- - Annotations are used for image verification. - Every specified key-value pair must exist and match in the verified payload. - The payload may contain other key-value pairs. - type: object - attestor: - description: Attestor is a nested set of Attestor - used to specify a more complex set of match - authorities. - x-kubernetes-preserve-unknown-fields: true - certificates: - description: Certificates specifies one or - more certificates. - properties: - cert: - description: Cert is an optional PEM-encoded - public certificate. - type: string - certChain: - description: CertChain is an optional - PEM encoded set of certificates used - to verify. - type: string - ctlog: - description: |- - CTLog (certificate timestamp log) provides a configuration for validation of Signed Certificate - Timestamps (SCTs). If the value is unset, the default behavior by Cosign is used. - properties: - ignoreSCT: - description: |- - IgnoreSCT defines whether to use the Signed Certificate Timestamp (SCT) log to check for a certificate - timestamp. Default is false. Set to true if this was opted out during signing. - type: boolean - pubkey: - description: PubKey, if set, is used - to validate SCTs against a custom - source. - type: string - tsaCertChain: - description: |- - TSACertChain, if set, is the PEM-encoded certificate chain file for the RFC3161 timestamp authority. Must - contain the root CA certificate. Optionally may contain intermediate CA certificates, and - may contain the leaf TSA certificate if not present in the timestamurce. - type: string - type: object - rekor: - description: |- - Rekor provides configuration for the Rekor transparency log service. If an empty object - is provided the public instance of Rekor (https://rekor.sigstore.dev) is used. - properties: - ignoreTlog: - description: IgnoreTlog skips transparency - log verification. - type: boolean - pubkey: - description: |- - RekorPubKey is an optional PEM-encoded public key to use for a custom Rekor. - If set, this will be used to validate transparency log signatures from a custom Rekor. - type: string - url: - description: URL is the address of - the transparency log. Defaults to - the public Rekor log instance https://rekor.sigstore.dev. - type: string - type: object - type: object - keyless: - description: |- - Keyless is a set of attribute used to verify a Sigstore keyless attestor. - See https://github.com/sigstore/cosign/blob/main/KEYLESS.md. - properties: - additionalExtensions: - additionalProperties: - type: string - description: AdditionalExtensions are - certificate-extensions used for keyless - signing. - type: object - ctlog: - description: |- - CTLog (certificate timestamp log) provides a configuration for validation of Signed Certificate - Timestamps (SCTs). If the value is unset, the default behavior by Cosign is used. - properties: - ignoreSCT: - description: |- - IgnoreSCT defines whether to use the Signed Certificate Timestamp (SCT) log to check for a certificate - timestamp. Default is false. Set to true if this was opted out during signing. - type: boolean - pubkey: - description: PubKey, if set, is used - to validate SCTs against a custom - source. - type: string - tsaCertChain: - description: |- - TSACertChain, if set, is the PEM-encoded certificate chain file for the RFC3161 timestamp authority. Must - contain the root CA certificate. Optionally may contain intermediate CA certificates, and - may contain the leaf TSA certificate if not present in the timestamurce. - type: string - type: object - issuer: - description: Issuer is the certificate - issuer used for keyless signing. - type: string - issuerRegExp: - description: IssuerRegExp is the regular - expression to match certificate issuer - used for keyless signing. - type: string - rekor: - description: |- - Rekor provides configuration for the Rekor transparency log service. If an empty object - is provided the public instance of Rekor (https://rekor.sigstore.dev) is used. - properties: - ignoreTlog: - description: IgnoreTlog skips transparency - log verification. - type: boolean - pubkey: - description: |- - RekorPubKey is an optional PEM-encoded public key to use for a custom Rekor. - If set, this will be used to validate transparency log signatures from a custom Rekor. - type: string - url: - description: URL is the address of - the transparency log. Defaults to - the public Rekor log instance https://rekor.sigstore.dev. - type: string - type: object - roots: - description: |- - Roots is an optional set of PEM encoded trusted root certificates. - If not provided, the system roots are used. - type: string - subject: - description: Subject is the verified identity - used for keyless signing, for example - the email address. - type: string - subjectRegExp: - description: SubjectRegExp is the regular - expression to match identity used for - keyless signing, for example the email - address. - type: string - type: object - keys: - description: Keys specifies one or more public - keys. - properties: - ctlog: - description: |- - CTLog (certificate timestamp log) provides a configuration for validation of Signed Certificate - Timestamps (SCTs). If the value is unset, the default behavior by Cosign is used. - properties: - ignoreSCT: - description: |- - IgnoreSCT defines whether to use the Signed Certificate Timestamp (SCT) log to check for a certificate - timestamp. Default is false. Set to true if this was opted out during signing. - type: boolean - pubkey: - description: PubKey, if set, is used - to validate SCTs against a custom - source. - type: string - tsaCertChain: - description: |- - TSACertChain, if set, is the PEM-encoded certificate chain file for the RFC3161 timestamp authority. Must - contain the root CA certificate. Optionally may contain intermediate CA certificates, and - may contain the leaf TSA certificate if not present in the timestamurce. - type: string - type: object - kms: - description: |- - KMS provides the URI to the public key stored in a Key Management System. See: - https://github.com/sigstore/cosign/blob/main/KMS.md - type: string - publicKeys: - description: |- - Keys is a set of X.509 public keys used to verify image signatures. The keys can be directly - specified or can be a variable reference to a key specified in a ConfigMap (see - https://kyverno.io/docs/writing-policies/variables/), or reference a standard Kubernetes Secret - elsewhere in the cluster by specifying it in the format "k8s:///". - The named Secret must specify a key `cosign.pub` containing the public key used for - verification, (see https://github.com/sigstore/cosign/blob/main/KMS.md#kubernetes-secret). - When multiple keys are specified each key is processed as a separate staticKey entry - (.attestors[*].entries.keys) within the set of attestors and the count is applied across the keys. - type: string - rekor: - description: |- - Rekor provides configuration for the Rekor transparency log service. If an empty object - is provided the public instance of Rekor (https://rekor.sigstore.dev) is used. - properties: - ignoreTlog: - description: IgnoreTlog skips transparency - log verification. - type: boolean - pubkey: - description: |- - RekorPubKey is an optional PEM-encoded public key to use for a custom Rekor. - If set, this will be used to validate transparency log signatures from a custom Rekor. - type: string - url: - description: URL is the address of - the transparency log. Defaults to - the public Rekor log instance https://rekor.sigstore.dev. - type: string - type: object - secret: - description: Reference to a Secret resource - that contains a public key - properties: - name: - description: Name of the secret. The - provided secret must contain a key - named cosign.pub. - type: string - namespace: - description: Namespace name where - the Secret exists. - type: string - required: - - name - - namespace - type: object - signatureAlgorithm: - default: sha256 - description: Deprecated. Use attestor.signatureAlgorithm - instead. - type: string - type: object - repository: - description: |- - Repository is an optional alternate OCI repository to use for signatures and attestations that match this rule. - If specified Repository will override other OCI image repository locations for this Attestor. - type: string - signatureAlgorithm: - default: sha256 - description: Specify signature algorithm for - public keys. Supported values are sha224, - sha256, sha384 and sha512. - type: string - type: object - type: array - type: object - type: array - failureAction: - description: Allowed values are Audit or Enforce. - enum: - - Audit - - Enforce - type: string - imageReferences: - description: |- - ImageReferences is a list of matching image reference patterns. At least one pattern in the - list must match the image for the rule to apply. Each image reference consists of a registry - address (defaults to docker.io), repository, image, and tag (defaults to latest). - Wildcards ('*' and '?') are allowed. See: https://kubernetes.io/docs/concepts/containers/images. - items: - type: string - type: array - imageRegistryCredentials: - description: ImageRegistryCredentials provides credentials - that will be used for authentication with registry - properties: - allowInsecureRegistry: - description: AllowInsecureRegistry allows insecure - access to a registry. - type: boolean - providers: - description: |- - Providers specifies a list of OCI Registry names, whose authentication providers are provided. - It can be of one of these values: default,google,azure,amazon,github. - items: - description: ImageRegistryCredentialsProvidersType - provides the list of credential providers required. - enum: - - default - - amazon - - azure - - google - - github - type: string - type: array - secrets: - description: |- - Secrets specifies a list of secrets that are provided for credentials. - Secrets must live in the Kyverno namespace. - items: - type: string - type: array - type: object - mutateDigest: - default: true - description: |- - MutateDigest enables replacement of image tags with digests. - Defaults to true. - type: boolean - repository: - description: |- - Repository is an optional alternate OCI repository to use for image signatures and attestations that match this rule. - If specified Repository will override the default OCI image repository configured for the installation. - The repository can also be overridden per Attestor or Attestation. - type: string - required: - default: true - description: Required validates that images are verified - i.e. have matched passed a signature or attestation - check. - type: boolean - skipImageReferences: - description: |- - SkipImageReferences is a list of matching image reference patterns that should be skipped. - At least one pattern in the list must match the image for the rule to be skipped. Each image reference - consists of a registry address (defaults to docker.io), repository, image, and tag (defaults to latest). - Wildcards ('*' and '?') are allowed. See: https://kubernetes.io/docs/concepts/containers/images. - items: - type: string - type: array - type: - description: |- - Type specifies the method of signature validation. The allowed options - are Cosign and Notary. By default Cosign is used if a type is not specified. - enum: - - Cosign - - SigstoreBundle - - Notary - type: string - useCache: - default: true - description: UseCache enables caching of image verify - responses for this rule - type: boolean - validate: - description: |- - Validation checks conditions across multiple image - verification attestations or context entries - properties: - deny: - description: Deny defines conditions used to pass - or fail a validation rule. - properties: - conditions: - description: |- - Multiple conditions can be declared under an `any` or `all` statement. A direct list - of conditions (without `any` or `all` statements) is also supported for backwards compatibility - but will be deprecated in the next major release. - See: https://kyverno.io/docs/writing-policies/validate/#deny-rules - x-kubernetes-preserve-unknown-fields: true - type: object - message: - description: Message specifies a custom message to - be displayed on failure. - type: string - type: object - verifyDigest: - default: true - description: VerifyDigest validates that images have a - digest. - type: boolean - type: object - type: array - required: - - match - - name - type: object - type: array - schemaValidation: - description: Deprecated. - type: boolean - useServerSideApply: - description: |- - UseServerSideApply controls whether to use server-side apply for generate rules - If is set to "true" create & update for generate rules will use apply instead of create/update. - Defaults to "false" if not specified. - type: boolean - validationFailureAction: - default: Audit - description: Deprecated, use validationFailureAction under the validate - rule instead. - enum: - - audit - - enforce - - Audit - - Enforce - type: string - validationFailureActionOverrides: - description: Deprecated, use validationFailureActionOverrides under - the validate rule instead. - items: - properties: - action: - description: ValidationFailureAction defines the policy validation - failure action - enum: - - audit - - enforce - - Audit - - Enforce - type: string - namespaceSelector: - description: |- - A label selector is a label query over a set of resources. The result of matchLabels and - matchExpressions are ANDed. An empty label selector matches all objects. A null - label selector matches no objects. - properties: - matchExpressions: - description: matchExpressions is a list of label selector - requirements. The requirements are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key that the selector - applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - namespaces: - items: - type: string - type: array - type: object - type: array - webhookConfiguration: - description: WebhookConfiguration specifies the custom configuration - for Kubernetes admission webhookconfiguration. - properties: - failurePolicy: - description: |- - FailurePolicy defines how unexpected policy errors and webhook response timeout errors are handled. - Rules within the same policy share the same failure behavior. - This field should not be accessed directly, instead `GetFailurePolicy()` should be used. - Allowed values are Ignore or Fail. Defaults to Fail. - enum: - - Ignore - - Fail - type: string - matchConditions: - description: |- - MatchCondition configures admission webhook matchConditions. - Requires Kubernetes 1.27 or later. - items: - description: MatchCondition represents a condition which must - by fulfilled for a request to be sent to a webhook. - properties: - expression: - description: |- - Expression represents the expression which will be evaluated by CEL. Must evaluate to bool. - CEL expressions have access to the contents of the AdmissionRequest and Authorizer, organized into CEL variables: - - 'object' - The object from the incoming request. The value is null for DELETE requests. - 'oldObject' - The existing object. The value is null for CREATE requests. - 'request' - Attributes of the admission request(/pkg/apis/admission/types.go#AdmissionRequest). - 'authorizer' - A CEL Authorizer. May be used to perform authorization checks for the principal (user or service account) of the request. - See https://pkg.go.dev/k8s.io/apiserver/pkg/cel/library#Authz - 'authorizer.requestResource' - A CEL ResourceCheck constructed from the 'authorizer' and configured with the - request resource. - Documentation on CEL: https://kubernetes.io/docs/reference/using-api/cel/ - - Required. - type: string - name: - description: |- - Name is an identifier for this match condition, used for strategic merging of MatchConditions, - as well as providing an identifier for logging purposes. A good name should be descriptive of - the associated expression. - Name must be a qualified name consisting of alphanumeric characters, '-', '_' or '.', and - must start and end with an alphanumeric character (e.g. 'MyName', or 'my.name', or - '123-abc', regex used for validation is '([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9]') with an - optional DNS subdomain prefix and '/' (e.g. 'example.com/MyName') - - Required. - type: string - required: - - expression - - name - type: object - type: array - timeoutSeconds: - description: |- - TimeoutSeconds specifies the maximum time in seconds allowed to apply this policy. - After the configured time expires, the admission request may fail, or may simply ignore the policy results, - based on the failure policy. The default timeout is 10s, the value must be between 1 and 30 seconds. - format: int32 - type: integer - type: object - webhookTimeoutSeconds: - description: Deprecated, use webhookTimeoutSeconds under webhookConfiguration - instead. - format: int32 - type: integer - type: object - status: - description: Status contains policy runtime data. - properties: - autogen: - description: AutogenStatus contains autogen status information. - properties: - rules: - description: Rules is a list of Rule instances. It contains auto - generated rules added for pod controllers - items: - description: |- - Rule defines a validation, mutation, or generation control for matching resources. - Each rules contains a match declaration to select resources, and an optional exclude - declaration to specify which resources to exclude. - properties: - celPreconditions: - description: |- - CELPreconditions are used to determine if a policy rule should be applied by evaluating a - set of CEL conditions. It can only be used with the validate.cel subrule - items: - description: MatchCondition represents a condition which - must by fulfilled for a request to be sent to a webhook. - properties: - expression: - description: |- - Expression represents the expression which will be evaluated by CEL. Must evaluate to bool. - CEL expressions have access to the contents of the AdmissionRequest and Authorizer, organized into CEL variables: - - 'object' - The object from the incoming request. The value is null for DELETE requests. - 'oldObject' - The existing object. The value is null for CREATE requests. - 'request' - Attributes of the admission request(/pkg/apis/admission/types.go#AdmissionRequest). - 'authorizer' - A CEL Authorizer. May be used to perform authorization checks for the principal (user or service account) of the request. - See https://pkg.go.dev/k8s.io/apiserver/pkg/cel/library#Authz - 'authorizer.requestResource' - A CEL ResourceCheck constructed from the 'authorizer' and configured with the - request resource. - Documentation on CEL: https://kubernetes.io/docs/reference/using-api/cel/ - - Required. - type: string - name: - description: |- - Name is an identifier for this match condition, used for strategic merging of MatchConditions, - as well as providing an identifier for logging purposes. A good name should be descriptive of - the associated expression. - Name must be a qualified name consisting of alphanumeric characters, '-', '_' or '.', and - must start and end with an alphanumeric character (e.g. 'MyName', or 'my.name', or - '123-abc', regex used for validation is '([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9]') with an - optional DNS subdomain prefix and '/' (e.g. 'example.com/MyName') - - Required. - type: string - required: - - expression - - name - type: object - type: array - context: - description: Context defines variables and data sources - that can be used during rule execution. - items: - description: |- - ContextEntry adds variables and data sources to a rule Context. Either a - ConfigMap reference or a APILookup must be provided. - oneOf: - - required: - - configMap - - required: - - apiCall - - required: - - imageRegistry - - required: - - variable - - required: - - globalReference - properties: - apiCall: - description: |- - APICall is an HTTP request to the Kubernetes API server, or other JSON web service. - The data returned is stored in the context with the name for the context entry. - properties: - data: - description: |- - The data object specifies the POST data sent to the server. - Only applicable when the method field is set to POST. - items: - description: RequestData contains the HTTP POST - data - properties: - key: - description: Key is a unique identifier - for the data value - type: string - value: - description: Value is the data value - x-kubernetes-preserve-unknown-fields: true - required: - - key - - value - type: object - type: array - default: - description: |- - Default is an optional arbitrary JSON object that the context - value is set to, if the apiCall returns error. - x-kubernetes-preserve-unknown-fields: true - jmesPath: - description: |- - JMESPath is an optional JSON Match Expression that can be used to - transform the JSON response returned from the server. For example - a JMESPath of "items | length(@)" applied to the API server response - for the URLPath "/apis/apps/v1/deployments" will return the total count - of deployments across all namespaces. - type: string - method: - default: GET - description: Method is the HTTP request type (GET - or POST). Defaults to GET. - enum: - - GET - - POST - type: string - service: - description: |- - Service is an API call to a JSON web service. - This is used for non-Kubernetes API server calls. - It's mutually exclusive with the URLPath field. - properties: - caBundle: - description: |- - CABundle is a PEM encoded CA bundle which will be used to validate - the server certificate. - type: string - headers: - description: Headers is a list of optional - HTTP headers to be included in the request. - items: - properties: - key: - description: Key is the header key - type: string - value: - description: Value is the header value - type: string - required: - - key - - value - type: object - type: array - url: - description: |- - URL is the JSON web service URL. A typical form is - `https://{service}.{namespace}:{port}/{path}`. - type: string - required: - - url - type: object - urlPath: - description: |- - URLPath is the URL path to be used in the HTTP GET or POST request to the - Kubernetes API server (e.g. "/api/v1/namespaces" or "/apis/apps/v1/deployments"). - The format required is the same format used by the `kubectl get --raw` command. - See https://kyverno.io/docs/writing-policies/external-data-sources/#variables-from-kubernetes-api-server-calls - for details. - It's mutually exclusive with the Service field. - type: string - type: object - configMap: - description: ConfigMap is the ConfigMap reference. - properties: - name: - description: Name is the ConfigMap name. - type: string - namespace: - description: Namespace is the ConfigMap namespace. - type: string - required: - - name - type: object - globalReference: - description: GlobalContextEntryReference is a reference - to a cached global context entry. - properties: - jmesPath: - description: |- - JMESPath is an optional JSON Match Expression that can be used to - transform the JSON response returned from the server. For example - a JMESPath of "items | length(@)" applied to the API server response - for the URLPath "/apis/apps/v1/deployments" will return the total count - of deployments across all namespaces. - type: string - name: - description: Name of the global context entry - type: string - required: - - name - type: object - imageRegistry: - description: |- - ImageRegistry defines requests to an OCI/Docker V2 registry to fetch image - details. - properties: - imageRegistryCredentials: - description: ImageRegistryCredentials provides - credentials that will be used for authentication - with registry - properties: - allowInsecureRegistry: - description: AllowInsecureRegistry allows - insecure access to a registry. - type: boolean - providers: - description: |- - Providers specifies a list of OCI Registry names, whose authentication providers are provided. - It can be of one of these values: default,google,azure,amazon,github. - items: - description: ImageRegistryCredentialsProvidersType - provides the list of credential providers - required. - enum: - - default - - amazon - - azure - - google - - github - type: string - type: array - secrets: - description: |- - Secrets specifies a list of secrets that are provided for credentials. - Secrets must live in the Kyverno namespace. - items: - type: string - type: array - type: object - jmesPath: - description: |- - JMESPath is an optional JSON Match Expression that can be used to - transform the ImageData struct returned as a result of processing - the image reference. - type: string - reference: - description: |- - Reference is image reference to a container image in the registry. - Example: ghcr.io/kyverno/kyverno:latest - type: string - required: - - reference - type: object - name: - description: Name is the variable name. - type: string - variable: - description: Variable defines an arbitrary JMESPath - context variable that can be defined inline. - properties: - default: - description: |- - Default is an optional arbitrary JSON object that the variable may take if the JMESPath - expression evaluates to nil - x-kubernetes-preserve-unknown-fields: true - jmesPath: - description: |- - JMESPath is an optional JMESPath Expression that can be used to - transform the variable. - type: string - value: - description: Value is any arbitrary JSON object - representable in YAML or JSON form. - x-kubernetes-preserve-unknown-fields: true - type: object - required: - - name - type: object - type: array - exclude: - description: |- - ExcludeResources defines when this policy rule should not be applied. The exclude - criteria can include resource information (e.g. kind, name, namespace, labels) - and admission review request information like the name or role. - not: - required: - - any - - all - properties: - all: - description: All allows specifying resources which will - be ANDed - items: - description: ResourceFilter allow users to "AND" or - "OR" between resources - properties: - clusterRoles: - description: ClusterRoles is the list of cluster-wide - role names for the user. - items: - type: string - type: array - resources: - description: ResourceDescription contains information - about the resource being created or modified. - not: - required: - - name - - names - properties: - annotations: - additionalProperties: - type: string - description: |- - Annotations is a map of annotations (key-value pairs of type string). Annotation keys - and values support the wildcard characters "*" (matches zero or many characters) and - "?" (matches at least one character). - type: object - kinds: - description: Kinds is a list of resource kinds. - items: - type: string - type: array - name: - description: |- - Name is the name of the resource. The name supports wildcard characters - "*" (matches zero or many characters) and "?" (at least one character). - NOTE: "Name" is being deprecated in favor of "Names". - type: string - names: - description: |- - Names are the names of the resources. Each name supports wildcard characters - "*" (matches zero or many characters) and "?" (at least one character). - items: - type: string - type: array - namespaceSelector: - description: |- - NamespaceSelector is a label selector for the resource namespace. Label keys and values - in `matchLabels` support the wildcard characters `*` (matches zero or many characters) - and `?` (matches one character).Wildcards allows writing label selectors like - ["storage.k8s.io/*": "*"]. Note that using ["*" : "*"] matches any key and value but - does not match an empty label set. - properties: - matchExpressions: - description: matchExpressions is a list - of label selector requirements. The - requirements are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key - that the selector applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - namespaces: - description: |- - Namespaces is a list of namespaces names. Each name supports wildcard characters - "*" (matches zero or many characters) and "?" (at least one character). - items: - type: string - type: array - operations: - description: Operations can contain values - ["CREATE, "UPDATE", "CONNECT", "DELETE"], - which are used to match a specific action. - items: - description: AdmissionOperation can have - one of the values CREATE, UPDATE, CONNECT, - DELETE, which are used to match a specific - action. - enum: - - CREATE - - CONNECT - - UPDATE - - DELETE - type: string - type: array - selector: - description: |- - Selector is a label selector. Label keys and values in `matchLabels` support the wildcard - characters `*` (matches zero or many characters) and `?` (matches one character). - Wildcards allows writing label selectors like ["storage.k8s.io/*": "*"]. Note that - using ["*" : "*"] matches any key and value but does not match an empty label set. - properties: - matchExpressions: - description: matchExpressions is a list - of label selector requirements. The - requirements are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key - that the selector applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - type: object - roles: - description: Roles is the list of namespaced role - names for the user. - items: - type: string - type: array - subjects: - description: Subjects is the list of subject names - like users, user groups, and service accounts. - items: - description: |- - Subject contains a reference to the object or user identities a role binding applies to. This can either hold a direct API object reference, - or a value for non-objects such as user and group names. - properties: - apiGroup: - description: |- - APIGroup holds the API group of the referenced subject. - Defaults to "" for ServiceAccount subjects. - Defaults to "rbac.authorization.k8s.io" for User and Group subjects. - type: string - kind: - description: |- - Kind of object being referenced. Values defined by this API group are "User", "Group", and "ServiceAccount". - If the Authorizer does not recognized the kind value, the Authorizer should report an error. - type: string - name: - description: Name of the object being referenced. - type: string - namespace: - description: |- - Namespace of the referenced object. If the object kind is non-namespace, such as "User" or "Group", and this value is not empty - the Authorizer should report an error. - type: string - required: - - kind - - name - type: object - x-kubernetes-map-type: atomic - type: array - type: object - type: array - any: - description: Any allows specifying resources which will - be ORed - items: - description: ResourceFilter allow users to "AND" or - "OR" between resources - properties: - clusterRoles: - description: ClusterRoles is the list of cluster-wide - role names for the user. - items: - type: string - type: array - resources: - description: ResourceDescription contains information - about the resource being created or modified. - not: - required: - - name - - names - properties: - annotations: - additionalProperties: - type: string - description: |- - Annotations is a map of annotations (key-value pairs of type string). Annotation keys - and values support the wildcard characters "*" (matches zero or many characters) and - "?" (matches at least one character). - type: object - kinds: - description: Kinds is a list of resource kinds. - items: - type: string - type: array - name: - description: |- - Name is the name of the resource. The name supports wildcard characters - "*" (matches zero or many characters) and "?" (at least one character). - NOTE: "Name" is being deprecated in favor of "Names". - type: string - names: - description: |- - Names are the names of the resources. Each name supports wildcard characters - "*" (matches zero or many characters) and "?" (at least one character). - items: - type: string - type: array - namespaceSelector: - description: |- - NamespaceSelector is a label selector for the resource namespace. Label keys and values - in `matchLabels` support the wildcard characters `*` (matches zero or many characters) - and `?` (matches one character).Wildcards allows writing label selectors like - ["storage.k8s.io/*": "*"]. Note that using ["*" : "*"] matches any key and value but - does not match an empty label set. - properties: - matchExpressions: - description: matchExpressions is a list - of label selector requirements. The - requirements are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key - that the selector applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - namespaces: - description: |- - Namespaces is a list of namespaces names. Each name supports wildcard characters - "*" (matches zero or many characters) and "?" (at least one character). - items: - type: string - type: array - operations: - description: Operations can contain values - ["CREATE, "UPDATE", "CONNECT", "DELETE"], - which are used to match a specific action. - items: - description: AdmissionOperation can have - one of the values CREATE, UPDATE, CONNECT, - DELETE, which are used to match a specific - action. - enum: - - CREATE - - CONNECT - - UPDATE - - DELETE - type: string - type: array - selector: - description: |- - Selector is a label selector. Label keys and values in `matchLabels` support the wildcard - characters `*` (matches zero or many characters) and `?` (matches one character). - Wildcards allows writing label selectors like ["storage.k8s.io/*": "*"]. Note that - using ["*" : "*"] matches any key and value but does not match an empty label set. - properties: - matchExpressions: - description: matchExpressions is a list - of label selector requirements. The - requirements are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key - that the selector applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - type: object - roles: - description: Roles is the list of namespaced role - names for the user. - items: - type: string - type: array - subjects: - description: Subjects is the list of subject names - like users, user groups, and service accounts. - items: - description: |- - Subject contains a reference to the object or user identities a role binding applies to. This can either hold a direct API object reference, - or a value for non-objects such as user and group names. - properties: - apiGroup: - description: |- - APIGroup holds the API group of the referenced subject. - Defaults to "" for ServiceAccount subjects. - Defaults to "rbac.authorization.k8s.io" for User and Group subjects. - type: string - kind: - description: |- - Kind of object being referenced. Values defined by this API group are "User", "Group", and "ServiceAccount". - If the Authorizer does not recognized the kind value, the Authorizer should report an error. - type: string - name: - description: Name of the object being referenced. - type: string - namespace: - description: |- - Namespace of the referenced object. If the object kind is non-namespace, such as "User" or "Group", and this value is not empty - the Authorizer should report an error. - type: string - required: - - kind - - name - type: object - x-kubernetes-map-type: atomic - type: array - type: object - type: array - clusterRoles: - description: ClusterRoles is the list of cluster-wide - role names for the user. - items: - type: string - type: array - resources: - description: |- - ResourceDescription contains information about the resource being created or modified. - Requires at least one tag to be specified when under MatchResources. - Specifying ResourceDescription directly under match is being deprecated. - Please specify under "any" or "all" instead. - not: - required: - - name - - names - properties: - annotations: - additionalProperties: - type: string - description: |- - Annotations is a map of annotations (key-value pairs of type string). Annotation keys - and values support the wildcard characters "*" (matches zero or many characters) and - "?" (matches at least one character). - type: object - kinds: - description: Kinds is a list of resource kinds. - items: - type: string - type: array - name: - description: |- - Name is the name of the resource. The name supports wildcard characters - "*" (matches zero or many characters) and "?" (at least one character). - NOTE: "Name" is being deprecated in favor of "Names". - type: string - names: - description: |- - Names are the names of the resources. Each name supports wildcard characters - "*" (matches zero or many characters) and "?" (at least one character). - items: - type: string - type: array - namespaceSelector: - description: |- - NamespaceSelector is a label selector for the resource namespace. Label keys and values - in `matchLabels` support the wildcard characters `*` (matches zero or many characters) - and `?` (matches one character).Wildcards allows writing label selectors like - ["storage.k8s.io/*": "*"]. Note that using ["*" : "*"] matches any key and value but - does not match an empty label set. - properties: - matchExpressions: - description: matchExpressions is a list of label - selector requirements. The requirements are - ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key that - the selector applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - namespaces: - description: |- - Namespaces is a list of namespaces names. Each name supports wildcard characters - "*" (matches zero or many characters) and "?" (at least one character). - items: - type: string - type: array - operations: - description: Operations can contain values ["CREATE, - "UPDATE", "CONNECT", "DELETE"], which are used - to match a specific action. - items: - description: AdmissionOperation can have one of - the values CREATE, UPDATE, CONNECT, DELETE, - which are used to match a specific action. - enum: - - CREATE - - CONNECT - - UPDATE - - DELETE - type: string - type: array - selector: - description: |- - Selector is a label selector. Label keys and values in `matchLabels` support the wildcard - characters `*` (matches zero or many characters) and `?` (matches one character). - Wildcards allows writing label selectors like ["storage.k8s.io/*": "*"]. Note that - using ["*" : "*"] matches any key and value but does not match an empty label set. - properties: - matchExpressions: - description: matchExpressions is a list of label - selector requirements. The requirements are - ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key that - the selector applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - type: object - roles: - description: Roles is the list of namespaced role names - for the user. - items: - type: string - type: array - subjects: - description: Subjects is the list of subject names like - users, user groups, and service accounts. - items: - description: |- - Subject contains a reference to the object or user identities a role binding applies to. This can either hold a direct API object reference, - or a value for non-objects such as user and group names. - properties: - apiGroup: - description: |- - APIGroup holds the API group of the referenced subject. - Defaults to "" for ServiceAccount subjects. - Defaults to "rbac.authorization.k8s.io" for User and Group subjects. - type: string - kind: - description: |- - Kind of object being referenced. Values defined by this API group are "User", "Group", and "ServiceAccount". - If the Authorizer does not recognized the kind value, the Authorizer should report an error. - type: string - name: - description: Name of the object being referenced. - type: string - namespace: - description: |- - Namespace of the referenced object. If the object kind is non-namespace, such as "User" or "Group", and this value is not empty - the Authorizer should report an error. - type: string - required: - - kind - - name - type: object - x-kubernetes-map-type: atomic - type: array - type: object - generate: - description: Generation is used to create new resources. - properties: - apiVersion: - description: APIVersion specifies resource apiVersion. - type: string - clone: - description: |- - Clone specifies the source resource used to populate each generated resource. - At most one of Data or Clone can be specified. If neither are provided, the generated - resource will be created with default data only. - properties: - name: - description: Name specifies name of the resource. - type: string - namespace: - description: Namespace specifies source resource - namespace. - type: string - type: object - cloneList: - description: CloneList specifies the list of source - resource used to populate each generated resource. - properties: - kinds: - description: Kinds is a list of resource kinds. - items: - type: string - type: array - namespace: - description: Namespace specifies source resource - namespace. - type: string - selector: - description: |- - Selector is a label selector. Label keys and values in `matchLabels`. - wildcard characters are not supported. - properties: - matchExpressions: - description: matchExpressions is a list of label - selector requirements. The requirements are - ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key that - the selector applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - type: object - data: - description: |- - Data provides the resource declaration used to populate each generated resource. - At most one of Data or Clone must be specified. If neither are provided, the generated - resource will be created with default data only. - x-kubernetes-preserve-unknown-fields: true - foreach: - description: ForEach applies generate rules to a list - of sub-elements by creating a context for each entry - in the list and looping over it to apply the specified - logic. - items: - properties: - apiVersion: - description: APIVersion specifies resource apiVersion. - type: string - clone: - description: |- - Clone specifies the source resource used to populate each generated resource. - At most one of Data or Clone can be specified. If neither are provided, the generated - resource will be created with default data only. - properties: - name: - description: Name specifies name of the resource. - type: string - namespace: - description: Namespace specifies source resource - namespace. - type: string - type: object - cloneList: - description: CloneList specifies the list of source - resource used to populate each generated resource. - properties: - kinds: - description: Kinds is a list of resource kinds. - items: - type: string - type: array - namespace: - description: Namespace specifies source resource - namespace. - type: string - selector: - description: |- - Selector is a label selector. Label keys and values in `matchLabels`. - wildcard characters are not supported. - properties: - matchExpressions: - description: matchExpressions is a list - of label selector requirements. The - requirements are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key - that the selector applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - type: object - context: - description: Context defines variables and data - sources that can be used during rule execution. - items: - description: |- - ContextEntry adds variables and data sources to a rule Context. Either a - ConfigMap reference or a APILookup must be provided. - oneOf: - - required: - - configMap - - required: - - apiCall - - required: - - imageRegistry - - required: - - variable - - required: - - globalReference - properties: - apiCall: - description: |- - APICall is an HTTP request to the Kubernetes API server, or other JSON web service. - The data returned is stored in the context with the name for the context entry. - properties: - data: - description: |- - The data object specifies the POST data sent to the server. - Only applicable when the method field is set to POST. - items: - description: RequestData contains - the HTTP POST data - properties: - key: - description: Key is a unique identifier - for the data value - type: string - value: - description: Value is the data - value - x-kubernetes-preserve-unknown-fields: true - required: - - key - - value - type: object - type: array - default: - description: |- - Default is an optional arbitrary JSON object that the context - value is set to, if the apiCall returns error. - x-kubernetes-preserve-unknown-fields: true - jmesPath: - description: |- - JMESPath is an optional JSON Match Expression that can be used to - transform the JSON response returned from the server. For example - a JMESPath of "items | length(@)" applied to the API server response - for the URLPath "/apis/apps/v1/deployments" will return the total count - of deployments across all namespaces. - type: string - method: - default: GET - description: Method is the HTTP request - type (GET or POST). Defaults to GET. - enum: - - GET - - POST - type: string - service: - description: |- - Service is an API call to a JSON web service. - This is used for non-Kubernetes API server calls. - It's mutually exclusive with the URLPath field. - properties: - caBundle: - description: |- - CABundle is a PEM encoded CA bundle which will be used to validate - the server certificate. - type: string - headers: - description: Headers is a list of - optional HTTP headers to be included - in the request. - items: - properties: - key: - description: Key is the header - key - type: string - value: - description: Value is the - header value - type: string - required: - - key - - value - type: object - type: array - url: - description: |- - URL is the JSON web service URL. A typical form is - `https://{service}.{namespace}:{port}/{path}`. - type: string - required: - - url - type: object - urlPath: - description: |- - URLPath is the URL path to be used in the HTTP GET or POST request to the - Kubernetes API server (e.g. "/api/v1/namespaces" or "/apis/apps/v1/deployments"). - The format required is the same format used by the `kubectl get --raw` command. - See https://kyverno.io/docs/writing-policies/external-data-sources/#variables-from-kubernetes-api-server-calls - for details. - It's mutually exclusive with the Service field. - type: string - type: object - configMap: - description: ConfigMap is the ConfigMap - reference. - properties: - name: - description: Name is the ConfigMap name. - type: string - namespace: - description: Namespace is the ConfigMap - namespace. - type: string - required: - - name - type: object - globalReference: - description: GlobalContextEntryReference - is a reference to a cached global context - entry. - properties: - jmesPath: - description: |- - JMESPath is an optional JSON Match Expression that can be used to - transform the JSON response returned from the server. For example - a JMESPath of "items | length(@)" applied to the API server response - for the URLPath "/apis/apps/v1/deployments" will return the total count - of deployments across all namespaces. - type: string - name: - description: Name of the global context - entry - type: string - required: - - name - type: object - imageRegistry: - description: |- - ImageRegistry defines requests to an OCI/Docker V2 registry to fetch image - details. - properties: - imageRegistryCredentials: - description: ImageRegistryCredentials - provides credentials that will be - used for authentication with registry - properties: - allowInsecureRegistry: - description: AllowInsecureRegistry - allows insecure access to a registry. - type: boolean - providers: - description: |- - Providers specifies a list of OCI Registry names, whose authentication providers are provided. - It can be of one of these values: default,google,azure,amazon,github. - items: - description: ImageRegistryCredentialsProvidersType - provides the list of credential - providers required. - enum: - - default - - amazon - - azure - - google - - github - type: string - type: array - secrets: - description: |- - Secrets specifies a list of secrets that are provided for credentials. - Secrets must live in the Kyverno namespace. - items: - type: string - type: array - type: object - jmesPath: - description: |- - JMESPath is an optional JSON Match Expression that can be used to - transform the ImageData struct returned as a result of processing - the image reference. - type: string - reference: - description: |- - Reference is image reference to a container image in the registry. - Example: ghcr.io/kyverno/kyverno:latest - type: string - required: - - reference - type: object - name: - description: Name is the variable name. - type: string - variable: - description: Variable defines an arbitrary - JMESPath context variable that can be - defined inline. - properties: - default: - description: |- - Default is an optional arbitrary JSON object that the variable may take if the JMESPath - expression evaluates to nil - x-kubernetes-preserve-unknown-fields: true - jmesPath: - description: |- - JMESPath is an optional JMESPath Expression that can be used to - transform the variable. - type: string - value: - description: Value is any arbitrary - JSON object representable in YAML - or JSON form. - x-kubernetes-preserve-unknown-fields: true - type: object - required: - - name - type: object - type: array - data: - description: |- - Data provides the resource declaration used to populate each generated resource. - At most one of Data or Clone must be specified. If neither are provided, the generated - resource will be created with default data only. - x-kubernetes-preserve-unknown-fields: true - kind: - description: Kind specifies resource kind. - type: string - list: - description: |- - List specifies a JMESPath expression that results in one or more elements - to which the validation logic is applied. - type: string - name: - description: Name specifies the resource name. - type: string - namespace: - description: Namespace specifies resource namespace. - type: string - preconditions: - description: |- - AnyAllConditions are used to determine if a policy rule should be applied by evaluating a - set of conditions. The declaration can contain nested `any` or `all` statements. - See: https://kyverno.io/docs/writing-policies/preconditions/ - properties: - all: - description: |- - AllConditions enable variable-based conditional rule execution. This is useful for - finer control of when an rule is applied. A condition can reference object data - using JMESPath notation. - Here, all of the conditions need to pass - items: - description: Condition defines variable-based - conditional criteria for rule execution. - properties: - key: - description: Key is the context entry - (using JMESPath) for conditional rule - evaluation. - x-kubernetes-preserve-unknown-fields: true - message: - description: Message is an optional - display message - type: string - operator: - description: |- - Operator is the conditional operation to perform. Valid operators are: - Equals, NotEquals, In, AnyIn, AllIn, NotIn, AnyNotIn, AllNotIn, GreaterThanOrEquals, - GreaterThan, LessThanOrEquals, LessThan, DurationGreaterThanOrEquals, DurationGreaterThan, - DurationLessThanOrEquals, DurationLessThan - enum: - - Equals - - NotEquals - - In - - AnyIn - - AllIn - - NotIn - - AnyNotIn - - AllNotIn - - GreaterThanOrEquals - - GreaterThan - - LessThanOrEquals - - LessThan - - DurationGreaterThanOrEquals - - DurationGreaterThan - - DurationLessThanOrEquals - - DurationLessThan - type: string - value: - description: |- - Value is the conditional value, or set of values. The values can be fixed set - or can be variables declared using JMESPath. - x-kubernetes-preserve-unknown-fields: true - type: object - type: array - any: - description: |- - AnyConditions enable variable-based conditional rule execution. This is useful for - finer control of when an rule is applied. A condition can reference object data - using JMESPath notation. - Here, at least one of the conditions need to pass - items: - description: Condition defines variable-based - conditional criteria for rule execution. - properties: - key: - description: Key is the context entry - (using JMESPath) for conditional rule - evaluation. - x-kubernetes-preserve-unknown-fields: true - message: - description: Message is an optional - display message - type: string - operator: - description: |- - Operator is the conditional operation to perform. Valid operators are: - Equals, NotEquals, In, AnyIn, AllIn, NotIn, AnyNotIn, AllNotIn, GreaterThanOrEquals, - GreaterThan, LessThanOrEquals, LessThan, DurationGreaterThanOrEquals, DurationGreaterThan, - DurationLessThanOrEquals, DurationLessThan - enum: - - Equals - - NotEquals - - In - - AnyIn - - AllIn - - NotIn - - AnyNotIn - - AllNotIn - - GreaterThanOrEquals - - GreaterThan - - LessThanOrEquals - - LessThan - - DurationGreaterThanOrEquals - - DurationGreaterThan - - DurationLessThanOrEquals - - DurationLessThan - type: string - value: - description: |- - Value is the conditional value, or set of values. The values can be fixed set - or can be variables declared using JMESPath. - x-kubernetes-preserve-unknown-fields: true - type: object - type: array - type: object - x-kubernetes-preserve-unknown-fields: true - uid: - description: UID specifies the resource uid. - type: string - type: object - type: array - generateExisting: - description: |- - GenerateExisting controls whether to trigger the rule in existing resources - If is set to "true" the rule will be triggered and applied to existing matched resources. - type: boolean - kind: - description: Kind specifies resource kind. - type: string - name: - description: Name specifies the resource name. - type: string - namespace: - description: Namespace specifies resource namespace. - type: string - orphanDownstreamOnPolicyDelete: - description: |- - OrphanDownstreamOnPolicyDelete controls whether generated resources should be deleted when the rule that generated - them is deleted with synchronization enabled. This option is only applicable to generate rules of the data type. - See https://kyverno.io/docs/writing-policies/generate/#data-examples. - Defaults to "false" if not specified. - type: boolean - synchronize: - description: |- - Synchronize controls if generated resources should be kept in-sync with their source resource. - If Synchronize is set to "true" changes to generated resources will be overwritten with resource - data from Data or the resource specified in the Clone declaration. - Optional. Defaults to "false" if not specified. - type: boolean - uid: - description: UID specifies the resource uid. - type: string - type: object - imageExtractors: - additionalProperties: - items: - properties: - jmesPath: - description: |- - JMESPath is an optional JMESPath expression to apply to the image value. - This is useful when the extracted image begins with a prefix like 'docker://'. - The 'trim_prefix' function may be used to trim the prefix: trim_prefix(@, 'docker://'). - Note - Image digest mutation may not be used when applying a JMESPAth to an image. - type: string - key: - description: |- - Key is an optional name of the field within 'path' that will be used to uniquely identify an image. - Note - this field MUST be unique. - type: string - name: - description: |- - Name is the entry the image will be available under 'images.' in the context. - If this field is not defined, image entries will appear under 'images.custom'. - type: string - path: - description: |- - Path is the path to the object containing the image field in a custom resource. - It should be slash-separated. Each slash-separated key must be a valid YAML key or a wildcard '*'. - Wildcard keys are expanded in case of arrays or objects. - type: string - value: - description: |- - Value is an optional name of the field within 'path' that points to the image URI. - This is useful when a custom 'key' is also defined. - type: string - required: - - path - type: object - type: array - description: |- - ImageExtractors defines a mapping from kinds to ImageExtractorConfigs. - This config is only valid for verifyImages rules. - type: object - match: - description: |- - MatchResources defines when this policy rule should be applied. The match - criteria can include resource information (e.g. kind, name, namespace, labels) - and admission review request information like the user name or role. - At least one kind is required. - not: - required: - - any - - all - properties: - all: - description: All allows specifying resources which will - be ANDed - items: - description: ResourceFilter allow users to "AND" or - "OR" between resources - properties: - clusterRoles: - description: ClusterRoles is the list of cluster-wide - role names for the user. - items: - type: string - type: array - resources: - description: ResourceDescription contains information - about the resource being created or modified. - not: - required: - - name - - names - properties: - annotations: - additionalProperties: - type: string - description: |- - Annotations is a map of annotations (key-value pairs of type string). Annotation keys - and values support the wildcard characters "*" (matches zero or many characters) and - "?" (matches at least one character). - type: object - kinds: - description: Kinds is a list of resource kinds. - items: - type: string - type: array - name: - description: |- - Name is the name of the resource. The name supports wildcard characters - "*" (matches zero or many characters) and "?" (at least one character). - NOTE: "Name" is being deprecated in favor of "Names". - type: string - names: - description: |- - Names are the names of the resources. Each name supports wildcard characters - "*" (matches zero or many characters) and "?" (at least one character). - items: - type: string - type: array - namespaceSelector: - description: |- - NamespaceSelector is a label selector for the resource namespace. Label keys and values - in `matchLabels` support the wildcard characters `*` (matches zero or many characters) - and `?` (matches one character).Wildcards allows writing label selectors like - ["storage.k8s.io/*": "*"]. Note that using ["*" : "*"] matches any key and value but - does not match an empty label set. - properties: - matchExpressions: - description: matchExpressions is a list - of label selector requirements. The - requirements are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key - that the selector applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - namespaces: - description: |- - Namespaces is a list of namespaces names. Each name supports wildcard characters - "*" (matches zero or many characters) and "?" (at least one character). - items: - type: string - type: array - operations: - description: Operations can contain values - ["CREATE, "UPDATE", "CONNECT", "DELETE"], - which are used to match a specific action. - items: - description: AdmissionOperation can have - one of the values CREATE, UPDATE, CONNECT, - DELETE, which are used to match a specific - action. - enum: - - CREATE - - CONNECT - - UPDATE - - DELETE - type: string - type: array - selector: - description: |- - Selector is a label selector. Label keys and values in `matchLabels` support the wildcard - characters `*` (matches zero or many characters) and `?` (matches one character). - Wildcards allows writing label selectors like ["storage.k8s.io/*": "*"]. Note that - using ["*" : "*"] matches any key and value but does not match an empty label set. - properties: - matchExpressions: - description: matchExpressions is a list - of label selector requirements. The - requirements are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key - that the selector applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - type: object - roles: - description: Roles is the list of namespaced role - names for the user. - items: - type: string - type: array - subjects: - description: Subjects is the list of subject names - like users, user groups, and service accounts. - items: - description: |- - Subject contains a reference to the object or user identities a role binding applies to. This can either hold a direct API object reference, - or a value for non-objects such as user and group names. - properties: - apiGroup: - description: |- - APIGroup holds the API group of the referenced subject. - Defaults to "" for ServiceAccount subjects. - Defaults to "rbac.authorization.k8s.io" for User and Group subjects. - type: string - kind: - description: |- - Kind of object being referenced. Values defined by this API group are "User", "Group", and "ServiceAccount". - If the Authorizer does not recognized the kind value, the Authorizer should report an error. - type: string - name: - description: Name of the object being referenced. - type: string - namespace: - description: |- - Namespace of the referenced object. If the object kind is non-namespace, such as "User" or "Group", and this value is not empty - the Authorizer should report an error. - type: string - required: - - kind - - name - type: object - x-kubernetes-map-type: atomic - type: array - type: object - type: array - any: - description: Any allows specifying resources which will - be ORed - items: - description: ResourceFilter allow users to "AND" or - "OR" between resources - properties: - clusterRoles: - description: ClusterRoles is the list of cluster-wide - role names for the user. - items: - type: string - type: array - resources: - description: ResourceDescription contains information - about the resource being created or modified. - not: - required: - - name - - names - properties: - annotations: - additionalProperties: - type: string - description: |- - Annotations is a map of annotations (key-value pairs of type string). Annotation keys - and values support the wildcard characters "*" (matches zero or many characters) and - "?" (matches at least one character). - type: object - kinds: - description: Kinds is a list of resource kinds. - items: - type: string - type: array - name: - description: |- - Name is the name of the resource. The name supports wildcard characters - "*" (matches zero or many characters) and "?" (at least one character). - NOTE: "Name" is being deprecated in favor of "Names". - type: string - names: - description: |- - Names are the names of the resources. Each name supports wildcard characters - "*" (matches zero or many characters) and "?" (at least one character). - items: - type: string - type: array - namespaceSelector: - description: |- - NamespaceSelector is a label selector for the resource namespace. Label keys and values - in `matchLabels` support the wildcard characters `*` (matches zero or many characters) - and `?` (matches one character).Wildcards allows writing label selectors like - ["storage.k8s.io/*": "*"]. Note that using ["*" : "*"] matches any key and value but - does not match an empty label set. - properties: - matchExpressions: - description: matchExpressions is a list - of label selector requirements. The - requirements are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key - that the selector applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - namespaces: - description: |- - Namespaces is a list of namespaces names. Each name supports wildcard characters - "*" (matches zero or many characters) and "?" (at least one character). - items: - type: string - type: array - operations: - description: Operations can contain values - ["CREATE, "UPDATE", "CONNECT", "DELETE"], - which are used to match a specific action. - items: - description: AdmissionOperation can have - one of the values CREATE, UPDATE, CONNECT, - DELETE, which are used to match a specific - action. - enum: - - CREATE - - CONNECT - - UPDATE - - DELETE - type: string - type: array - selector: - description: |- - Selector is a label selector. Label keys and values in `matchLabels` support the wildcard - characters `*` (matches zero or many characters) and `?` (matches one character). - Wildcards allows writing label selectors like ["storage.k8s.io/*": "*"]. Note that - using ["*" : "*"] matches any key and value but does not match an empty label set. - properties: - matchExpressions: - description: matchExpressions is a list - of label selector requirements. The - requirements are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key - that the selector applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - type: object - roles: - description: Roles is the list of namespaced role - names for the user. - items: - type: string - type: array - subjects: - description: Subjects is the list of subject names - like users, user groups, and service accounts. - items: - description: |- - Subject contains a reference to the object or user identities a role binding applies to. This can either hold a direct API object reference, - or a value for non-objects such as user and group names. - properties: - apiGroup: - description: |- - APIGroup holds the API group of the referenced subject. - Defaults to "" for ServiceAccount subjects. - Defaults to "rbac.authorization.k8s.io" for User and Group subjects. - type: string - kind: - description: |- - Kind of object being referenced. Values defined by this API group are "User", "Group", and "ServiceAccount". - If the Authorizer does not recognized the kind value, the Authorizer should report an error. - type: string - name: - description: Name of the object being referenced. - type: string - namespace: - description: |- - Namespace of the referenced object. If the object kind is non-namespace, such as "User" or "Group", and this value is not empty - the Authorizer should report an error. - type: string - required: - - kind - - name - type: object - x-kubernetes-map-type: atomic - type: array - type: object - type: array - clusterRoles: - description: ClusterRoles is the list of cluster-wide - role names for the user. - items: - type: string - type: array - resources: - description: |- - ResourceDescription contains information about the resource being created or modified. - Requires at least one tag to be specified when under MatchResources. - Specifying ResourceDescription directly under match is being deprecated. - Please specify under "any" or "all" instead. - not: - required: - - name - - names - properties: - annotations: - additionalProperties: - type: string - description: |- - Annotations is a map of annotations (key-value pairs of type string). Annotation keys - and values support the wildcard characters "*" (matches zero or many characters) and - "?" (matches at least one character). - type: object - kinds: - description: Kinds is a list of resource kinds. - items: - type: string - type: array - name: - description: |- - Name is the name of the resource. The name supports wildcard characters - "*" (matches zero or many characters) and "?" (at least one character). - NOTE: "Name" is being deprecated in favor of "Names". - type: string - names: - description: |- - Names are the names of the resources. Each name supports wildcard characters - "*" (matches zero or many characters) and "?" (at least one character). - items: - type: string - type: array - namespaceSelector: - description: |- - NamespaceSelector is a label selector for the resource namespace. Label keys and values - in `matchLabels` support the wildcard characters `*` (matches zero or many characters) - and `?` (matches one character).Wildcards allows writing label selectors like - ["storage.k8s.io/*": "*"]. Note that using ["*" : "*"] matches any key and value but - does not match an empty label set. - properties: - matchExpressions: - description: matchExpressions is a list of label - selector requirements. The requirements are - ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key that - the selector applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - namespaces: - description: |- - Namespaces is a list of namespaces names. Each name supports wildcard characters - "*" (matches zero or many characters) and "?" (at least one character). - items: - type: string - type: array - operations: - description: Operations can contain values ["CREATE, - "UPDATE", "CONNECT", "DELETE"], which are used - to match a specific action. - items: - description: AdmissionOperation can have one of - the values CREATE, UPDATE, CONNECT, DELETE, - which are used to match a specific action. - enum: - - CREATE - - CONNECT - - UPDATE - - DELETE - type: string - type: array - selector: - description: |- - Selector is a label selector. Label keys and values in `matchLabels` support the wildcard - characters `*` (matches zero or many characters) and `?` (matches one character). - Wildcards allows writing label selectors like ["storage.k8s.io/*": "*"]. Note that - using ["*" : "*"] matches any key and value but does not match an empty label set. - properties: - matchExpressions: - description: matchExpressions is a list of label - selector requirements. The requirements are - ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key that - the selector applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - type: object - roles: - description: Roles is the list of namespaced role names - for the user. - items: - type: string - type: array - subjects: - description: Subjects is the list of subject names like - users, user groups, and service accounts. - items: - description: |- - Subject contains a reference to the object or user identities a role binding applies to. This can either hold a direct API object reference, - or a value for non-objects such as user and group names. - properties: - apiGroup: - description: |- - APIGroup holds the API group of the referenced subject. - Defaults to "" for ServiceAccount subjects. - Defaults to "rbac.authorization.k8s.io" for User and Group subjects. - type: string - kind: - description: |- - Kind of object being referenced. Values defined by this API group are "User", "Group", and "ServiceAccount". - If the Authorizer does not recognized the kind value, the Authorizer should report an error. - type: string - name: - description: Name of the object being referenced. - type: string - namespace: - description: |- - Namespace of the referenced object. If the object kind is non-namespace, such as "User" or "Group", and this value is not empty - the Authorizer should report an error. - type: string - required: - - kind - - name - type: object - x-kubernetes-map-type: atomic - type: array - type: object - mutate: - description: Mutation is used to modify matching resources. - properties: - foreach: - description: ForEach applies mutation rules to a list - of sub-elements by creating a context for each entry - in the list and looping over it to apply the specified - logic. - items: - description: ForEachMutation applies mutation rules - to a list of sub-elements by creating a context - for each entry in the list and looping over it to - apply the specified logic. - properties: - context: - description: Context defines variables and data - sources that can be used during rule execution. - items: - description: |- - ContextEntry adds variables and data sources to a rule Context. Either a - ConfigMap reference or a APILookup must be provided. - oneOf: - - required: - - configMap - - required: - - apiCall - - required: - - imageRegistry - - required: - - variable - - required: - - globalReference - properties: - apiCall: - description: |- - APICall is an HTTP request to the Kubernetes API server, or other JSON web service. - The data returned is stored in the context with the name for the context entry. - properties: - data: - description: |- - The data object specifies the POST data sent to the server. - Only applicable when the method field is set to POST. - items: - description: RequestData contains - the HTTP POST data - properties: - key: - description: Key is a unique identifier - for the data value - type: string - value: - description: Value is the data - value - x-kubernetes-preserve-unknown-fields: true - required: - - key - - value - type: object - type: array - default: - description: |- - Default is an optional arbitrary JSON object that the context - value is set to, if the apiCall returns error. - x-kubernetes-preserve-unknown-fields: true - jmesPath: - description: |- - JMESPath is an optional JSON Match Expression that can be used to - transform the JSON response returned from the server. For example - a JMESPath of "items | length(@)" applied to the API server response - for the URLPath "/apis/apps/v1/deployments" will return the total count - of deployments across all namespaces. - type: string - method: - default: GET - description: Method is the HTTP request - type (GET or POST). Defaults to GET. - enum: - - GET - - POST - type: string - service: - description: |- - Service is an API call to a JSON web service. - This is used for non-Kubernetes API server calls. - It's mutually exclusive with the URLPath field. - properties: - caBundle: - description: |- - CABundle is a PEM encoded CA bundle which will be used to validate - the server certificate. - type: string - headers: - description: Headers is a list of - optional HTTP headers to be included - in the request. - items: - properties: - key: - description: Key is the header - key - type: string - value: - description: Value is the - header value - type: string - required: - - key - - value - type: object - type: array - url: - description: |- - URL is the JSON web service URL. A typical form is - `https://{service}.{namespace}:{port}/{path}`. - type: string - required: - - url - type: object - urlPath: - description: |- - URLPath is the URL path to be used in the HTTP GET or POST request to the - Kubernetes API server (e.g. "/api/v1/namespaces" or "/apis/apps/v1/deployments"). - The format required is the same format used by the `kubectl get --raw` command. - See https://kyverno.io/docs/writing-policies/external-data-sources/#variables-from-kubernetes-api-server-calls - for details. - It's mutually exclusive with the Service field. - type: string - type: object - configMap: - description: ConfigMap is the ConfigMap - reference. - properties: - name: - description: Name is the ConfigMap name. - type: string - namespace: - description: Namespace is the ConfigMap - namespace. - type: string - required: - - name - type: object - globalReference: - description: GlobalContextEntryReference - is a reference to a cached global context - entry. - properties: - jmesPath: - description: |- - JMESPath is an optional JSON Match Expression that can be used to - transform the JSON response returned from the server. For example - a JMESPath of "items | length(@)" applied to the API server response - for the URLPath "/apis/apps/v1/deployments" will return the total count - of deployments across all namespaces. - type: string - name: - description: Name of the global context - entry - type: string - required: - - name - type: object - imageRegistry: - description: |- - ImageRegistry defines requests to an OCI/Docker V2 registry to fetch image - details. - properties: - imageRegistryCredentials: - description: ImageRegistryCredentials - provides credentials that will be - used for authentication with registry - properties: - allowInsecureRegistry: - description: AllowInsecureRegistry - allows insecure access to a registry. - type: boolean - providers: - description: |- - Providers specifies a list of OCI Registry names, whose authentication providers are provided. - It can be of one of these values: default,google,azure,amazon,github. - items: - description: ImageRegistryCredentialsProvidersType - provides the list of credential - providers required. - enum: - - default - - amazon - - azure - - google - - github - type: string - type: array - secrets: - description: |- - Secrets specifies a list of secrets that are provided for credentials. - Secrets must live in the Kyverno namespace. - items: - type: string - type: array - type: object - jmesPath: - description: |- - JMESPath is an optional JSON Match Expression that can be used to - transform the ImageData struct returned as a result of processing - the image reference. - type: string - reference: - description: |- - Reference is image reference to a container image in the registry. - Example: ghcr.io/kyverno/kyverno:latest - type: string - required: - - reference - type: object - name: - description: Name is the variable name. - type: string - variable: - description: Variable defines an arbitrary - JMESPath context variable that can be - defined inline. - properties: - default: - description: |- - Default is an optional arbitrary JSON object that the variable may take if the JMESPath - expression evaluates to nil - x-kubernetes-preserve-unknown-fields: true - jmesPath: - description: |- - JMESPath is an optional JMESPath Expression that can be used to - transform the variable. - type: string - value: - description: Value is any arbitrary - JSON object representable in YAML - or JSON form. - x-kubernetes-preserve-unknown-fields: true - type: object - required: - - name - type: object - type: array - foreach: - description: Foreach declares a nested foreach - iterator - x-kubernetes-preserve-unknown-fields: true - list: - description: |- - List specifies a JMESPath expression that results in one or more elements - to which the validation logic is applied. - type: string - order: - description: |- - Order defines the iteration order on the list. - Can be Ascending to iterate from first to last element or Descending to iterate in from last to first element. - enum: - - Ascending - - Descending - type: string - patchStrategicMerge: - description: |- - PatchStrategicMerge is a strategic merge patch used to modify resources. - See https://kubernetes.io/docs/tasks/manage-kubernetes-objects/update-api-object-kubectl-patch/ - and https://kubectl.docs.kubernetes.io/references/kustomize/kustomization/patchesstrategicmerge/. - x-kubernetes-preserve-unknown-fields: true - patchesJson6902: - description: |- - PatchesJSON6902 is a list of RFC 6902 JSON Patch declarations used to modify resources. - See https://tools.ietf.org/html/rfc6902 and https://kubectl.docs.kubernetes.io/references/kustomize/kustomization/patchesjson6902/. - type: string - preconditions: - description: |- - AnyAllConditions are used to determine if a policy rule should be applied by evaluating a - set of conditions. The declaration can contain nested `any` or `all` statements. - See: https://kyverno.io/docs/writing-policies/preconditions/ - properties: - all: - description: |- - AllConditions enable variable-based conditional rule execution. This is useful for - finer control of when an rule is applied. A condition can reference object data - using JMESPath notation. - Here, all of the conditions need to pass - items: - description: Condition defines variable-based - conditional criteria for rule execution. - properties: - key: - description: Key is the context entry - (using JMESPath) for conditional rule - evaluation. - x-kubernetes-preserve-unknown-fields: true - message: - description: Message is an optional - display message - type: string - operator: - description: |- - Operator is the conditional operation to perform. Valid operators are: - Equals, NotEquals, In, AnyIn, AllIn, NotIn, AnyNotIn, AllNotIn, GreaterThanOrEquals, - GreaterThan, LessThanOrEquals, LessThan, DurationGreaterThanOrEquals, DurationGreaterThan, - DurationLessThanOrEquals, DurationLessThan - enum: - - Equals - - NotEquals - - In - - AnyIn - - AllIn - - NotIn - - AnyNotIn - - AllNotIn - - GreaterThanOrEquals - - GreaterThan - - LessThanOrEquals - - LessThan - - DurationGreaterThanOrEquals - - DurationGreaterThan - - DurationLessThanOrEquals - - DurationLessThan - type: string - value: - description: |- - Value is the conditional value, or set of values. The values can be fixed set - or can be variables declared using JMESPath. - x-kubernetes-preserve-unknown-fields: true - type: object - type: array - any: - description: |- - AnyConditions enable variable-based conditional rule execution. This is useful for - finer control of when an rule is applied. A condition can reference object data - using JMESPath notation. - Here, at least one of the conditions need to pass - items: - description: Condition defines variable-based - conditional criteria for rule execution. - properties: - key: - description: Key is the context entry - (using JMESPath) for conditional rule - evaluation. - x-kubernetes-preserve-unknown-fields: true - message: - description: Message is an optional - display message - type: string - operator: - description: |- - Operator is the conditional operation to perform. Valid operators are: - Equals, NotEquals, In, AnyIn, AllIn, NotIn, AnyNotIn, AllNotIn, GreaterThanOrEquals, - GreaterThan, LessThanOrEquals, LessThan, DurationGreaterThanOrEquals, DurationGreaterThan, - DurationLessThanOrEquals, DurationLessThan - enum: - - Equals - - NotEquals - - In - - AnyIn - - AllIn - - NotIn - - AnyNotIn - - AllNotIn - - GreaterThanOrEquals - - GreaterThan - - LessThanOrEquals - - LessThan - - DurationGreaterThanOrEquals - - DurationGreaterThan - - DurationLessThanOrEquals - - DurationLessThan - type: string - value: - description: |- - Value is the conditional value, or set of values. The values can be fixed set - or can be variables declared using JMESPath. - x-kubernetes-preserve-unknown-fields: true - type: object - type: array - type: object - x-kubernetes-preserve-unknown-fields: true - type: object - type: array - mutateExistingOnPolicyUpdate: - description: MutateExistingOnPolicyUpdate controls if - the mutateExisting rule will be applied on policy - events. - type: boolean - patchStrategicMerge: - description: |- - PatchStrategicMerge is a strategic merge patch used to modify resources. - See https://kubernetes.io/docs/tasks/manage-kubernetes-objects/update-api-object-kubectl-patch/ - and https://kubectl.docs.kubernetes.io/references/kustomize/kustomization/patchesstrategicmerge/. - x-kubernetes-preserve-unknown-fields: true - patchesJson6902: - description: |- - PatchesJSON6902 is a list of RFC 6902 JSON Patch declarations used to modify resources. - See https://tools.ietf.org/html/rfc6902 and https://kubectl.docs.kubernetes.io/references/kustomize/kustomization/patchesjson6902/. - type: string - targets: - description: Targets defines the target resources to - be mutated. - items: - description: TargetResourceSpec defines targets for - mutating existing resources. - properties: - apiVersion: - description: APIVersion specifies resource apiVersion. - type: string - context: - description: Context defines variables and data - sources that can be used during rule execution. - items: - description: |- - ContextEntry adds variables and data sources to a rule Context. Either a - ConfigMap reference or a APILookup must be provided. - oneOf: - - required: - - configMap - - required: - - apiCall - - required: - - imageRegistry - - required: - - variable - - required: - - globalReference - properties: - apiCall: - description: |- - APICall is an HTTP request to the Kubernetes API server, or other JSON web service. - The data returned is stored in the context with the name for the context entry. - properties: - data: - description: |- - The data object specifies the POST data sent to the server. - Only applicable when the method field is set to POST. - items: - description: RequestData contains - the HTTP POST data - properties: - key: - description: Key is a unique identifier - for the data value - type: string - value: - description: Value is the data - value - x-kubernetes-preserve-unknown-fields: true - required: - - key - - value - type: object - type: array - default: - description: |- - Default is an optional arbitrary JSON object that the context - value is set to, if the apiCall returns error. - x-kubernetes-preserve-unknown-fields: true - jmesPath: - description: |- - JMESPath is an optional JSON Match Expression that can be used to - transform the JSON response returned from the server. For example - a JMESPath of "items | length(@)" applied to the API server response - for the URLPath "/apis/apps/v1/deployments" will return the total count - of deployments across all namespaces. - type: string - method: - default: GET - description: Method is the HTTP request - type (GET or POST). Defaults to GET. - enum: - - GET - - POST - type: string - service: - description: |- - Service is an API call to a JSON web service. - This is used for non-Kubernetes API server calls. - It's mutually exclusive with the URLPath field. - properties: - caBundle: - description: |- - CABundle is a PEM encoded CA bundle which will be used to validate - the server certificate. - type: string - headers: - description: Headers is a list of - optional HTTP headers to be included - in the request. - items: - properties: - key: - description: Key is the header - key - type: string - value: - description: Value is the - header value - type: string - required: - - key - - value - type: object - type: array - url: - description: |- - URL is the JSON web service URL. A typical form is - `https://{service}.{namespace}:{port}/{path}`. - type: string - required: - - url - type: object - urlPath: - description: |- - URLPath is the URL path to be used in the HTTP GET or POST request to the - Kubernetes API server (e.g. "/api/v1/namespaces" or "/apis/apps/v1/deployments"). - The format required is the same format used by the `kubectl get --raw` command. - See https://kyverno.io/docs/writing-policies/external-data-sources/#variables-from-kubernetes-api-server-calls - for details. - It's mutually exclusive with the Service field. - type: string - type: object - configMap: - description: ConfigMap is the ConfigMap - reference. - properties: - name: - description: Name is the ConfigMap name. - type: string - namespace: - description: Namespace is the ConfigMap - namespace. - type: string - required: - - name - type: object - globalReference: - description: GlobalContextEntryReference - is a reference to a cached global context - entry. - properties: - jmesPath: - description: |- - JMESPath is an optional JSON Match Expression that can be used to - transform the JSON response returned from the server. For example - a JMESPath of "items | length(@)" applied to the API server response - for the URLPath "/apis/apps/v1/deployments" will return the total count - of deployments across all namespaces. - type: string - name: - description: Name of the global context - entry - type: string - required: - - name - type: object - imageRegistry: - description: |- - ImageRegistry defines requests to an OCI/Docker V2 registry to fetch image - details. - properties: - imageRegistryCredentials: - description: ImageRegistryCredentials - provides credentials that will be - used for authentication with registry - properties: - allowInsecureRegistry: - description: AllowInsecureRegistry - allows insecure access to a registry. - type: boolean - providers: - description: |- - Providers specifies a list of OCI Registry names, whose authentication providers are provided. - It can be of one of these values: default,google,azure,amazon,github. - items: - description: ImageRegistryCredentialsProvidersType - provides the list of credential - providers required. - enum: - - default - - amazon - - azure - - google - - github - type: string - type: array - secrets: - description: |- - Secrets specifies a list of secrets that are provided for credentials. - Secrets must live in the Kyverno namespace. - items: - type: string - type: array - type: object - jmesPath: - description: |- - JMESPath is an optional JSON Match Expression that can be used to - transform the ImageData struct returned as a result of processing - the image reference. - type: string - reference: - description: |- - Reference is image reference to a container image in the registry. - Example: ghcr.io/kyverno/kyverno:latest - type: string - required: - - reference - type: object - name: - description: Name is the variable name. - type: string - variable: - description: Variable defines an arbitrary - JMESPath context variable that can be - defined inline. - properties: - default: - description: |- - Default is an optional arbitrary JSON object that the variable may take if the JMESPath - expression evaluates to nil - x-kubernetes-preserve-unknown-fields: true - jmesPath: - description: |- - JMESPath is an optional JMESPath Expression that can be used to - transform the variable. - type: string - value: - description: Value is any arbitrary - JSON object representable in YAML - or JSON form. - x-kubernetes-preserve-unknown-fields: true - type: object - required: - - name - type: object - type: array - kind: - description: Kind specifies resource kind. - type: string - name: - description: Name specifies the resource name. - type: string - namespace: - description: Namespace specifies resource namespace. - type: string - preconditions: - description: |- - Preconditions are used to determine if a policy rule should be applied by evaluating a - set of conditions. The declaration can contain nested `any` or `all` statements. A direct list - of conditions (without `any` or `all` statements is supported for backwards compatibility but - will be deprecated in the next major release. - See: https://kyverno.io/docs/writing-policies/preconditions/ - x-kubernetes-preserve-unknown-fields: true - selector: - description: Selector allows you to select target - resources with their labels. - properties: - matchExpressions: - description: matchExpressions is a list of - label selector requirements. The requirements - are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key that - the selector applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - uid: - description: UID specifies the resource uid. - type: string - type: object - type: array - type: object - name: - description: Name is a label to identify the rule, It must - be unique within the policy. - maxLength: 63 - type: string - preconditions: - description: |- - Preconditions are used to determine if a policy rule should be applied by evaluating a - set of conditions. The declaration can contain nested `any` or `all` statements. A direct list - of conditions (without `any` or `all` statements is supported for backwards compatibility but - will be deprecated in the next major release. - See: https://kyverno.io/docs/writing-policies/preconditions/ - x-kubernetes-preserve-unknown-fields: true - reportProperties: - additionalProperties: - type: string - description: ReportProperties are the additional properties - from the rule that will be added to the policy report - result - type: object - skipBackgroundRequests: - default: true - description: |- - SkipBackgroundRequests bypasses admission requests that are sent by the background controller. - The default value is set to "true", it must be set to "false" to apply - generate and mutateExisting rules to those requests. - type: boolean - validate: - description: Validation is used to validate matching resources. - properties: - allowExistingViolations: - default: true - description: AllowExistingViolations allows prexisting - violating resources to continue violating a policy. - type: boolean - anyPattern: - description: |- - AnyPattern specifies list of validation patterns. At least one of the patterns - must be satisfied for the validation rule to succeed. - x-kubernetes-preserve-unknown-fields: true - assert: - description: Assert defines a kyverno-json assertion - tree. - type: object - x-kubernetes-preserve-unknown-fields: true - cel: - description: CEL allows validation checks using the - Common Expression Language (https://kubernetes.io/docs/reference/using-api/cel/). - properties: - auditAnnotations: - description: AuditAnnotations contains CEL expressions - which are used to produce audit annotations for - the audit event of the API request. - items: - description: AuditAnnotation describes how to - produce an audit annotation for an API request. - properties: - key: - description: |- - key specifies the audit annotation key. The audit annotation keys of - a ValidatingAdmissionPolicy must be unique. The key must be a qualified - name ([A-Za-z0-9][-A-Za-z0-9_.]*) no more than 63 bytes in length. - - The key is combined with the resource name of the - ValidatingAdmissionPolicy to construct an audit annotation key: - "{ValidatingAdmissionPolicy name}/{key}". - - If an admission webhook uses the same resource name as this ValidatingAdmissionPolicy - and the same audit annotation key, the annotation key will be identical. - In this case, the first annotation written with the key will be included - in the audit event and all subsequent annotations with the same key - will be discarded. - - Required. - type: string - valueExpression: - description: |- - valueExpression represents the expression which is evaluated by CEL to - produce an audit annotation value. The expression must evaluate to either - a string or null value. If the expression evaluates to a string, the - audit annotation is included with the string value. If the expression - evaluates to null or empty string the audit annotation will be omitted. - The valueExpression may be no longer than 5kb in length. - If the result of the valueExpression is more than 10kb in length, it - will be truncated to 10kb. - - If multiple ValidatingAdmissionPolicyBinding resources match an - API request, then the valueExpression will be evaluated for - each binding. All unique values produced by the valueExpressions - will be joined together in a comma-separated list. - - Required. - type: string - required: - - key - - valueExpression - type: object - type: array - expressions: - description: Expressions is a list of CELExpression - types. - items: - description: Validation specifies the CEL expression - which is used to apply the validation. - properties: - expression: - description: "Expression represents the expression - which will be evaluated by CEL.\nref: https://github.com/google/cel-spec\nCEL - expressions have access to the contents - of the API request/response, organized into - CEL variables as well as some other useful - variables:\n\n- 'object' - The object from - the incoming request. The value is null - for DELETE requests.\n- 'oldObject' - The - existing object. The value is null for CREATE - requests.\n- 'request' - Attributes of the - API request([ref](/pkg/apis/admission/types.go#AdmissionRequest)).\n- - 'params' - Parameter resource referred to - by the policy binding being evaluated. Only - populated if the policy has a ParamKind.\n- - 'namespaceObject' - The namespace object - that the incoming object belongs to. The - value is null for cluster-scoped resources.\n- - 'variables' - Map of composited variables, - from its name to its lazily evaluated value.\n - \ For example, a variable named 'foo' can - be accessed as 'variables.foo'.\n- 'authorizer' - - A CEL Authorizer. May be used to perform - authorization checks for the principal (user - or service account) of the request.\n See - https://pkg.go.dev/k8s.io/apiserver/pkg/cel/library#Authz\n- - 'authorizer.requestResource' - A CEL ResourceCheck - constructed from the 'authorizer' and configured - with the\n request resource.\n\nThe `apiVersion`, - `kind`, `metadata.name` and `metadata.generateName` - are always accessible from the root of the\nobject. - No other metadata properties are accessible.\n\nOnly - property names of the form `[a-zA-Z_.-/][a-zA-Z0-9_.-/]*` - are accessible.\nAccessible property names - are escaped according to the following rules - when accessed in the expression:\n- '__' - escapes to '__underscores__'\n- '.' escapes - to '__dot__'\n- '-' escapes to '__dash__'\n- - '/' escapes to '__slash__'\n- Property names - that exactly match a CEL RESERVED keyword - escape to '__{keyword}__'. The keywords - are:\n\t \"true\", \"false\", \"null\", - \"in\", \"as\", \"break\", \"const\", \"continue\", - \"else\", \"for\", \"function\", \"if\",\n\t - \ \"import\", \"let\", \"loop\", \"package\", - \"namespace\", \"return\".\nExamples:\n - \ - Expression accessing a property named - \"namespace\": {\"Expression\": \"object.__namespace__ - > 0\"}\n - Expression accessing a property - named \"x-prop\": {\"Expression\": \"object.x__dash__prop - > 0\"}\n - Expression accessing a property - named \"redact__d\": {\"Expression\": \"object.redact__underscores__d - > 0\"}\n\nEquality on arrays with list type - of 'set' or 'map' ignores element order, - i.e. [1, 2] == [2, 1].\nConcatenation on - arrays with x-kubernetes-list-type use the - semantics of the list type:\n - 'set': - `X + Y` performs a union where the array - positions of all elements in `X` are preserved - and\n non-intersecting elements in `Y` - are appended, retaining their partial order.\n - \ - 'map': `X + Y` performs a merge where - the array positions of all keys in `X` are - preserved but the values\n are overwritten - by values in `Y` when the key sets of `X` - and `Y` intersect. Elements in `Y` with\n - \ non-intersecting keys are appended, - retaining their partial order.\nRequired." - type: string - message: - description: |- - Message represents the message displayed when validation fails. The message is required if the Expression contains - line breaks. The message must not contain line breaks. - If unset, the message is "failed rule: {Rule}". - e.g. "must be a URL with the host matching spec.host" - If the Expression contains line breaks. Message is required. - The message must not contain line breaks. - If unset, the message is "failed Expression: {Expression}". - type: string - messageExpression: - description: |- - messageExpression declares a CEL expression that evaluates to the validation failure message that is returned when this rule fails. - Since messageExpression is used as a failure message, it must evaluate to a string. - If both message and messageExpression are present on a validation, then messageExpression will be used if validation fails. - If messageExpression results in a runtime error, the runtime error is logged, and the validation failure message is produced - as if the messageExpression field were unset. If messageExpression evaluates to an empty string, a string with only spaces, or a string - that contains line breaks, then the validation failure message will also be produced as if the messageExpression field were unset, and - the fact that messageExpression produced an empty string/string with only spaces/string with line breaks will be logged. - messageExpression has access to all the same variables as the `expression` except for 'authorizer' and 'authorizer.requestResource'. - Example: - "object.x must be less than max ("+string(params.max)+")" - type: string - reason: - description: |- - Reason represents a machine-readable description of why this validation failed. - If this is the first validation in the list to fail, this reason, as well as the - corresponding HTTP response code, are used in the - HTTP response to the client. - The currently supported reasons are: "Unauthorized", "Forbidden", "Invalid", "RequestEntityTooLarge". - If not set, StatusReasonInvalid is used in the response to the client. - type: string - required: - - expression - type: object - type: array - generate: - default: false - description: |- - Generate specifies whether to generate a Kubernetes ValidatingAdmissionPolicy from the rule. - Optional. Defaults to "false" if not specified. - type: boolean - paramKind: - description: ParamKind is a tuple of Group Kind - and Version. - properties: - apiVersion: - description: |- - APIVersion is the API group version the resources belong to. - In format of "group/version". - Required. - type: string - kind: - description: |- - Kind is the API kind the resources belong to. - Required. - type: string - type: object - x-kubernetes-map-type: atomic - paramRef: - description: ParamRef references a parameter resource. - properties: - name: - description: |- - name is the name of the resource being referenced. - - One of `name` or `selector` must be set, but `name` and `selector` are - mutually exclusive properties. If one is set, the other must be unset. - - A single parameter used for all admission requests can be configured - by setting the `name` field, leaving `selector` blank, and setting namespace - if `paramKind` is namespace-scoped. - type: string - namespace: - description: |- - namespace is the namespace of the referenced resource. Allows limiting - the search for params to a specific namespace. Applies to both `name` and - `selector` fields. - - A per-namespace parameter may be used by specifying a namespace-scoped - `paramKind` in the policy and leaving this field empty. - - - If `paramKind` is cluster-scoped, this field MUST be unset. Setting this - field results in a configuration error. - - - If `paramKind` is namespace-scoped, the namespace of the object being - evaluated for admission will be used when this field is left unset. Take - care that if this is left empty the binding must not match any cluster-scoped - resources, which will result in an error. - type: string - parameterNotFoundAction: - description: |- - `parameterNotFoundAction` controls the behavior of the binding when the resource - exists, and name or selector is valid, but there are no parameters - matched by the binding. If the value is set to `Allow`, then no - matched parameters will be treated as successful validation by the binding. - If set to `Deny`, then no matched parameters will be subject to the - `failurePolicy` of the policy. - - Allowed values are `Allow` or `Deny` - - Required - type: string - selector: - description: |- - selector can be used to match multiple param objects based on their labels. - Supply selector: {} to match all resources of the ParamKind. - - If multiple params are found, they are all evaluated with the policy expressions - and the results are ANDed together. - - One of `name` or `selector` must be set, but `name` and `selector` are - mutually exclusive properties. If one is set, the other must be unset. - properties: - matchExpressions: - description: matchExpressions is a list - of label selector requirements. The requirements - are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key - that the selector applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - type: object - x-kubernetes-map-type: atomic - variables: - description: |- - Variables contain definitions of variables that can be used in composition of other expressions. - Each variable is defined as a named CEL expression. - The variables defined here will be available under `variables` in other expressions of the policy. - items: - description: Variable is the definition of a variable - that is used for composition. A variable is - defined as a named expression. - properties: - expression: - description: |- - Expression is the expression that will be evaluated as the value of the variable. - The CEL expression has access to the same identifiers as the CEL expressions in Validation. - type: string - name: - description: |- - Name is the name of the variable. The name must be a valid CEL identifier and unique among all variables. - The variable can be accessed in other expressions through `variables` - For example, if name is "foo", the variable will be available as `variables.foo` - type: string - required: - - expression - - name - type: object - x-kubernetes-map-type: atomic - type: array - type: object - deny: - description: Deny defines conditions used to pass or - fail a validation rule. - properties: - conditions: - description: |- - Multiple conditions can be declared under an `any` or `all` statement. A direct list - of conditions (without `any` or `all` statements) is also supported for backwards compatibility - but will be deprecated in the next major release. - See: https://kyverno.io/docs/writing-policies/validate/#deny-rules - x-kubernetes-preserve-unknown-fields: true - type: object - failureAction: - description: |- - FailureAction defines if a validation policy rule violation should block - the admission review request (Enforce), or allow (Audit) the admission review request - and report an error in a policy report. Optional. - Allowed values are Audit or Enforce. - enum: - - Audit - - Enforce - type: string - failureActionOverrides: - description: |- - FailureActionOverrides is a Cluster Policy attribute that specifies FailureAction - namespace-wise. It overrides FailureAction for the specified namespaces. - items: - properties: - action: - description: ValidationFailureAction defines the - policy validation failure action - enum: - - audit - - enforce - - Audit - - Enforce - type: string - namespaceSelector: - description: |- - A label selector is a label query over a set of resources. The result of matchLabels and - matchExpressions are ANDed. An empty label selector matches all objects. A null - label selector matches no objects. - properties: - matchExpressions: - description: matchExpressions is a list of - label selector requirements. The requirements - are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key that - the selector applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - namespaces: - items: - type: string - type: array - type: object - type: array - foreach: - description: ForEach applies validate rules to a list - of sub-elements by creating a context for each entry - in the list and looping over it to apply the specified - logic. - items: - description: ForEachValidation applies validate rules - to a list of sub-elements by creating a context - for each entry in the list and looping over it to - apply the specified logic. - properties: - anyPattern: - description: |- - AnyPattern specifies list of validation patterns. At least one of the patterns - must be satisfied for the validation rule to succeed. - x-kubernetes-preserve-unknown-fields: true - context: - description: Context defines variables and data - sources that can be used during rule execution. - items: - description: |- - ContextEntry adds variables and data sources to a rule Context. Either a - ConfigMap reference or a APILookup must be provided. - oneOf: - - required: - - configMap - - required: - - apiCall - - required: - - imageRegistry - - required: - - variable - - required: - - globalReference - properties: - apiCall: - description: |- - APICall is an HTTP request to the Kubernetes API server, or other JSON web service. - The data returned is stored in the context with the name for the context entry. - properties: - data: - description: |- - The data object specifies the POST data sent to the server. - Only applicable when the method field is set to POST. - items: - description: RequestData contains - the HTTP POST data - properties: - key: - description: Key is a unique identifier - for the data value - type: string - value: - description: Value is the data - value - x-kubernetes-preserve-unknown-fields: true - required: - - key - - value - type: object - type: array - default: - description: |- - Default is an optional arbitrary JSON object that the context - value is set to, if the apiCall returns error. - x-kubernetes-preserve-unknown-fields: true - jmesPath: - description: |- - JMESPath is an optional JSON Match Expression that can be used to - transform the JSON response returned from the server. For example - a JMESPath of "items | length(@)" applied to the API server response - for the URLPath "/apis/apps/v1/deployments" will return the total count - of deployments across all namespaces. - type: string - method: - default: GET - description: Method is the HTTP request - type (GET or POST). Defaults to GET. - enum: - - GET - - POST - type: string - service: - description: |- - Service is an API call to a JSON web service. - This is used for non-Kubernetes API server calls. - It's mutually exclusive with the URLPath field. - properties: - caBundle: - description: |- - CABundle is a PEM encoded CA bundle which will be used to validate - the server certificate. - type: string - headers: - description: Headers is a list of - optional HTTP headers to be included - in the request. - items: - properties: - key: - description: Key is the header - key - type: string - value: - description: Value is the - header value - type: string - required: - - key - - value - type: object - type: array - url: - description: |- - URL is the JSON web service URL. A typical form is - `https://{service}.{namespace}:{port}/{path}`. - type: string - required: - - url - type: object - urlPath: - description: |- - URLPath is the URL path to be used in the HTTP GET or POST request to the - Kubernetes API server (e.g. "/api/v1/namespaces" or "/apis/apps/v1/deployments"). - The format required is the same format used by the `kubectl get --raw` command. - See https://kyverno.io/docs/writing-policies/external-data-sources/#variables-from-kubernetes-api-server-calls - for details. - It's mutually exclusive with the Service field. - type: string - type: object - configMap: - description: ConfigMap is the ConfigMap - reference. - properties: - name: - description: Name is the ConfigMap name. - type: string - namespace: - description: Namespace is the ConfigMap - namespace. - type: string - required: - - name - type: object - globalReference: - description: GlobalContextEntryReference - is a reference to a cached global context - entry. - properties: - jmesPath: - description: |- - JMESPath is an optional JSON Match Expression that can be used to - transform the JSON response returned from the server. For example - a JMESPath of "items | length(@)" applied to the API server response - for the URLPath "/apis/apps/v1/deployments" will return the total count - of deployments across all namespaces. - type: string - name: - description: Name of the global context - entry - type: string - required: - - name - type: object - imageRegistry: - description: |- - ImageRegistry defines requests to an OCI/Docker V2 registry to fetch image - details. - properties: - imageRegistryCredentials: - description: ImageRegistryCredentials - provides credentials that will be - used for authentication with registry - properties: - allowInsecureRegistry: - description: AllowInsecureRegistry - allows insecure access to a registry. - type: boolean - providers: - description: |- - Providers specifies a list of OCI Registry names, whose authentication providers are provided. - It can be of one of these values: default,google,azure,amazon,github. - items: - description: ImageRegistryCredentialsProvidersType - provides the list of credential - providers required. - enum: - - default - - amazon - - azure - - google - - github - type: string - type: array - secrets: - description: |- - Secrets specifies a list of secrets that are provided for credentials. - Secrets must live in the Kyverno namespace. - items: - type: string - type: array - type: object - jmesPath: - description: |- - JMESPath is an optional JSON Match Expression that can be used to - transform the ImageData struct returned as a result of processing - the image reference. - type: string - reference: - description: |- - Reference is image reference to a container image in the registry. - Example: ghcr.io/kyverno/kyverno:latest - type: string - required: - - reference - type: object - name: - description: Name is the variable name. - type: string - variable: - description: Variable defines an arbitrary - JMESPath context variable that can be - defined inline. - properties: - default: - description: |- - Default is an optional arbitrary JSON object that the variable may take if the JMESPath - expression evaluates to nil - x-kubernetes-preserve-unknown-fields: true - jmesPath: - description: |- - JMESPath is an optional JMESPath Expression that can be used to - transform the variable. - type: string - value: - description: Value is any arbitrary - JSON object representable in YAML - or JSON form. - x-kubernetes-preserve-unknown-fields: true - type: object - required: - - name - type: object - type: array - deny: - description: Deny defines conditions used to pass - or fail a validation rule. - properties: - conditions: - description: |- - Multiple conditions can be declared under an `any` or `all` statement. A direct list - of conditions (without `any` or `all` statements) is also supported for backwards compatibility - but will be deprecated in the next major release. - See: https://kyverno.io/docs/writing-policies/validate/#deny-rules - x-kubernetes-preserve-unknown-fields: true - type: object - elementScope: - description: |- - ElementScope specifies whether to use the current list element as the scope for validation. Defaults to "true" if not specified. - When set to "false", "request.object" is used as the validation scope within the foreach - block to allow referencing other elements in the subtree. - type: boolean - foreach: - description: Foreach declares a nested foreach - iterator - x-kubernetes-preserve-unknown-fields: true - list: - description: |- - List specifies a JMESPath expression that results in one or more elements - to which the validation logic is applied. - type: string - pattern: - description: Pattern specifies an overlay-style - pattern used to check resources. - x-kubernetes-preserve-unknown-fields: true - preconditions: - description: |- - AnyAllConditions are used to determine if a policy rule should be applied by evaluating a - set of conditions. The declaration can contain nested `any` or `all` statements. - See: https://kyverno.io/docs/writing-policies/preconditions/ - properties: - all: - description: |- - AllConditions enable variable-based conditional rule execution. This is useful for - finer control of when an rule is applied. A condition can reference object data - using JMESPath notation. - Here, all of the conditions need to pass - items: - description: Condition defines variable-based - conditional criteria for rule execution. - properties: - key: - description: Key is the context entry - (using JMESPath) for conditional rule - evaluation. - x-kubernetes-preserve-unknown-fields: true - message: - description: Message is an optional - display message - type: string - operator: - description: |- - Operator is the conditional operation to perform. Valid operators are: - Equals, NotEquals, In, AnyIn, AllIn, NotIn, AnyNotIn, AllNotIn, GreaterThanOrEquals, - GreaterThan, LessThanOrEquals, LessThan, DurationGreaterThanOrEquals, DurationGreaterThan, - DurationLessThanOrEquals, DurationLessThan - enum: - - Equals - - NotEquals - - In - - AnyIn - - AllIn - - NotIn - - AnyNotIn - - AllNotIn - - GreaterThanOrEquals - - GreaterThan - - LessThanOrEquals - - LessThan - - DurationGreaterThanOrEquals - - DurationGreaterThan - - DurationLessThanOrEquals - - DurationLessThan - type: string - value: - description: |- - Value is the conditional value, or set of values. The values can be fixed set - or can be variables declared using JMESPath. - x-kubernetes-preserve-unknown-fields: true - type: object - type: array - any: - description: |- - AnyConditions enable variable-based conditional rule execution. This is useful for - finer control of when an rule is applied. A condition can reference object data - using JMESPath notation. - Here, at least one of the conditions need to pass - items: - description: Condition defines variable-based - conditional criteria for rule execution. - properties: - key: - description: Key is the context entry - (using JMESPath) for conditional rule - evaluation. - x-kubernetes-preserve-unknown-fields: true - message: - description: Message is an optional - display message - type: string - operator: - description: |- - Operator is the conditional operation to perform. Valid operators are: - Equals, NotEquals, In, AnyIn, AllIn, NotIn, AnyNotIn, AllNotIn, GreaterThanOrEquals, - GreaterThan, LessThanOrEquals, LessThan, DurationGreaterThanOrEquals, DurationGreaterThan, - DurationLessThanOrEquals, DurationLessThan - enum: - - Equals - - NotEquals - - In - - AnyIn - - AllIn - - NotIn - - AnyNotIn - - AllNotIn - - GreaterThanOrEquals - - GreaterThan - - LessThanOrEquals - - LessThan - - DurationGreaterThanOrEquals - - DurationGreaterThan - - DurationLessThanOrEquals - - DurationLessThan - type: string - value: - description: |- - Value is the conditional value, or set of values. The values can be fixed set - or can be variables declared using JMESPath. - x-kubernetes-preserve-unknown-fields: true - type: object - type: array - type: object - x-kubernetes-preserve-unknown-fields: true - type: object - type: array - manifests: - description: Manifest specifies conditions for manifest - verification - properties: - annotationDomain: - description: AnnotationDomain is custom domain of - annotation for message and signature. Default - is "cosign.sigstore.dev". - type: string - attestors: - description: Attestors specified the required attestors - (i.e. authorities) - items: - properties: - count: - description: |- - Count specifies the required number of entries that must match. If the count is null, all entries must match - (a logical AND). If the count is 1, at least one entry must match (a logical OR). If the count contains a - value N, then N must be less than or equal to the size of entries, and at least N entries must match. - minimum: 1 - type: integer - entries: - description: |- - Entries contains the available attestors. An attestor can be a static key, - attributes for keyless verification, or a nested attestor declaration. - items: - properties: - annotations: - additionalProperties: - type: string - description: |- - Annotations are used for image verification. - Every specified key-value pair must exist and match in the verified payload. - The payload may contain other key-value pairs. - type: object - attestor: - description: Attestor is a nested set - of Attestor used to specify a more - complex set of match authorities. - x-kubernetes-preserve-unknown-fields: true - certificates: - description: Certificates specifies - one or more certificates. - properties: - cert: - description: Cert is an optional - PEM-encoded public certificate. - type: string - certChain: - description: CertChain is an optional - PEM encoded set of certificates - used to verify. - type: string - ctlog: - description: |- - CTLog (certificate timestamp log) provides a configuration for validation of Signed Certificate - Timestamps (SCTs). If the value is unset, the default behavior by Cosign is used. - properties: - ignoreSCT: - description: |- - IgnoreSCT defines whether to use the Signed Certificate Timestamp (SCT) log to check for a certificate - timestamp. Default is false. Set to true if this was opted out during signing. - type: boolean - pubkey: - description: PubKey, if set, - is used to validate SCTs against - a custom source. - type: string - tsaCertChain: - description: |- - TSACertChain, if set, is the PEM-encoded certificate chain file for the RFC3161 timestamp authority. Must - contain the root CA certificate. Optionally may contain intermediate CA certificates, and - may contain the leaf TSA certificate if not present in the timestamurce. - type: string - type: object - rekor: - description: |- - Rekor provides configuration for the Rekor transparency log service. If an empty object - is provided the public instance of Rekor (https://rekor.sigstore.dev) is used. - properties: - ignoreTlog: - description: IgnoreTlog skips - transparency log verification. - type: boolean - pubkey: - description: |- - RekorPubKey is an optional PEM-encoded public key to use for a custom Rekor. - If set, this will be used to validate transparency log signatures from a custom Rekor. - type: string - url: - description: URL is the address - of the transparency log. Defaults - to the public Rekor log instance - https://rekor.sigstore.dev. - type: string - type: object - type: object - keyless: - description: |- - Keyless is a set of attribute used to verify a Sigstore keyless attestor. - See https://github.com/sigstore/cosign/blob/main/KEYLESS.md. - properties: - additionalExtensions: - additionalProperties: - type: string - description: AdditionalExtensions - are certificate-extensions used - for keyless signing. - type: object - ctlog: - description: |- - CTLog (certificate timestamp log) provides a configuration for validation of Signed Certificate - Timestamps (SCTs). If the value is unset, the default behavior by Cosign is used. - properties: - ignoreSCT: - description: |- - IgnoreSCT defines whether to use the Signed Certificate Timestamp (SCT) log to check for a certificate - timestamp. Default is false. Set to true if this was opted out during signing. - type: boolean - pubkey: - description: PubKey, if set, - is used to validate SCTs against - a custom source. - type: string - tsaCertChain: - description: |- - TSACertChain, if set, is the PEM-encoded certificate chain file for the RFC3161 timestamp authority. Must - contain the root CA certificate. Optionally may contain intermediate CA certificates, and - may contain the leaf TSA certificate if not present in the timestamurce. - type: string - type: object - issuer: - description: Issuer is the certificate - issuer used for keyless signing. - type: string - issuerRegExp: - description: IssuerRegExp is the - regular expression to match certificate - issuer used for keyless signing. - type: string - rekor: - description: |- - Rekor provides configuration for the Rekor transparency log service. If an empty object - is provided the public instance of Rekor (https://rekor.sigstore.dev) is used. - properties: - ignoreTlog: - description: IgnoreTlog skips - transparency log verification. - type: boolean - pubkey: - description: |- - RekorPubKey is an optional PEM-encoded public key to use for a custom Rekor. - If set, this will be used to validate transparency log signatures from a custom Rekor. - type: string - url: - description: URL is the address - of the transparency log. Defaults - to the public Rekor log instance - https://rekor.sigstore.dev. - type: string - type: object - roots: - description: |- - Roots is an optional set of PEM encoded trusted root certificates. - If not provided, the system roots are used. - type: string - subject: - description: Subject is the verified - identity used for keyless signing, - for example the email address. - type: string - subjectRegExp: - description: SubjectRegExp is the - regular expression to match identity - used for keyless signing, for - example the email address. - type: string - type: object - keys: - description: Keys specifies one or more - public keys. - properties: - ctlog: - description: |- - CTLog (certificate timestamp log) provides a configuration for validation of Signed Certificate - Timestamps (SCTs). If the value is unset, the default behavior by Cosign is used. - properties: - ignoreSCT: - description: |- - IgnoreSCT defines whether to use the Signed Certificate Timestamp (SCT) log to check for a certificate - timestamp. Default is false. Set to true if this was opted out during signing. - type: boolean - pubkey: - description: PubKey, if set, - is used to validate SCTs against - a custom source. - type: string - tsaCertChain: - description: |- - TSACertChain, if set, is the PEM-encoded certificate chain file for the RFC3161 timestamp authority. Must - contain the root CA certificate. Optionally may contain intermediate CA certificates, and - may contain the leaf TSA certificate if not present in the timestamurce. - type: string - type: object - kms: - description: |- - KMS provides the URI to the public key stored in a Key Management System. See: - https://github.com/sigstore/cosign/blob/main/KMS.md - type: string - publicKeys: - description: |- - Keys is a set of X.509 public keys used to verify image signatures. The keys can be directly - specified or can be a variable reference to a key specified in a ConfigMap (see - https://kyverno.io/docs/writing-policies/variables/), or reference a standard Kubernetes Secret - elsewhere in the cluster by specifying it in the format "k8s:///". - The named Secret must specify a key `cosign.pub` containing the public key used for - verification, (see https://github.com/sigstore/cosign/blob/main/KMS.md#kubernetes-secret). - When multiple keys are specified each key is processed as a separate staticKey entry - (.attestors[*].entries.keys) within the set of attestors and the count is applied across the keys. - type: string - rekor: - description: |- - Rekor provides configuration for the Rekor transparency log service. If an empty object - is provided the public instance of Rekor (https://rekor.sigstore.dev) is used. - properties: - ignoreTlog: - description: IgnoreTlog skips - transparency log verification. - type: boolean - pubkey: - description: |- - RekorPubKey is an optional PEM-encoded public key to use for a custom Rekor. - If set, this will be used to validate transparency log signatures from a custom Rekor. - type: string - url: - description: URL is the address - of the transparency log. Defaults - to the public Rekor log instance - https://rekor.sigstore.dev. - type: string - type: object - secret: - description: Reference to a Secret - resource that contains a public - key - properties: - name: - description: Name of the secret. - The provided secret must contain - a key named cosign.pub. - type: string - namespace: - description: Namespace name - where the Secret exists. - type: string - required: - - name - - namespace - type: object - signatureAlgorithm: - default: sha256 - description: Deprecated. Use attestor.signatureAlgorithm - instead. - type: string - type: object - repository: - description: |- - Repository is an optional alternate OCI repository to use for signatures and attestations that match this rule. - If specified Repository will override other OCI image repository locations for this Attestor. - type: string - signatureAlgorithm: - default: sha256 - description: Specify signature algorithm - for public keys. Supported values - are sha224, sha256, sha384 and sha512. - type: string - type: object - type: array - type: object - type: array - dryRun: - description: DryRun configuration - properties: - enable: - type: boolean - namespace: - type: string - type: object - ignoreFields: - description: Fields which will be ignored while - comparing manifests. - items: - properties: - fields: - items: - type: string - type: array - objects: - items: - properties: - group: - type: string - kind: - type: string - name: - type: string - namespace: - type: string - version: - type: string - type: object - type: array - type: object - type: array - repository: - description: |- - Repository is an optional alternate OCI repository to use for resource bundle reference. - The repository can be overridden per Attestor or Attestation. - type: string - type: object - message: - description: Message specifies a custom message to be - displayed on failure. - type: string - pattern: - description: Pattern specifies an overlay-style pattern - used to check resources. - x-kubernetes-preserve-unknown-fields: true - podSecurity: - description: |- - PodSecurity applies exemptions for Kubernetes Pod Security admission - by specifying exclusions for Pod Security Standards controls. - properties: - exclude: - description: Exclude specifies the Pod Security - Standard controls to be excluded. - items: - description: PodSecurityStandard specifies the - Pod Security Standard controls to be excluded. - properties: - controlName: - description: |- - ControlName specifies the name of the Pod Security Standard control. - See: https://kubernetes.io/docs/concepts/security/pod-security-standards/ - enum: - - HostProcess - - Host Namespaces - - Privileged Containers - - Capabilities - - HostPath Volumes - - Host Ports - - AppArmor - - SELinux - - /proc Mount Type - - Seccomp - - Sysctls - - Volume Types - - Privilege Escalation - - Running as Non-root - - Running as Non-root user - type: string - images: - description: |- - Images selects matching containers and applies the container level PSS. - Each image is the image name consisting of the registry address, repository, image, and tag. - Empty list matches no containers, PSS checks are applied at the pod level only. - Wildcards ('*' and '?') are allowed. See: https://kubernetes.io/docs/concepts/containers/images. - items: - type: string - type: array - restrictedField: - description: |- - RestrictedField selects the field for the given Pod Security Standard control. - When not set, all restricted fields for the control are selected. - type: string - values: - description: Values defines the allowed values - that can be excluded. - items: - type: string - type: array - required: - - controlName - type: object - type: array - level: - description: |- - Level defines the Pod Security Standard level to be applied to workloads. - Allowed values are privileged, baseline, and restricted. - enum: - - privileged - - baseline - - restricted - type: string - version: - description: |- - Version defines the Pod Security Standard versions that Kubernetes supports. - Allowed values are v1.19, v1.20, v1.21, v1.22, v1.23, v1.24, v1.25, v1.26, v1.27, v1.28, v1.29, latest. Defaults to latest. - enum: - - v1.19 - - v1.20 - - v1.21 - - v1.22 - - v1.23 - - v1.24 - - v1.25 - - v1.26 - - v1.27 - - v1.28 - - v1.29 - - latest - type: string - type: object - type: object - verifyImages: - description: VerifyImages is used to verify image signatures - and mutate them to add a digest - items: - description: |- - ImageVerification validates that images that match the specified pattern - are signed with the supplied public key. Once the image is verified it is - mutated to include the SHA digest retrieved during the registration. - properties: - additionalExtensions: - additionalProperties: - type: string - description: Deprecated. - type: object - annotations: - additionalProperties: - type: string - description: Deprecated. Use annotations per Attestor - instead. - type: object - attestations: - description: |- - Attestations are optional checks for signed in-toto Statements used to verify the image. - See https://github.com/in-toto/attestation. Kyverno fetches signed attestations from the - OCI registry and decodes them into a list of Statement declarations. - items: - description: |- - Attestation are checks for signed in-toto Statements that are used to verify the image. - See https://github.com/in-toto/attestation. Kyverno fetches signed attestations from the - OCI registry and decodes them into a list of Statements. - properties: - attestors: - description: Attestors specify the required - attestors (i.e. authorities). - items: - properties: - count: - description: |- - Count specifies the required number of entries that must match. If the count is null, all entries must match - (a logical AND). If the count is 1, at least one entry must match (a logical OR). If the count contains a - value N, then N must be less than or equal to the size of entries, and at least N entries must match. - minimum: 1 - type: integer - entries: - description: |- - Entries contains the available attestors. An attestor can be a static key, - attributes for keyless verification, or a nested attestor declaration. - items: - properties: - annotations: - additionalProperties: - type: string - description: |- - Annotations are used for image verification. - Every specified key-value pair must exist and match in the verified payload. - The payload may contain other key-value pairs. - type: object - attestor: - description: Attestor is a nested - set of Attestor used to specify - a more complex set of match authorities. - x-kubernetes-preserve-unknown-fields: true - certificates: - description: Certificates specifies - one or more certificates. - properties: - cert: - description: Cert is an optional - PEM-encoded public certificate. - type: string - certChain: - description: CertChain is an - optional PEM encoded set of - certificates used to verify. - type: string - ctlog: - description: |- - CTLog (certificate timestamp log) provides a configuration for validation of Signed Certificate - Timestamps (SCTs). If the value is unset, the default behavior by Cosign is used. - properties: - ignoreSCT: - description: |- - IgnoreSCT defines whether to use the Signed Certificate Timestamp (SCT) log to check for a certificate - timestamp. Default is false. Set to true if this was opted out during signing. - type: boolean - pubkey: - description: PubKey, if - set, is used to validate - SCTs against a custom - source. - type: string - tsaCertChain: - description: |- - TSACertChain, if set, is the PEM-encoded certificate chain file for the RFC3161 timestamp authority. Must - contain the root CA certificate. Optionally may contain intermediate CA certificates, and - may contain the leaf TSA certificate if not present in the timestamurce. - type: string - type: object - rekor: - description: |- - Rekor provides configuration for the Rekor transparency log service. If an empty object - is provided the public instance of Rekor (https://rekor.sigstore.dev) is used. - properties: - ignoreTlog: - description: IgnoreTlog - skips transparency log - verification. - type: boolean - pubkey: - description: |- - RekorPubKey is an optional PEM-encoded public key to use for a custom Rekor. - If set, this will be used to validate transparency log signatures from a custom Rekor. - type: string - url: - description: URL is the - address of the transparency - log. Defaults to the public - Rekor log instance https://rekor.sigstore.dev. - type: string - type: object - type: object - keyless: - description: |- - Keyless is a set of attribute used to verify a Sigstore keyless attestor. - See https://github.com/sigstore/cosign/blob/main/KEYLESS.md. - properties: - additionalExtensions: - additionalProperties: - type: string - description: AdditionalExtensions - are certificate-extensions - used for keyless signing. - type: object - ctlog: - description: |- - CTLog (certificate timestamp log) provides a configuration for validation of Signed Certificate - Timestamps (SCTs). If the value is unset, the default behavior by Cosign is used. - properties: - ignoreSCT: - description: |- - IgnoreSCT defines whether to use the Signed Certificate Timestamp (SCT) log to check for a certificate - timestamp. Default is false. Set to true if this was opted out during signing. - type: boolean - pubkey: - description: PubKey, if - set, is used to validate - SCTs against a custom - source. - type: string - tsaCertChain: - description: |- - TSACertChain, if set, is the PEM-encoded certificate chain file for the RFC3161 timestamp authority. Must - contain the root CA certificate. Optionally may contain intermediate CA certificates, and - may contain the leaf TSA certificate if not present in the timestamurce. - type: string - type: object - issuer: - description: Issuer is the certificate - issuer used for keyless signing. - type: string - issuerRegExp: - description: IssuerRegExp is - the regular expression to - match certificate issuer used - for keyless signing. - type: string - rekor: - description: |- - Rekor provides configuration for the Rekor transparency log service. If an empty object - is provided the public instance of Rekor (https://rekor.sigstore.dev) is used. - properties: - ignoreTlog: - description: IgnoreTlog - skips transparency log - verification. - type: boolean - pubkey: - description: |- - RekorPubKey is an optional PEM-encoded public key to use for a custom Rekor. - If set, this will be used to validate transparency log signatures from a custom Rekor. - type: string - url: - description: URL is the - address of the transparency - log. Defaults to the public - Rekor log instance https://rekor.sigstore.dev. - type: string - type: object - roots: - description: |- - Roots is an optional set of PEM encoded trusted root certificates. - If not provided, the system roots are used. - type: string - subject: - description: Subject is the - verified identity used for - keyless signing, for example - the email address. - type: string - subjectRegExp: - description: SubjectRegExp is - the regular expression to - match identity used for keyless - signing, for example the email - address. - type: string - type: object - keys: - description: Keys specifies one - or more public keys. - properties: - ctlog: - description: |- - CTLog (certificate timestamp log) provides a configuration for validation of Signed Certificate - Timestamps (SCTs). If the value is unset, the default behavior by Cosign is used. - properties: - ignoreSCT: - description: |- - IgnoreSCT defines whether to use the Signed Certificate Timestamp (SCT) log to check for a certificate - timestamp. Default is false. Set to true if this was opted out during signing. - type: boolean - pubkey: - description: PubKey, if - set, is used to validate - SCTs against a custom - source. - type: string - tsaCertChain: - description: |- - TSACertChain, if set, is the PEM-encoded certificate chain file for the RFC3161 timestamp authority. Must - contain the root CA certificate. Optionally may contain intermediate CA certificates, and - may contain the leaf TSA certificate if not present in the timestamurce. - type: string - type: object - kms: - description: |- - KMS provides the URI to the public key stored in a Key Management System. See: - https://github.com/sigstore/cosign/blob/main/KMS.md - type: string - publicKeys: - description: |- - Keys is a set of X.509 public keys used to verify image signatures. The keys can be directly - specified or can be a variable reference to a key specified in a ConfigMap (see - https://kyverno.io/docs/writing-policies/variables/), or reference a standard Kubernetes Secret - elsewhere in the cluster by specifying it in the format "k8s:///". - The named Secret must specify a key `cosign.pub` containing the public key used for - verification, (see https://github.com/sigstore/cosign/blob/main/KMS.md#kubernetes-secret). - When multiple keys are specified each key is processed as a separate staticKey entry - (.attestors[*].entries.keys) within the set of attestors and the count is applied across the keys. - type: string - rekor: - description: |- - Rekor provides configuration for the Rekor transparency log service. If an empty object - is provided the public instance of Rekor (https://rekor.sigstore.dev) is used. - properties: - ignoreTlog: - description: IgnoreTlog - skips transparency log - verification. - type: boolean - pubkey: - description: |- - RekorPubKey is an optional PEM-encoded public key to use for a custom Rekor. - If set, this will be used to validate transparency log signatures from a custom Rekor. - type: string - url: - description: URL is the - address of the transparency - log. Defaults to the public - Rekor log instance https://rekor.sigstore.dev. - type: string - type: object - secret: - description: Reference to a - Secret resource that contains - a public key - properties: - name: - description: Name of the - secret. The provided secret - must contain a key named - cosign.pub. - type: string - namespace: - description: Namespace name - where the Secret exists. - type: string - required: - - name - - namespace - type: object - signatureAlgorithm: - default: sha256 - description: Deprecated. Use - attestor.signatureAlgorithm - instead. - type: string - type: object - repository: - description: |- - Repository is an optional alternate OCI repository to use for signatures and attestations that match this rule. - If specified Repository will override other OCI image repository locations for this Attestor. - type: string - signatureAlgorithm: - default: sha256 - description: Specify signature algorithm - for public keys. Supported values - are sha224, sha256, sha384 and - sha512. - type: string - type: object - type: array - type: object - type: array - conditions: - description: |- - Conditions are used to verify attributes within a Predicate. If no Conditions are specified - the attestation check is satisfied as long there are predicates that match the predicate type. - items: - description: |- - AnyAllConditions consists of conditions wrapped denoting a logical criteria to be fulfilled. - AnyConditions get fulfilled when at least one of its sub-conditions passes. - AllConditions get fulfilled only when all of its sub-conditions pass. - properties: - all: - description: |- - AllConditions enable variable-based conditional rule execution. This is useful for - finer control of when an rule is applied. A condition can reference object data - using JMESPath notation. - Here, all of the conditions need to pass - items: - description: Condition defines variable-based - conditional criteria for rule execution. - properties: - key: - description: Key is the context - entry (using JMESPath) for conditional - rule evaluation. - x-kubernetes-preserve-unknown-fields: true - message: - description: Message is an optional - display message - type: string - operator: - description: |- - Operator is the conditional operation to perform. Valid operators are: - Equals, NotEquals, In, AnyIn, AllIn, NotIn, AnyNotIn, AllNotIn, GreaterThanOrEquals, - GreaterThan, LessThanOrEquals, LessThan, DurationGreaterThanOrEquals, DurationGreaterThan, - DurationLessThanOrEquals, DurationLessThan - enum: - - Equals - - NotEquals - - In - - AnyIn - - AllIn - - NotIn - - AnyNotIn - - AllNotIn - - GreaterThanOrEquals - - GreaterThan - - LessThanOrEquals - - LessThan - - DurationGreaterThanOrEquals - - DurationGreaterThan - - DurationLessThanOrEquals - - DurationLessThan - type: string - value: - description: |- - Value is the conditional value, or set of values. The values can be fixed set - or can be variables declared using JMESPath. - x-kubernetes-preserve-unknown-fields: true - type: object - type: array - any: - description: |- - AnyConditions enable variable-based conditional rule execution. This is useful for - finer control of when an rule is applied. A condition can reference object data - using JMESPath notation. - Here, at least one of the conditions need to pass - items: - description: Condition defines variable-based - conditional criteria for rule execution. - properties: - key: - description: Key is the context - entry (using JMESPath) for conditional - rule evaluation. - x-kubernetes-preserve-unknown-fields: true - message: - description: Message is an optional - display message - type: string - operator: - description: |- - Operator is the conditional operation to perform. Valid operators are: - Equals, NotEquals, In, AnyIn, AllIn, NotIn, AnyNotIn, AllNotIn, GreaterThanOrEquals, - GreaterThan, LessThanOrEquals, LessThan, DurationGreaterThanOrEquals, DurationGreaterThan, - DurationLessThanOrEquals, DurationLessThan - enum: - - Equals - - NotEquals - - In - - AnyIn - - AllIn - - NotIn - - AnyNotIn - - AllNotIn - - GreaterThanOrEquals - - GreaterThan - - LessThanOrEquals - - LessThan - - DurationGreaterThanOrEquals - - DurationGreaterThan - - DurationLessThanOrEquals - - DurationLessThan - type: string - value: - description: |- - Value is the conditional value, or set of values. The values can be fixed set - or can be variables declared using JMESPath. - x-kubernetes-preserve-unknown-fields: true - type: object - type: array - type: object - type: array - name: - description: Name is the variable name. - type: string - predicateType: - description: Deprecated in favour of 'Type', - to be removed soon - type: string - type: - description: Type defines the type of attestation - contained within the Statement. - type: string - type: object - type: array - attestors: - description: Attestors specified the required attestors - (i.e. authorities) - items: - properties: - count: - description: |- - Count specifies the required number of entries that must match. If the count is null, all entries must match - (a logical AND). If the count is 1, at least one entry must match (a logical OR). If the count contains a - value N, then N must be less than or equal to the size of entries, and at least N entries must match. - minimum: 1 - type: integer - entries: - description: |- - Entries contains the available attestors. An attestor can be a static key, - attributes for keyless verification, or a nested attestor declaration. - items: - properties: - annotations: - additionalProperties: - type: string - description: |- - Annotations are used for image verification. - Every specified key-value pair must exist and match in the verified payload. - The payload may contain other key-value pairs. - type: object - attestor: - description: Attestor is a nested set - of Attestor used to specify a more complex - set of match authorities. - x-kubernetes-preserve-unknown-fields: true - certificates: - description: Certificates specifies one - or more certificates. - properties: - cert: - description: Cert is an optional PEM-encoded - public certificate. - type: string - certChain: - description: CertChain is an optional - PEM encoded set of certificates - used to verify. - type: string - ctlog: - description: |- - CTLog (certificate timestamp log) provides a configuration for validation of Signed Certificate - Timestamps (SCTs). If the value is unset, the default behavior by Cosign is used. - properties: - ignoreSCT: - description: |- - IgnoreSCT defines whether to use the Signed Certificate Timestamp (SCT) log to check for a certificate - timestamp. Default is false. Set to true if this was opted out during signing. - type: boolean - pubkey: - description: PubKey, if set, is - used to validate SCTs against - a custom source. - type: string - tsaCertChain: - description: |- - TSACertChain, if set, is the PEM-encoded certificate chain file for the RFC3161 timestamp authority. Must - contain the root CA certificate. Optionally may contain intermediate CA certificates, and - may contain the leaf TSA certificate if not present in the timestamurce. - type: string - type: object - rekor: - description: |- - Rekor provides configuration for the Rekor transparency log service. If an empty object - is provided the public instance of Rekor (https://rekor.sigstore.dev) is used. - properties: - ignoreTlog: - description: IgnoreTlog skips - transparency log verification. - type: boolean - pubkey: - description: |- - RekorPubKey is an optional PEM-encoded public key to use for a custom Rekor. - If set, this will be used to validate transparency log signatures from a custom Rekor. - type: string - url: - description: URL is the address - of the transparency log. Defaults - to the public Rekor log instance - https://rekor.sigstore.dev. - type: string - type: object - type: object - keyless: - description: |- - Keyless is a set of attribute used to verify a Sigstore keyless attestor. - See https://github.com/sigstore/cosign/blob/main/KEYLESS.md. - properties: - additionalExtensions: - additionalProperties: - type: string - description: AdditionalExtensions - are certificate-extensions used - for keyless signing. - type: object - ctlog: - description: |- - CTLog (certificate timestamp log) provides a configuration for validation of Signed Certificate - Timestamps (SCTs). If the value is unset, the default behavior by Cosign is used. - properties: - ignoreSCT: - description: |- - IgnoreSCT defines whether to use the Signed Certificate Timestamp (SCT) log to check for a certificate - timestamp. Default is false. Set to true if this was opted out during signing. - type: boolean - pubkey: - description: PubKey, if set, is - used to validate SCTs against - a custom source. - type: string - tsaCertChain: - description: |- - TSACertChain, if set, is the PEM-encoded certificate chain file for the RFC3161 timestamp authority. Must - contain the root CA certificate. Optionally may contain intermediate CA certificates, and - may contain the leaf TSA certificate if not present in the timestamurce. - type: string - type: object - issuer: - description: Issuer is the certificate - issuer used for keyless signing. - type: string - issuerRegExp: - description: IssuerRegExp is the regular - expression to match certificate - issuer used for keyless signing. - type: string - rekor: - description: |- - Rekor provides configuration for the Rekor transparency log service. If an empty object - is provided the public instance of Rekor (https://rekor.sigstore.dev) is used. - properties: - ignoreTlog: - description: IgnoreTlog skips - transparency log verification. - type: boolean - pubkey: - description: |- - RekorPubKey is an optional PEM-encoded public key to use for a custom Rekor. - If set, this will be used to validate transparency log signatures from a custom Rekor. - type: string - url: - description: URL is the address - of the transparency log. Defaults - to the public Rekor log instance - https://rekor.sigstore.dev. - type: string - type: object - roots: - description: |- - Roots is an optional set of PEM encoded trusted root certificates. - If not provided, the system roots are used. - type: string - subject: - description: Subject is the verified - identity used for keyless signing, - for example the email address. - type: string - subjectRegExp: - description: SubjectRegExp is the - regular expression to match identity - used for keyless signing, for example - the email address. - type: string - type: object - keys: - description: Keys specifies one or more - public keys. - properties: - ctlog: - description: |- - CTLog (certificate timestamp log) provides a configuration for validation of Signed Certificate - Timestamps (SCTs). If the value is unset, the default behavior by Cosign is used. - properties: - ignoreSCT: - description: |- - IgnoreSCT defines whether to use the Signed Certificate Timestamp (SCT) log to check for a certificate - timestamp. Default is false. Set to true if this was opted out during signing. - type: boolean - pubkey: - description: PubKey, if set, is - used to validate SCTs against - a custom source. - type: string - tsaCertChain: - description: |- - TSACertChain, if set, is the PEM-encoded certificate chain file for the RFC3161 timestamp authority. Must - contain the root CA certificate. Optionally may contain intermediate CA certificates, and - may contain the leaf TSA certificate if not present in the timestamurce. - type: string - type: object - kms: - description: |- - KMS provides the URI to the public key stored in a Key Management System. See: - https://github.com/sigstore/cosign/blob/main/KMS.md - type: string - publicKeys: - description: |- - Keys is a set of X.509 public keys used to verify image signatures. The keys can be directly - specified or can be a variable reference to a key specified in a ConfigMap (see - https://kyverno.io/docs/writing-policies/variables/), or reference a standard Kubernetes Secret - elsewhere in the cluster by specifying it in the format "k8s:///". - The named Secret must specify a key `cosign.pub` containing the public key used for - verification, (see https://github.com/sigstore/cosign/blob/main/KMS.md#kubernetes-secret). - When multiple keys are specified each key is processed as a separate staticKey entry - (.attestors[*].entries.keys) within the set of attestors and the count is applied across the keys. - type: string - rekor: - description: |- - Rekor provides configuration for the Rekor transparency log service. If an empty object - is provided the public instance of Rekor (https://rekor.sigstore.dev) is used. - properties: - ignoreTlog: - description: IgnoreTlog skips - transparency log verification. - type: boolean - pubkey: - description: |- - RekorPubKey is an optional PEM-encoded public key to use for a custom Rekor. - If set, this will be used to validate transparency log signatures from a custom Rekor. - type: string - url: - description: URL is the address - of the transparency log. Defaults - to the public Rekor log instance - https://rekor.sigstore.dev. - type: string - type: object - secret: - description: Reference to a Secret - resource that contains a public - key - properties: - name: - description: Name of the secret. - The provided secret must contain - a key named cosign.pub. - type: string - namespace: - description: Namespace name where - the Secret exists. - type: string - required: - - name - - namespace - type: object - signatureAlgorithm: - default: sha256 - description: Deprecated. Use attestor.signatureAlgorithm - instead. - type: string - type: object - repository: - description: |- - Repository is an optional alternate OCI repository to use for signatures and attestations that match this rule. - If specified Repository will override other OCI image repository locations for this Attestor. - type: string - signatureAlgorithm: - default: sha256 - description: Specify signature algorithm - for public keys. Supported values are - sha224, sha256, sha384 and sha512. - type: string - type: object - type: array - type: object - type: array - cosignOCI11: - description: |- - CosignOCI11 enables the experimental OCI 1.1 behaviour in cosign image verification. - Defaults to false. - type: boolean - failureAction: - description: Allowed values are Audit or Enforce. - enum: - - Audit - - Enforce - type: string - image: - description: Deprecated. Use ImageReferences instead. - type: string - imageReferences: - description: |- - ImageReferences is a list of matching image reference patterns. At least one pattern in the - list must match the image for the rule to apply. Each image reference consists of a registry - address (defaults to docker.io), repository, image, and tag (defaults to latest). - Wildcards ('*' and '?') are allowed. See: https://kubernetes.io/docs/concepts/containers/images. - items: - type: string - type: array - imageRegistryCredentials: - description: ImageRegistryCredentials provides credentials - that will be used for authentication with registry. - properties: - allowInsecureRegistry: - description: AllowInsecureRegistry allows insecure - access to a registry. - type: boolean - providers: - description: |- - Providers specifies a list of OCI Registry names, whose authentication providers are provided. - It can be of one of these values: default,google,azure,amazon,github. - items: - description: ImageRegistryCredentialsProvidersType - provides the list of credential providers - required. - enum: - - default - - amazon - - azure - - google - - github - type: string - type: array - secrets: - description: |- - Secrets specifies a list of secrets that are provided for credentials. - Secrets must live in the Kyverno namespace. - items: - type: string - type: array - type: object - issuer: - description: Deprecated. Use KeylessAttestor instead. - type: string - key: - description: Deprecated. Use StaticKeyAttestor instead. - type: string - mutateDigest: - default: true - description: |- - MutateDigest enables replacement of image tags with digests. - Defaults to true. - type: boolean - repository: - description: |- - Repository is an optional alternate OCI repository to use for image signatures and attestations that match this rule. - If specified Repository will override the default OCI image repository configured for the installation. - The repository can also be overridden per Attestor or Attestation. - type: string - required: - default: true - description: Required validates that images are verified - i.e. have matched passed a signature or attestation - check. - type: boolean - roots: - description: Deprecated. Use KeylessAttestor instead. - type: string - skipImageReferences: - description: |- - SkipImageReferences is a list of matching image reference patterns that should be skipped. - At least one pattern in the list must match the image for the rule to be skipped. Each image reference - consists of a registry address (defaults to docker.io), repository, image, and tag (defaults to latest). - Wildcards ('*' and '?') are allowed. See: https://kubernetes.io/docs/concepts/containers/images. - items: - type: string - type: array - subject: - description: Deprecated. Use KeylessAttestor instead. - type: string - type: - description: |- - Type specifies the method of signature validation. The allowed options - are Cosign, Sigstore Bundle and Notary. By default Cosign is used if a type is not specified. - enum: - - Cosign - - SigstoreBundle - - Notary - type: string - useCache: - default: true - description: UseCache enables caching of image verify - responses for this rule. - type: boolean - validate: - description: |- - Validation checks conditions across multiple image - verification attestations or context entries - properties: - deny: - description: Deny defines conditions used to pass - or fail a validation rule. - properties: - conditions: - description: |- - Multiple conditions can be declared under an `any` or `all` statement. A direct list - of conditions (without `any` or `all` statements) is also supported for backwards compatibility - but will be deprecated in the next major release. - See: https://kyverno.io/docs/writing-policies/validate/#deny-rules - x-kubernetes-preserve-unknown-fields: true - type: object - message: - description: Message specifies a custom message - to be displayed on failure. - type: string - type: object - verifyDigest: - default: true - description: VerifyDigest validates that images have - a digest. - type: boolean - type: object - type: array - required: - - match - - name - type: object - type: array - type: object - conditions: - items: - description: Condition contains details for one aspect of the current - state of this API Resource. - properties: - lastTransitionTime: - description: |- - lastTransitionTime is the last time the condition transitioned from one status to another. - This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable. - format: date-time - type: string - message: - description: |- - message is a human readable message indicating details about the transition. - This may be an empty string. - maxLength: 32768 - type: string - observedGeneration: - description: |- - observedGeneration represents the .metadata.generation that the condition was set based upon. - For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date - with respect to the current state of the instance. - format: int64 - minimum: 0 - type: integer - reason: - description: |- - reason contains a programmatic identifier indicating the reason for the condition's last transition. - Producers of specific condition types may define expected values and meanings for this field, - and whether the values are considered a guaranteed API. - The value should be a CamelCase string. - This field may not be empty. - maxLength: 1024 - minLength: 1 - pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ - type: string - status: - description: status of the condition, one of True, False, Unknown. - enum: - - "True" - - "False" - - Unknown - type: string - type: - description: type of condition in CamelCase or in foo.example.com/CamelCase. - maxLength: 316 - pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ - type: string - required: - - lastTransitionTime - - message - - reason - - status - - type - type: object - type: array - ready: - description: Deprecated in favor of Conditions - type: boolean - rulecount: - description: |- - RuleCountStatus contains four variables which describes counts for - validate, generate, mutate and verify images rules - properties: - generate: - description: Count for generate rules in policy - type: integer - mutate: - description: Count for mutate rules in policy - type: integer - validate: - description: Count for validate rules in policy - type: integer - verifyimages: - description: Count for verify image rules in policy - type: integer - required: - - generate - - mutate - - validate - - verifyimages - type: object - validatingadmissionpolicy: - description: ValidatingAdmissionPolicy contains status information - properties: - generated: - description: Generated indicates whether a validating admission - policy is generated from the policy or not - type: boolean - message: - description: |- - Message is a human readable message indicating details about the generation of validating admission policy - It is an empty string when validating admission policy is successfully generated. - type: string - required: - - generated - - message - type: object - type: object - required: - - spec - type: object - served: true - storage: false - subresources: - status: {} ---- -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - labels: - app.kubernetes.io/component: crds - app.kubernetes.io/instance: kyverno - app.kubernetes.io/managed-by: Helm - app.kubernetes.io/part-of: kyverno-crds - app.kubernetes.io/version: 3.5.1 - helm.sh/chart: crds-3.5.1 - annotations: - controller-gen.kubebuilder.io/version: v0.17.3 - name: globalcontextentries.kyverno.io -spec: - group: kyverno.io - names: - categories: - - kyverno - kind: GlobalContextEntry - listKind: GlobalContextEntryList - plural: globalcontextentries - shortNames: - - gctxentry - singular: globalcontextentry - scope: Cluster - versions: - - additionalPrinterColumns: - - jsonPath: .metadata.creationTimestamp - name: AGE - type: date - - jsonPath: .spec.apiCall.refreshInterval - name: REFRESH INTERVAL - type: string - - jsonPath: .status.lastRefreshTime - name: LAST REFRESH - type: date - name: v2alpha1 - schema: - openAPIV3Schema: - description: GlobalContextEntry declares resources to be cached. - properties: - apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - type: string - kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - metadata: - type: object - spec: - description: Spec declares policy exception behaviors. - oneOf: - - required: - - kubernetesResource - - required: - - apiCall - properties: - apiCall: - description: |- - Stores results from an API call which will be cached. - Mutually exclusive with KubernetesResource. - This can be used to make calls to external (non-Kubernetes API server) services. - It can also be used to make calls to the Kubernetes API server in such cases: - 1. A POST is needed to create a resource. - 2. Finer-grained control is needed. Example: To restrict the number of resources cached. - properties: - data: - description: |- - The data object specifies the POST data sent to the server. - Only applicable when the method field is set to POST. - items: - description: RequestData contains the HTTP POST data - properties: - key: - description: Key is a unique identifier for the data value - type: string - value: - description: Value is the data value - x-kubernetes-preserve-unknown-fields: true - required: - - key - - value - type: object - type: array - method: - default: GET - description: Method is the HTTP request type (GET or POST). Defaults - to GET. - enum: - - GET - - POST - type: string - refreshInterval: - default: 10m - description: |- - RefreshInterval defines the interval in duration at which to poll the APICall. - The duration is a sequence of decimal numbers, each with optional fraction and a unit suffix, - such as "300ms", "1.5h" or "2h45m". Valid time units are "ns", "us" (or "µs"), "ms", "s", "m", "h". - format: duration - type: string - retryLimit: - default: 3 - description: RetryLimit defines the number of times the APICall - should be retried in case of failure. - minimum: 1 - type: integer - service: - description: |- - Service is an API call to a JSON web service. - This is used for non-Kubernetes API server calls. - It's mutually exclusive with the URLPath field. - properties: - caBundle: - description: |- - CABundle is a PEM encoded CA bundle which will be used to validate - the server certificate. - type: string - headers: - description: Headers is a list of optional HTTP headers to - be included in the request. - items: - properties: - key: - description: Key is the header key - type: string - value: - description: Value is the header value - type: string - required: - - key - - value - type: object - type: array - url: - description: |- - URL is the JSON web service URL. A typical form is - `https://{service}.{namespace}:{port}/{path}`. - type: string - required: - - url - type: object - urlPath: - description: |- - URLPath is the URL path to be used in the HTTP GET or POST request to the - Kubernetes API server (e.g. "/api/v1/namespaces" or "/apis/apps/v1/deployments"). - The format required is the same format used by the `kubectl get --raw` command. - See https://kyverno.io/docs/writing-policies/external-data-sources/#variables-from-kubernetes-api-server-calls - for details. - It's mutually exclusive with the Service field. - type: string - type: object - kubernetesResource: - description: |- - Stores a list of Kubernetes resources which will be cached. - Mutually exclusive with APICall. - properties: - group: - description: Group defines the group of the resource. - type: string - namespace: - description: |- - Namespace defines the namespace of the resource. Leave empty for cluster scoped resources. - If left empty for namespaced resources, all resources from all namespaces will be cached. - type: string - resource: - description: |- - Resource defines the type of the resource. - Requires the pluralized form of the resource kind in lowercase. (Ex., "deployments") - type: string - version: - description: Version defines the version of the resource. - type: string - required: - - resource - - version - type: object - projections: - description: Projections defines the list of JMESPath expressions - to extract values from the cached resource. - items: - properties: - jmesPath: - description: JMESPath is the JMESPath expression to extract - the value from the cached resource. - type: string - name: - description: Name is the name to use for the extracted value - in the context. - type: string - required: - - jmesPath - - name - type: object - type: array - type: object - status: - description: Status contains globalcontextentry runtime data. - properties: - conditions: - items: - description: Condition contains details for one aspect of the current - state of this API Resource. - properties: - lastTransitionTime: - description: |- - lastTransitionTime is the last time the condition transitioned from one status to another. - This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable. - format: date-time - type: string - message: - description: |- - message is a human readable message indicating details about the transition. - This may be an empty string. - maxLength: 32768 - type: string - observedGeneration: - description: |- - observedGeneration represents the .metadata.generation that the condition was set based upon. - For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date - with respect to the current state of the instance. - format: int64 - minimum: 0 - type: integer - reason: - description: |- - reason contains a programmatic identifier indicating the reason for the condition's last transition. - Producers of specific condition types may define expected values and meanings for this field, - and whether the values are considered a guaranteed API. - The value should be a CamelCase string. - This field may not be empty. - maxLength: 1024 - minLength: 1 - pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ - type: string - status: - description: status of the condition, one of True, False, Unknown. - enum: - - "True" - - "False" - - Unknown - type: string - type: - description: type of condition in CamelCase or in foo.example.com/CamelCase. - maxLength: 316 - pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ - type: string - required: - - lastTransitionTime - - message - - reason - - status - - type - type: object - type: array - lastRefreshTime: - description: Indicates the time when the globalcontextentry was last - refreshed successfully for the API Call - format: date-time - type: string - ready: - description: Deprecated in favor of Conditions - type: boolean - type: object - required: - - spec - type: object - served: true - storage: true - subresources: - status: {} ---- -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - labels: - app.kubernetes.io/component: crds - app.kubernetes.io/instance: kyverno - app.kubernetes.io/managed-by: Helm - app.kubernetes.io/part-of: kyverno-crds - app.kubernetes.io/version: 3.5.1 - helm.sh/chart: crds-3.5.1 - annotations: - controller-gen.kubebuilder.io/version: v0.17.3 - name: policies.kyverno.io -spec: - group: kyverno.io - names: - categories: - - kyverno - kind: Policy - listKind: PolicyList - plural: policies - shortNames: - - pol - singular: policy - scope: Namespaced - versions: - - additionalPrinterColumns: - - jsonPath: .spec.admission - name: ADMISSION - type: boolean - - jsonPath: .spec.background - name: BACKGROUND - type: boolean - - jsonPath: .status.conditions[?(@.type == "Ready")].status - name: READY - type: string - - jsonPath: .metadata.creationTimestamp - name: AGE - type: date - - jsonPath: .spec.failurePolicy - name: FAILURE POLICY - priority: 1 - type: string - - jsonPath: .status.rulecount.validate - name: VALIDATE - priority: 1 - type: integer - - jsonPath: .status.rulecount.mutate - name: MUTATE - priority: 1 - type: integer - - jsonPath: .status.rulecount.generate - name: GENERATE - priority: 1 - type: integer - - jsonPath: .status.rulecount.verifyimages - name: VERIFY IMAGES - priority: 1 - type: integer - - jsonPath: .status.conditions[?(@.type == "Ready")].message - name: MESSAGE - type: string - name: v1 - schema: - openAPIV3Schema: - description: |- - Policy declares validation, mutation, and generation behaviors for matching resources. - See: https://kyverno.io/docs/writing-policies/ for more information. - properties: - apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - type: string - kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - metadata: - type: object - spec: - description: Spec defines policy behaviors and contains one or more rules. - properties: - admission: - default: true - description: |- - Admission controls if rules are applied during admission. - Optional. Default value is "true". - type: boolean - applyRules: - description: |- - ApplyRules controls how rules in a policy are applied. Rule are processed in - the order of declaration. When set to `One` processing stops after a rule has - been applied i.e. the rule matches and results in a pass, fail, or error. When - set to `All` all rules in the policy are processed. The default is `All`. - enum: - - All - - One - type: string - background: - default: true - description: |- - Background controls if rules are applied to existing resources during a background scan. - Optional. Default value is "true". The value must be set to "false" if the policy rule - uses variables that are only available in the admission review request (e.g. user name). - type: boolean - emitWarning: - default: false - description: |- - EmitWarning enables API response warnings for mutate policy rules or validate policy rules with validationFailureAction set to Audit. - Enabling this option will extend admission request processing times. The default value is "false". - type: boolean - failurePolicy: - description: Deprecated, use failurePolicy under the webhookConfiguration - instead. - enum: - - Ignore - - Fail - type: string - generateExisting: - description: Deprecated, use generateExisting under the generate rule - instead - type: boolean - generateExistingOnPolicyUpdate: - description: Deprecated, use generateExisting instead - type: boolean - mutateExistingOnPolicyUpdate: - description: Deprecated, use mutateExistingOnPolicyUpdate under the - mutate rule instead - type: boolean - rules: - description: |- - Rules is a list of Rule instances. A Policy contains multiple rules and - each rule can validate, mutate, or generate resources. - items: - description: |- - Rule defines a validation, mutation, or generation control for matching resources. - Each rules contains a match declaration to select resources, and an optional exclude - declaration to specify which resources to exclude. - properties: - celPreconditions: - description: |- - CELPreconditions are used to determine if a policy rule should be applied by evaluating a - set of CEL conditions. It can only be used with the validate.cel subrule - items: - description: MatchCondition represents a condition which must - by fulfilled for a request to be sent to a webhook. - properties: - expression: - description: |- - Expression represents the expression which will be evaluated by CEL. Must evaluate to bool. - CEL expressions have access to the contents of the AdmissionRequest and Authorizer, organized into CEL variables: - - 'object' - The object from the incoming request. The value is null for DELETE requests. - 'oldObject' - The existing object. The value is null for CREATE requests. - 'request' - Attributes of the admission request(/pkg/apis/admission/types.go#AdmissionRequest). - 'authorizer' - A CEL Authorizer. May be used to perform authorization checks for the principal (user or service account) of the request. - See https://pkg.go.dev/k8s.io/apiserver/pkg/cel/library#Authz - 'authorizer.requestResource' - A CEL ResourceCheck constructed from the 'authorizer' and configured with the - request resource. - Documentation on CEL: https://kubernetes.io/docs/reference/using-api/cel/ - - Required. - type: string - name: - description: |- - Name is an identifier for this match condition, used for strategic merging of MatchConditions, - as well as providing an identifier for logging purposes. A good name should be descriptive of - the associated expression. - Name must be a qualified name consisting of alphanumeric characters, '-', '_' or '.', and - must start and end with an alphanumeric character (e.g. 'MyName', or 'my.name', or - '123-abc', regex used for validation is '([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9]') with an - optional DNS subdomain prefix and '/' (e.g. 'example.com/MyName') - - Required. - type: string - required: - - expression - - name - type: object - type: array - context: - description: Context defines variables and data sources that - can be used during rule execution. - items: - description: |- - ContextEntry adds variables and data sources to a rule Context. Either a - ConfigMap reference or a APILookup must be provided. - oneOf: - - required: - - configMap - - required: - - apiCall - - required: - - imageRegistry - - required: - - variable - - required: - - globalReference - properties: - apiCall: - description: |- - APICall is an HTTP request to the Kubernetes API server, or other JSON web service. - The data returned is stored in the context with the name for the context entry. - properties: - data: - description: |- - The data object specifies the POST data sent to the server. - Only applicable when the method field is set to POST. - items: - description: RequestData contains the HTTP POST - data - properties: - key: - description: Key is a unique identifier for - the data value - type: string - value: - description: Value is the data value - x-kubernetes-preserve-unknown-fields: true - required: - - key - - value - type: object - type: array - default: - description: |- - Default is an optional arbitrary JSON object that the context - value is set to, if the apiCall returns error. - x-kubernetes-preserve-unknown-fields: true - jmesPath: - description: |- - JMESPath is an optional JSON Match Expression that can be used to - transform the JSON response returned from the server. For example - a JMESPath of "items | length(@)" applied to the API server response - for the URLPath "/apis/apps/v1/deployments" will return the total count - of deployments across all namespaces. - type: string - method: - default: GET - description: Method is the HTTP request type (GET - or POST). Defaults to GET. - enum: - - GET - - POST - type: string - service: - description: |- - Service is an API call to a JSON web service. - This is used for non-Kubernetes API server calls. - It's mutually exclusive with the URLPath field. - properties: - caBundle: - description: |- - CABundle is a PEM encoded CA bundle which will be used to validate - the server certificate. - type: string - headers: - description: Headers is a list of optional HTTP - headers to be included in the request. - items: - properties: - key: - description: Key is the header key - type: string - value: - description: Value is the header value - type: string - required: - - key - - value - type: object - type: array - url: - description: |- - URL is the JSON web service URL. A typical form is - `https://{service}.{namespace}:{port}/{path}`. - type: string - required: - - url - type: object - urlPath: - description: |- - URLPath is the URL path to be used in the HTTP GET or POST request to the - Kubernetes API server (e.g. "/api/v1/namespaces" or "/apis/apps/v1/deployments"). - The format required is the same format used by the `kubectl get --raw` command. - See https://kyverno.io/docs/writing-policies/external-data-sources/#variables-from-kubernetes-api-server-calls - for details. - It's mutually exclusive with the Service field. - type: string - type: object - configMap: - description: ConfigMap is the ConfigMap reference. - properties: - name: - description: Name is the ConfigMap name. - type: string - namespace: - description: Namespace is the ConfigMap namespace. - type: string - required: - - name - type: object - globalReference: - description: GlobalContextEntryReference is a reference - to a cached global context entry. - properties: - jmesPath: - description: |- - JMESPath is an optional JSON Match Expression that can be used to - transform the JSON response returned from the server. For example - a JMESPath of "items | length(@)" applied to the API server response - for the URLPath "/apis/apps/v1/deployments" will return the total count - of deployments across all namespaces. - type: string - name: - description: Name of the global context entry - type: string - required: - - name - type: object - imageRegistry: - description: |- - ImageRegistry defines requests to an OCI/Docker V2 registry to fetch image - details. - properties: - imageRegistryCredentials: - description: ImageRegistryCredentials provides credentials - that will be used for authentication with registry - properties: - allowInsecureRegistry: - description: AllowInsecureRegistry allows insecure - access to a registry. - type: boolean - providers: - description: |- - Providers specifies a list of OCI Registry names, whose authentication providers are provided. - It can be of one of these values: default,google,azure,amazon,github. - items: - description: ImageRegistryCredentialsProvidersType - provides the list of credential providers - required. - enum: - - default - - amazon - - azure - - google - - github - type: string - type: array - secrets: - description: |- - Secrets specifies a list of secrets that are provided for credentials. - Secrets must live in the Kyverno namespace. - items: - type: string - type: array - type: object - jmesPath: - description: |- - JMESPath is an optional JSON Match Expression that can be used to - transform the ImageData struct returned as a result of processing - the image reference. - type: string - reference: - description: |- - Reference is image reference to a container image in the registry. - Example: ghcr.io/kyverno/kyverno:latest - type: string - required: - - reference - type: object - name: - description: Name is the variable name. - type: string - variable: - description: Variable defines an arbitrary JMESPath context - variable that can be defined inline. - properties: - default: - description: |- - Default is an optional arbitrary JSON object that the variable may take if the JMESPath - expression evaluates to nil - x-kubernetes-preserve-unknown-fields: true - jmesPath: - description: |- - JMESPath is an optional JMESPath Expression that can be used to - transform the variable. - type: string - value: - description: Value is any arbitrary JSON object representable - in YAML or JSON form. - x-kubernetes-preserve-unknown-fields: true - type: object - required: - - name - type: object - type: array - exclude: - description: |- - ExcludeResources defines when this policy rule should not be applied. The exclude - criteria can include resource information (e.g. kind, name, namespace, labels) - and admission review request information like the name or role. - not: - required: - - any - - all - properties: - all: - description: All allows specifying resources which will - be ANDed - items: - description: ResourceFilter allow users to "AND" or "OR" - between resources - properties: - clusterRoles: - description: ClusterRoles is the list of cluster-wide - role names for the user. - items: - type: string - type: array - resources: - description: ResourceDescription contains information - about the resource being created or modified. - not: - required: - - name - - names - properties: - annotations: - additionalProperties: - type: string - description: |- - Annotations is a map of annotations (key-value pairs of type string). Annotation keys - and values support the wildcard characters "*" (matches zero or many characters) and - "?" (matches at least one character). - type: object - kinds: - description: Kinds is a list of resource kinds. - items: - type: string - type: array - name: - description: |- - Name is the name of the resource. The name supports wildcard characters - "*" (matches zero or many characters) and "?" (at least one character). - NOTE: "Name" is being deprecated in favor of "Names". - type: string - names: - description: |- - Names are the names of the resources. Each name supports wildcard characters - "*" (matches zero or many characters) and "?" (at least one character). - items: - type: string - type: array - namespaceSelector: - description: |- - NamespaceSelector is a label selector for the resource namespace. Label keys and values - in `matchLabels` support the wildcard characters `*` (matches zero or many characters) - and `?` (matches one character).Wildcards allows writing label selectors like - ["storage.k8s.io/*": "*"]. Note that using ["*" : "*"] matches any key and value but - does not match an empty label set. - properties: - matchExpressions: - description: matchExpressions is a list of - label selector requirements. The requirements - are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key that - the selector applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - namespaces: - description: |- - Namespaces is a list of namespaces names. Each name supports wildcard characters - "*" (matches zero or many characters) and "?" (at least one character). - items: - type: string - type: array - operations: - description: Operations can contain values ["CREATE, - "UPDATE", "CONNECT", "DELETE"], which are used - to match a specific action. - items: - description: AdmissionOperation can have one - of the values CREATE, UPDATE, CONNECT, DELETE, - which are used to match a specific action. - enum: - - CREATE - - CONNECT - - UPDATE - - DELETE - type: string - type: array - selector: - description: |- - Selector is a label selector. Label keys and values in `matchLabels` support the wildcard - characters `*` (matches zero or many characters) and `?` (matches one character). - Wildcards allows writing label selectors like ["storage.k8s.io/*": "*"]. Note that - using ["*" : "*"] matches any key and value but does not match an empty label set. - properties: - matchExpressions: - description: matchExpressions is a list of - label selector requirements. The requirements - are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key that - the selector applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - type: object - roles: - description: Roles is the list of namespaced role - names for the user. - items: - type: string - type: array - subjects: - description: Subjects is the list of subject names - like users, user groups, and service accounts. - items: - description: |- - Subject contains a reference to the object or user identities a role binding applies to. This can either hold a direct API object reference, - or a value for non-objects such as user and group names. - properties: - apiGroup: - description: |- - APIGroup holds the API group of the referenced subject. - Defaults to "" for ServiceAccount subjects. - Defaults to "rbac.authorization.k8s.io" for User and Group subjects. - type: string - kind: - description: |- - Kind of object being referenced. Values defined by this API group are "User", "Group", and "ServiceAccount". - If the Authorizer does not recognized the kind value, the Authorizer should report an error. - type: string - name: - description: Name of the object being referenced. - type: string - namespace: - description: |- - Namespace of the referenced object. If the object kind is non-namespace, such as "User" or "Group", and this value is not empty - the Authorizer should report an error. - type: string - required: - - kind - - name - type: object - x-kubernetes-map-type: atomic - type: array - type: object - type: array - any: - description: Any allows specifying resources which will - be ORed - items: - description: ResourceFilter allow users to "AND" or "OR" - between resources - properties: - clusterRoles: - description: ClusterRoles is the list of cluster-wide - role names for the user. - items: - type: string - type: array - resources: - description: ResourceDescription contains information - about the resource being created or modified. - not: - required: - - name - - names - properties: - annotations: - additionalProperties: - type: string - description: |- - Annotations is a map of annotations (key-value pairs of type string). Annotation keys - and values support the wildcard characters "*" (matches zero or many characters) and - "?" (matches at least one character). - type: object - kinds: - description: Kinds is a list of resource kinds. - items: - type: string - type: array - name: - description: |- - Name is the name of the resource. The name supports wildcard characters - "*" (matches zero or many characters) and "?" (at least one character). - NOTE: "Name" is being deprecated in favor of "Names". - type: string - names: - description: |- - Names are the names of the resources. Each name supports wildcard characters - "*" (matches zero or many characters) and "?" (at least one character). - items: - type: string - type: array - namespaceSelector: - description: |- - NamespaceSelector is a label selector for the resource namespace. Label keys and values - in `matchLabels` support the wildcard characters `*` (matches zero or many characters) - and `?` (matches one character).Wildcards allows writing label selectors like - ["storage.k8s.io/*": "*"]. Note that using ["*" : "*"] matches any key and value but - does not match an empty label set. - properties: - matchExpressions: - description: matchExpressions is a list of - label selector requirements. The requirements - are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key that - the selector applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - namespaces: - description: |- - Namespaces is a list of namespaces names. Each name supports wildcard characters - "*" (matches zero or many characters) and "?" (at least one character). - items: - type: string - type: array - operations: - description: Operations can contain values ["CREATE, - "UPDATE", "CONNECT", "DELETE"], which are used - to match a specific action. - items: - description: AdmissionOperation can have one - of the values CREATE, UPDATE, CONNECT, DELETE, - which are used to match a specific action. - enum: - - CREATE - - CONNECT - - UPDATE - - DELETE - type: string - type: array - selector: - description: |- - Selector is a label selector. Label keys and values in `matchLabels` support the wildcard - characters `*` (matches zero or many characters) and `?` (matches one character). - Wildcards allows writing label selectors like ["storage.k8s.io/*": "*"]. Note that - using ["*" : "*"] matches any key and value but does not match an empty label set. - properties: - matchExpressions: - description: matchExpressions is a list of - label selector requirements. The requirements - are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key that - the selector applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - type: object - roles: - description: Roles is the list of namespaced role - names for the user. - items: - type: string - type: array - subjects: - description: Subjects is the list of subject names - like users, user groups, and service accounts. - items: - description: |- - Subject contains a reference to the object or user identities a role binding applies to. This can either hold a direct API object reference, - or a value for non-objects such as user and group names. - properties: - apiGroup: - description: |- - APIGroup holds the API group of the referenced subject. - Defaults to "" for ServiceAccount subjects. - Defaults to "rbac.authorization.k8s.io" for User and Group subjects. - type: string - kind: - description: |- - Kind of object being referenced. Values defined by this API group are "User", "Group", and "ServiceAccount". - If the Authorizer does not recognized the kind value, the Authorizer should report an error. - type: string - name: - description: Name of the object being referenced. - type: string - namespace: - description: |- - Namespace of the referenced object. If the object kind is non-namespace, such as "User" or "Group", and this value is not empty - the Authorizer should report an error. - type: string - required: - - kind - - name - type: object - x-kubernetes-map-type: atomic - type: array - type: object - type: array - clusterRoles: - description: ClusterRoles is the list of cluster-wide role - names for the user. - items: - type: string - type: array - resources: - description: |- - ResourceDescription contains information about the resource being created or modified. - Requires at least one tag to be specified when under MatchResources. - Specifying ResourceDescription directly under match is being deprecated. - Please specify under "any" or "all" instead. - not: - required: - - name - - names - properties: - annotations: - additionalProperties: - type: string - description: |- - Annotations is a map of annotations (key-value pairs of type string). Annotation keys - and values support the wildcard characters "*" (matches zero or many characters) and - "?" (matches at least one character). - type: object - kinds: - description: Kinds is a list of resource kinds. - items: - type: string - type: array - name: - description: |- - Name is the name of the resource. The name supports wildcard characters - "*" (matches zero or many characters) and "?" (at least one character). - NOTE: "Name" is being deprecated in favor of "Names". - type: string - names: - description: |- - Names are the names of the resources. Each name supports wildcard characters - "*" (matches zero or many characters) and "?" (at least one character). - items: - type: string - type: array - namespaceSelector: - description: |- - NamespaceSelector is a label selector for the resource namespace. Label keys and values - in `matchLabels` support the wildcard characters `*` (matches zero or many characters) - and `?` (matches one character).Wildcards allows writing label selectors like - ["storage.k8s.io/*": "*"]. Note that using ["*" : "*"] matches any key and value but - does not match an empty label set. - properties: - matchExpressions: - description: matchExpressions is a list of label - selector requirements. The requirements are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key that the - selector applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - namespaces: - description: |- - Namespaces is a list of namespaces names. Each name supports wildcard characters - "*" (matches zero or many characters) and "?" (at least one character). - items: - type: string - type: array - operations: - description: Operations can contain values ["CREATE, - "UPDATE", "CONNECT", "DELETE"], which are used to - match a specific action. - items: - description: AdmissionOperation can have one of the - values CREATE, UPDATE, CONNECT, DELETE, which are - used to match a specific action. - enum: - - CREATE - - CONNECT - - UPDATE - - DELETE - type: string - type: array - selector: - description: |- - Selector is a label selector. Label keys and values in `matchLabels` support the wildcard - characters `*` (matches zero or many characters) and `?` (matches one character). - Wildcards allows writing label selectors like ["storage.k8s.io/*": "*"]. Note that - using ["*" : "*"] matches any key and value but does not match an empty label set. - properties: - matchExpressions: - description: matchExpressions is a list of label - selector requirements. The requirements are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key that the - selector applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - type: object - roles: - description: Roles is the list of namespaced role names - for the user. - items: - type: string - type: array - subjects: - description: Subjects is the list of subject names like - users, user groups, and service accounts. - items: - description: |- - Subject contains a reference to the object or user identities a role binding applies to. This can either hold a direct API object reference, - or a value for non-objects such as user and group names. - properties: - apiGroup: - description: |- - APIGroup holds the API group of the referenced subject. - Defaults to "" for ServiceAccount subjects. - Defaults to "rbac.authorization.k8s.io" for User and Group subjects. - type: string - kind: - description: |- - Kind of object being referenced. Values defined by this API group are "User", "Group", and "ServiceAccount". - If the Authorizer does not recognized the kind value, the Authorizer should report an error. - type: string - name: - description: Name of the object being referenced. - type: string - namespace: - description: |- - Namespace of the referenced object. If the object kind is non-namespace, such as "User" or "Group", and this value is not empty - the Authorizer should report an error. - type: string - required: - - kind - - name - type: object - x-kubernetes-map-type: atomic - type: array - type: object - generate: - description: Generation is used to create new resources. - properties: - apiVersion: - description: APIVersion specifies resource apiVersion. - type: string - clone: - description: |- - Clone specifies the source resource used to populate each generated resource. - At most one of Data or Clone can be specified. If neither are provided, the generated - resource will be created with default data only. - properties: - name: - description: Name specifies name of the resource. - type: string - namespace: - description: Namespace specifies source resource namespace. - type: string - type: object - cloneList: - description: CloneList specifies the list of source resource - used to populate each generated resource. - properties: - kinds: - description: Kinds is a list of resource kinds. - items: - type: string - type: array - namespace: - description: Namespace specifies source resource namespace. - type: string - selector: - description: |- - Selector is a label selector. Label keys and values in `matchLabels`. - wildcard characters are not supported. - properties: - matchExpressions: - description: matchExpressions is a list of label - selector requirements. The requirements are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key that the - selector applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - type: object - data: - description: |- - Data provides the resource declaration used to populate each generated resource. - At most one of Data or Clone must be specified. If neither are provided, the generated - resource will be created with default data only. - x-kubernetes-preserve-unknown-fields: true - foreach: - description: ForEach applies generate rules to a list of - sub-elements by creating a context for each entry in the - list and looping over it to apply the specified logic. - items: - properties: - apiVersion: - description: APIVersion specifies resource apiVersion. - type: string - clone: - description: |- - Clone specifies the source resource used to populate each generated resource. - At most one of Data or Clone can be specified. If neither are provided, the generated - resource will be created with default data only. - properties: - name: - description: Name specifies name of the resource. - type: string - namespace: - description: Namespace specifies source resource - namespace. - type: string - type: object - cloneList: - description: CloneList specifies the list of source - resource used to populate each generated resource. - properties: - kinds: - description: Kinds is a list of resource kinds. - items: - type: string - type: array - namespace: - description: Namespace specifies source resource - namespace. - type: string - selector: - description: |- - Selector is a label selector. Label keys and values in `matchLabels`. - wildcard characters are not supported. - properties: - matchExpressions: - description: matchExpressions is a list of - label selector requirements. The requirements - are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key that - the selector applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - type: object - context: - description: Context defines variables and data sources - that can be used during rule execution. - items: - description: |- - ContextEntry adds variables and data sources to a rule Context. Either a - ConfigMap reference or a APILookup must be provided. - oneOf: - - required: - - configMap - - required: - - apiCall - - required: - - imageRegistry - - required: - - variable - - required: - - globalReference - properties: - apiCall: - description: |- - APICall is an HTTP request to the Kubernetes API server, or other JSON web service. - The data returned is stored in the context with the name for the context entry. - properties: - data: - description: |- - The data object specifies the POST data sent to the server. - Only applicable when the method field is set to POST. - items: - description: RequestData contains the - HTTP POST data - properties: - key: - description: Key is a unique identifier - for the data value - type: string - value: - description: Value is the data value - x-kubernetes-preserve-unknown-fields: true - required: - - key - - value - type: object - type: array - default: - description: |- - Default is an optional arbitrary JSON object that the context - value is set to, if the apiCall returns error. - x-kubernetes-preserve-unknown-fields: true - jmesPath: - description: |- - JMESPath is an optional JSON Match Expression that can be used to - transform the JSON response returned from the server. For example - a JMESPath of "items | length(@)" applied to the API server response - for the URLPath "/apis/apps/v1/deployments" will return the total count - of deployments across all namespaces. - type: string - method: - default: GET - description: Method is the HTTP request - type (GET or POST). Defaults to GET. - enum: - - GET - - POST - type: string - service: - description: |- - Service is an API call to a JSON web service. - This is used for non-Kubernetes API server calls. - It's mutually exclusive with the URLPath field. - properties: - caBundle: - description: |- - CABundle is a PEM encoded CA bundle which will be used to validate - the server certificate. - type: string - headers: - description: Headers is a list of optional - HTTP headers to be included in the - request. - items: - properties: - key: - description: Key is the header - key - type: string - value: - description: Value is the header - value - type: string - required: - - key - - value - type: object - type: array - url: - description: |- - URL is the JSON web service URL. A typical form is - `https://{service}.{namespace}:{port}/{path}`. - type: string - required: - - url - type: object - urlPath: - description: |- - URLPath is the URL path to be used in the HTTP GET or POST request to the - Kubernetes API server (e.g. "/api/v1/namespaces" or "/apis/apps/v1/deployments"). - The format required is the same format used by the `kubectl get --raw` command. - See https://kyverno.io/docs/writing-policies/external-data-sources/#variables-from-kubernetes-api-server-calls - for details. - It's mutually exclusive with the Service field. - type: string - type: object - configMap: - description: ConfigMap is the ConfigMap reference. - properties: - name: - description: Name is the ConfigMap name. - type: string - namespace: - description: Namespace is the ConfigMap - namespace. - type: string - required: - - name - type: object - globalReference: - description: GlobalContextEntryReference is - a reference to a cached global context entry. - properties: - jmesPath: - description: |- - JMESPath is an optional JSON Match Expression that can be used to - transform the JSON response returned from the server. For example - a JMESPath of "items | length(@)" applied to the API server response - for the URLPath "/apis/apps/v1/deployments" will return the total count - of deployments across all namespaces. - type: string - name: - description: Name of the global context - entry - type: string - required: - - name - type: object - imageRegistry: - description: |- - ImageRegistry defines requests to an OCI/Docker V2 registry to fetch image - details. - properties: - imageRegistryCredentials: - description: ImageRegistryCredentials provides - credentials that will be used for authentication - with registry - properties: - allowInsecureRegistry: - description: AllowInsecureRegistry allows - insecure access to a registry. - type: boolean - providers: - description: |- - Providers specifies a list of OCI Registry names, whose authentication providers are provided. - It can be of one of these values: default,google,azure,amazon,github. - items: - description: ImageRegistryCredentialsProvidersType - provides the list of credential - providers required. - enum: - - default - - amazon - - azure - - google - - github - type: string - type: array - secrets: - description: |- - Secrets specifies a list of secrets that are provided for credentials. - Secrets must live in the Kyverno namespace. - items: - type: string - type: array - type: object - jmesPath: - description: |- - JMESPath is an optional JSON Match Expression that can be used to - transform the ImageData struct returned as a result of processing - the image reference. - type: string - reference: - description: |- - Reference is image reference to a container image in the registry. - Example: ghcr.io/kyverno/kyverno:latest - type: string - required: - - reference - type: object - name: - description: Name is the variable name. - type: string - variable: - description: Variable defines an arbitrary JMESPath - context variable that can be defined inline. - properties: - default: - description: |- - Default is an optional arbitrary JSON object that the variable may take if the JMESPath - expression evaluates to nil - x-kubernetes-preserve-unknown-fields: true - jmesPath: - description: |- - JMESPath is an optional JMESPath Expression that can be used to - transform the variable. - type: string - value: - description: Value is any arbitrary JSON - object representable in YAML or JSON form. - x-kubernetes-preserve-unknown-fields: true - type: object - required: - - name - type: object - type: array - data: - description: |- - Data provides the resource declaration used to populate each generated resource. - At most one of Data or Clone must be specified. If neither are provided, the generated - resource will be created with default data only. - x-kubernetes-preserve-unknown-fields: true - kind: - description: Kind specifies resource kind. - type: string - list: - description: |- - List specifies a JMESPath expression that results in one or more elements - to which the validation logic is applied. - type: string - name: - description: Name specifies the resource name. - type: string - namespace: - description: Namespace specifies resource namespace. - type: string - preconditions: - description: |- - AnyAllConditions are used to determine if a policy rule should be applied by evaluating a - set of conditions. The declaration can contain nested `any` or `all` statements. - See: https://kyverno.io/docs/writing-policies/preconditions/ - properties: - all: - description: |- - AllConditions enable variable-based conditional rule execution. This is useful for - finer control of when an rule is applied. A condition can reference object data - using JMESPath notation. - Here, all of the conditions need to pass - items: - description: Condition defines variable-based - conditional criteria for rule execution. - properties: - key: - description: Key is the context entry (using - JMESPath) for conditional rule evaluation. - x-kubernetes-preserve-unknown-fields: true - message: - description: Message is an optional display - message - type: string - operator: - description: |- - Operator is the conditional operation to perform. Valid operators are: - Equals, NotEquals, In, AnyIn, AllIn, NotIn, AnyNotIn, AllNotIn, GreaterThanOrEquals, - GreaterThan, LessThanOrEquals, LessThan, DurationGreaterThanOrEquals, DurationGreaterThan, - DurationLessThanOrEquals, DurationLessThan - enum: - - Equals - - NotEquals - - In - - AnyIn - - AllIn - - NotIn - - AnyNotIn - - AllNotIn - - GreaterThanOrEquals - - GreaterThan - - LessThanOrEquals - - LessThan - - DurationGreaterThanOrEquals - - DurationGreaterThan - - DurationLessThanOrEquals - - DurationLessThan - type: string - value: - description: |- - Value is the conditional value, or set of values. The values can be fixed set - or can be variables declared using JMESPath. - x-kubernetes-preserve-unknown-fields: true - type: object - type: array - any: - description: |- - AnyConditions enable variable-based conditional rule execution. This is useful for - finer control of when an rule is applied. A condition can reference object data - using JMESPath notation. - Here, at least one of the conditions need to pass - items: - description: Condition defines variable-based - conditional criteria for rule execution. - properties: - key: - description: Key is the context entry (using - JMESPath) for conditional rule evaluation. - x-kubernetes-preserve-unknown-fields: true - message: - description: Message is an optional display - message - type: string - operator: - description: |- - Operator is the conditional operation to perform. Valid operators are: - Equals, NotEquals, In, AnyIn, AllIn, NotIn, AnyNotIn, AllNotIn, GreaterThanOrEquals, - GreaterThan, LessThanOrEquals, LessThan, DurationGreaterThanOrEquals, DurationGreaterThan, - DurationLessThanOrEquals, DurationLessThan - enum: - - Equals - - NotEquals - - In - - AnyIn - - AllIn - - NotIn - - AnyNotIn - - AllNotIn - - GreaterThanOrEquals - - GreaterThan - - LessThanOrEquals - - LessThan - - DurationGreaterThanOrEquals - - DurationGreaterThan - - DurationLessThanOrEquals - - DurationLessThan - type: string - value: - description: |- - Value is the conditional value, or set of values. The values can be fixed set - or can be variables declared using JMESPath. - x-kubernetes-preserve-unknown-fields: true - type: object - type: array - type: object - x-kubernetes-preserve-unknown-fields: true - uid: - description: UID specifies the resource uid. - type: string - type: object - type: array - generateExisting: - description: |- - GenerateExisting controls whether to trigger the rule in existing resources - If is set to "true" the rule will be triggered and applied to existing matched resources. - type: boolean - kind: - description: Kind specifies resource kind. - type: string - name: - description: Name specifies the resource name. - type: string - namespace: - description: Namespace specifies resource namespace. - type: string - orphanDownstreamOnPolicyDelete: - description: |- - OrphanDownstreamOnPolicyDelete controls whether generated resources should be deleted when the rule that generated - them is deleted with synchronization enabled. This option is only applicable to generate rules of the data type. - See https://kyverno.io/docs/writing-policies/generate/#data-examples. - Defaults to "false" if not specified. - type: boolean - synchronize: - description: |- - Synchronize controls if generated resources should be kept in-sync with their source resource. - If Synchronize is set to "true" changes to generated resources will be overwritten with resource - data from Data or the resource specified in the Clone declaration. - Optional. Defaults to "false" if not specified. - type: boolean - uid: - description: UID specifies the resource uid. - type: string - type: object - imageExtractors: - additionalProperties: - items: - properties: - jmesPath: - description: |- - JMESPath is an optional JMESPath expression to apply to the image value. - This is useful when the extracted image begins with a prefix like 'docker://'. - The 'trim_prefix' function may be used to trim the prefix: trim_prefix(@, 'docker://'). - Note - Image digest mutation may not be used when applying a JMESPAth to an image. - type: string - key: - description: |- - Key is an optional name of the field within 'path' that will be used to uniquely identify an image. - Note - this field MUST be unique. - type: string - name: - description: |- - Name is the entry the image will be available under 'images.' in the context. - If this field is not defined, image entries will appear under 'images.custom'. - type: string - path: - description: |- - Path is the path to the object containing the image field in a custom resource. - It should be slash-separated. Each slash-separated key must be a valid YAML key or a wildcard '*'. - Wildcard keys are expanded in case of arrays or objects. - type: string - value: - description: |- - Value is an optional name of the field within 'path' that points to the image URI. - This is useful when a custom 'key' is also defined. - type: string - required: - - path - type: object - type: array - description: |- - ImageExtractors defines a mapping from kinds to ImageExtractorConfigs. - This config is only valid for verifyImages rules. - type: object - match: - description: |- - MatchResources defines when this policy rule should be applied. The match - criteria can include resource information (e.g. kind, name, namespace, labels) - and admission review request information like the user name or role. - At least one kind is required. - not: - required: - - any - - all - properties: - all: - description: All allows specifying resources which will - be ANDed - items: - description: ResourceFilter allow users to "AND" or "OR" - between resources - properties: - clusterRoles: - description: ClusterRoles is the list of cluster-wide - role names for the user. - items: - type: string - type: array - resources: - description: ResourceDescription contains information - about the resource being created or modified. - not: - required: - - name - - names - properties: - annotations: - additionalProperties: - type: string - description: |- - Annotations is a map of annotations (key-value pairs of type string). Annotation keys - and values support the wildcard characters "*" (matches zero or many characters) and - "?" (matches at least one character). - type: object - kinds: - description: Kinds is a list of resource kinds. - items: - type: string - type: array - name: - description: |- - Name is the name of the resource. The name supports wildcard characters - "*" (matches zero or many characters) and "?" (at least one character). - NOTE: "Name" is being deprecated in favor of "Names". - type: string - names: - description: |- - Names are the names of the resources. Each name supports wildcard characters - "*" (matches zero or many characters) and "?" (at least one character). - items: - type: string - type: array - namespaceSelector: - description: |- - NamespaceSelector is a label selector for the resource namespace. Label keys and values - in `matchLabels` support the wildcard characters `*` (matches zero or many characters) - and `?` (matches one character).Wildcards allows writing label selectors like - ["storage.k8s.io/*": "*"]. Note that using ["*" : "*"] matches any key and value but - does not match an empty label set. - properties: - matchExpressions: - description: matchExpressions is a list of - label selector requirements. The requirements - are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key that - the selector applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - namespaces: - description: |- - Namespaces is a list of namespaces names. Each name supports wildcard characters - "*" (matches zero or many characters) and "?" (at least one character). - items: - type: string - type: array - operations: - description: Operations can contain values ["CREATE, - "UPDATE", "CONNECT", "DELETE"], which are used - to match a specific action. - items: - description: AdmissionOperation can have one - of the values CREATE, UPDATE, CONNECT, DELETE, - which are used to match a specific action. - enum: - - CREATE - - CONNECT - - UPDATE - - DELETE - type: string - type: array - selector: - description: |- - Selector is a label selector. Label keys and values in `matchLabels` support the wildcard - characters `*` (matches zero or many characters) and `?` (matches one character). - Wildcards allows writing label selectors like ["storage.k8s.io/*": "*"]. Note that - using ["*" : "*"] matches any key and value but does not match an empty label set. - properties: - matchExpressions: - description: matchExpressions is a list of - label selector requirements. The requirements - are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key that - the selector applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - type: object - roles: - description: Roles is the list of namespaced role - names for the user. - items: - type: string - type: array - subjects: - description: Subjects is the list of subject names - like users, user groups, and service accounts. - items: - description: |- - Subject contains a reference to the object or user identities a role binding applies to. This can either hold a direct API object reference, - or a value for non-objects such as user and group names. - properties: - apiGroup: - description: |- - APIGroup holds the API group of the referenced subject. - Defaults to "" for ServiceAccount subjects. - Defaults to "rbac.authorization.k8s.io" for User and Group subjects. - type: string - kind: - description: |- - Kind of object being referenced. Values defined by this API group are "User", "Group", and "ServiceAccount". - If the Authorizer does not recognized the kind value, the Authorizer should report an error. - type: string - name: - description: Name of the object being referenced. - type: string - namespace: - description: |- - Namespace of the referenced object. If the object kind is non-namespace, such as "User" or "Group", and this value is not empty - the Authorizer should report an error. - type: string - required: - - kind - - name - type: object - x-kubernetes-map-type: atomic - type: array - type: object - type: array - any: - description: Any allows specifying resources which will - be ORed - items: - description: ResourceFilter allow users to "AND" or "OR" - between resources - properties: - clusterRoles: - description: ClusterRoles is the list of cluster-wide - role names for the user. - items: - type: string - type: array - resources: - description: ResourceDescription contains information - about the resource being created or modified. - not: - required: - - name - - names - properties: - annotations: - additionalProperties: - type: string - description: |- - Annotations is a map of annotations (key-value pairs of type string). Annotation keys - and values support the wildcard characters "*" (matches zero or many characters) and - "?" (matches at least one character). - type: object - kinds: - description: Kinds is a list of resource kinds. - items: - type: string - type: array - name: - description: |- - Name is the name of the resource. The name supports wildcard characters - "*" (matches zero or many characters) and "?" (at least one character). - NOTE: "Name" is being deprecated in favor of "Names". - type: string - names: - description: |- - Names are the names of the resources. Each name supports wildcard characters - "*" (matches zero or many characters) and "?" (at least one character). - items: - type: string - type: array - namespaceSelector: - description: |- - NamespaceSelector is a label selector for the resource namespace. Label keys and values - in `matchLabels` support the wildcard characters `*` (matches zero or many characters) - and `?` (matches one character).Wildcards allows writing label selectors like - ["storage.k8s.io/*": "*"]. Note that using ["*" : "*"] matches any key and value but - does not match an empty label set. - properties: - matchExpressions: - description: matchExpressions is a list of - label selector requirements. The requirements - are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key that - the selector applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - namespaces: - description: |- - Namespaces is a list of namespaces names. Each name supports wildcard characters - "*" (matches zero or many characters) and "?" (at least one character). - items: - type: string - type: array - operations: - description: Operations can contain values ["CREATE, - "UPDATE", "CONNECT", "DELETE"], which are used - to match a specific action. - items: - description: AdmissionOperation can have one - of the values CREATE, UPDATE, CONNECT, DELETE, - which are used to match a specific action. - enum: - - CREATE - - CONNECT - - UPDATE - - DELETE - type: string - type: array - selector: - description: |- - Selector is a label selector. Label keys and values in `matchLabels` support the wildcard - characters `*` (matches zero or many characters) and `?` (matches one character). - Wildcards allows writing label selectors like ["storage.k8s.io/*": "*"]. Note that - using ["*" : "*"] matches any key and value but does not match an empty label set. - properties: - matchExpressions: - description: matchExpressions is a list of - label selector requirements. The requirements - are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key that - the selector applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - type: object - roles: - description: Roles is the list of namespaced role - names for the user. - items: - type: string - type: array - subjects: - description: Subjects is the list of subject names - like users, user groups, and service accounts. - items: - description: |- - Subject contains a reference to the object or user identities a role binding applies to. This can either hold a direct API object reference, - or a value for non-objects such as user and group names. - properties: - apiGroup: - description: |- - APIGroup holds the API group of the referenced subject. - Defaults to "" for ServiceAccount subjects. - Defaults to "rbac.authorization.k8s.io" for User and Group subjects. - type: string - kind: - description: |- - Kind of object being referenced. Values defined by this API group are "User", "Group", and "ServiceAccount". - If the Authorizer does not recognized the kind value, the Authorizer should report an error. - type: string - name: - description: Name of the object being referenced. - type: string - namespace: - description: |- - Namespace of the referenced object. If the object kind is non-namespace, such as "User" or "Group", and this value is not empty - the Authorizer should report an error. - type: string - required: - - kind - - name - type: object - x-kubernetes-map-type: atomic - type: array - type: object - type: array - clusterRoles: - description: ClusterRoles is the list of cluster-wide role - names for the user. - items: - type: string - type: array - resources: - description: |- - ResourceDescription contains information about the resource being created or modified. - Requires at least one tag to be specified when under MatchResources. - Specifying ResourceDescription directly under match is being deprecated. - Please specify under "any" or "all" instead. - not: - required: - - name - - names - properties: - annotations: - additionalProperties: - type: string - description: |- - Annotations is a map of annotations (key-value pairs of type string). Annotation keys - and values support the wildcard characters "*" (matches zero or many characters) and - "?" (matches at least one character). - type: object - kinds: - description: Kinds is a list of resource kinds. - items: - type: string - type: array - name: - description: |- - Name is the name of the resource. The name supports wildcard characters - "*" (matches zero or many characters) and "?" (at least one character). - NOTE: "Name" is being deprecated in favor of "Names". - type: string - names: - description: |- - Names are the names of the resources. Each name supports wildcard characters - "*" (matches zero or many characters) and "?" (at least one character). - items: - type: string - type: array - namespaceSelector: - description: |- - NamespaceSelector is a label selector for the resource namespace. Label keys and values - in `matchLabels` support the wildcard characters `*` (matches zero or many characters) - and `?` (matches one character).Wildcards allows writing label selectors like - ["storage.k8s.io/*": "*"]. Note that using ["*" : "*"] matches any key and value but - does not match an empty label set. - properties: - matchExpressions: - description: matchExpressions is a list of label - selector requirements. The requirements are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key that the - selector applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - namespaces: - description: |- - Namespaces is a list of namespaces names. Each name supports wildcard characters - "*" (matches zero or many characters) and "?" (at least one character). - items: - type: string - type: array - operations: - description: Operations can contain values ["CREATE, - "UPDATE", "CONNECT", "DELETE"], which are used to - match a specific action. - items: - description: AdmissionOperation can have one of the - values CREATE, UPDATE, CONNECT, DELETE, which are - used to match a specific action. - enum: - - CREATE - - CONNECT - - UPDATE - - DELETE - type: string - type: array - selector: - description: |- - Selector is a label selector. Label keys and values in `matchLabels` support the wildcard - characters `*` (matches zero or many characters) and `?` (matches one character). - Wildcards allows writing label selectors like ["storage.k8s.io/*": "*"]. Note that - using ["*" : "*"] matches any key and value but does not match an empty label set. - properties: - matchExpressions: - description: matchExpressions is a list of label - selector requirements. The requirements are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key that the - selector applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - type: object - roles: - description: Roles is the list of namespaced role names - for the user. - items: - type: string - type: array - subjects: - description: Subjects is the list of subject names like - users, user groups, and service accounts. - items: - description: |- - Subject contains a reference to the object or user identities a role binding applies to. This can either hold a direct API object reference, - or a value for non-objects such as user and group names. - properties: - apiGroup: - description: |- - APIGroup holds the API group of the referenced subject. - Defaults to "" for ServiceAccount subjects. - Defaults to "rbac.authorization.k8s.io" for User and Group subjects. - type: string - kind: - description: |- - Kind of object being referenced. Values defined by this API group are "User", "Group", and "ServiceAccount". - If the Authorizer does not recognized the kind value, the Authorizer should report an error. - type: string - name: - description: Name of the object being referenced. - type: string - namespace: - description: |- - Namespace of the referenced object. If the object kind is non-namespace, such as "User" or "Group", and this value is not empty - the Authorizer should report an error. - type: string - required: - - kind - - name - type: object - x-kubernetes-map-type: atomic - type: array - type: object - mutate: - description: Mutation is used to modify matching resources. - properties: - foreach: - description: ForEach applies mutation rules to a list of - sub-elements by creating a context for each entry in the - list and looping over it to apply the specified logic. - items: - description: ForEachMutation applies mutation rules to - a list of sub-elements by creating a context for each - entry in the list and looping over it to apply the specified - logic. - properties: - context: - description: Context defines variables and data sources - that can be used during rule execution. - items: - description: |- - ContextEntry adds variables and data sources to a rule Context. Either a - ConfigMap reference or a APILookup must be provided. - oneOf: - - required: - - configMap - - required: - - apiCall - - required: - - imageRegistry - - required: - - variable - - required: - - globalReference - properties: - apiCall: - description: |- - APICall is an HTTP request to the Kubernetes API server, or other JSON web service. - The data returned is stored in the context with the name for the context entry. - properties: - data: - description: |- - The data object specifies the POST data sent to the server. - Only applicable when the method field is set to POST. - items: - description: RequestData contains the - HTTP POST data - properties: - key: - description: Key is a unique identifier - for the data value - type: string - value: - description: Value is the data value - x-kubernetes-preserve-unknown-fields: true - required: - - key - - value - type: object - type: array - default: - description: |- - Default is an optional arbitrary JSON object that the context - value is set to, if the apiCall returns error. - x-kubernetes-preserve-unknown-fields: true - jmesPath: - description: |- - JMESPath is an optional JSON Match Expression that can be used to - transform the JSON response returned from the server. For example - a JMESPath of "items | length(@)" applied to the API server response - for the URLPath "/apis/apps/v1/deployments" will return the total count - of deployments across all namespaces. - type: string - method: - default: GET - description: Method is the HTTP request - type (GET or POST). Defaults to GET. - enum: - - GET - - POST - type: string - service: - description: |- - Service is an API call to a JSON web service. - This is used for non-Kubernetes API server calls. - It's mutually exclusive with the URLPath field. - properties: - caBundle: - description: |- - CABundle is a PEM encoded CA bundle which will be used to validate - the server certificate. - type: string - headers: - description: Headers is a list of optional - HTTP headers to be included in the - request. - items: - properties: - key: - description: Key is the header - key - type: string - value: - description: Value is the header - value - type: string - required: - - key - - value - type: object - type: array - url: - description: |- - URL is the JSON web service URL. A typical form is - `https://{service}.{namespace}:{port}/{path}`. - type: string - required: - - url - type: object - urlPath: - description: |- - URLPath is the URL path to be used in the HTTP GET or POST request to the - Kubernetes API server (e.g. "/api/v1/namespaces" or "/apis/apps/v1/deployments"). - The format required is the same format used by the `kubectl get --raw` command. - See https://kyverno.io/docs/writing-policies/external-data-sources/#variables-from-kubernetes-api-server-calls - for details. - It's mutually exclusive with the Service field. - type: string - type: object - configMap: - description: ConfigMap is the ConfigMap reference. - properties: - name: - description: Name is the ConfigMap name. - type: string - namespace: - description: Namespace is the ConfigMap - namespace. - type: string - required: - - name - type: object - globalReference: - description: GlobalContextEntryReference is - a reference to a cached global context entry. - properties: - jmesPath: - description: |- - JMESPath is an optional JSON Match Expression that can be used to - transform the JSON response returned from the server. For example - a JMESPath of "items | length(@)" applied to the API server response - for the URLPath "/apis/apps/v1/deployments" will return the total count - of deployments across all namespaces. - type: string - name: - description: Name of the global context - entry - type: string - required: - - name - type: object - imageRegistry: - description: |- - ImageRegistry defines requests to an OCI/Docker V2 registry to fetch image - details. - properties: - imageRegistryCredentials: - description: ImageRegistryCredentials provides - credentials that will be used for authentication - with registry - properties: - allowInsecureRegistry: - description: AllowInsecureRegistry allows - insecure access to a registry. - type: boolean - providers: - description: |- - Providers specifies a list of OCI Registry names, whose authentication providers are provided. - It can be of one of these values: default,google,azure,amazon,github. - items: - description: ImageRegistryCredentialsProvidersType - provides the list of credential - providers required. - enum: - - default - - amazon - - azure - - google - - github - type: string - type: array - secrets: - description: |- - Secrets specifies a list of secrets that are provided for credentials. - Secrets must live in the Kyverno namespace. - items: - type: string - type: array - type: object - jmesPath: - description: |- - JMESPath is an optional JSON Match Expression that can be used to - transform the ImageData struct returned as a result of processing - the image reference. - type: string - reference: - description: |- - Reference is image reference to a container image in the registry. - Example: ghcr.io/kyverno/kyverno:latest - type: string - required: - - reference - type: object - name: - description: Name is the variable name. - type: string - variable: - description: Variable defines an arbitrary JMESPath - context variable that can be defined inline. - properties: - default: - description: |- - Default is an optional arbitrary JSON object that the variable may take if the JMESPath - expression evaluates to nil - x-kubernetes-preserve-unknown-fields: true - jmesPath: - description: |- - JMESPath is an optional JMESPath Expression that can be used to - transform the variable. - type: string - value: - description: Value is any arbitrary JSON - object representable in YAML or JSON form. - x-kubernetes-preserve-unknown-fields: true - type: object - required: - - name - type: object - type: array - foreach: - description: Foreach declares a nested foreach iterator - x-kubernetes-preserve-unknown-fields: true - list: - description: |- - List specifies a JMESPath expression that results in one or more elements - to which the validation logic is applied. - type: string - order: - description: |- - Order defines the iteration order on the list. - Can be Ascending to iterate from first to last element or Descending to iterate in from last to first element. - enum: - - Ascending - - Descending - type: string - patchStrategicMerge: - description: |- - PatchStrategicMerge is a strategic merge patch used to modify resources. - See https://kubernetes.io/docs/tasks/manage-kubernetes-objects/update-api-object-kubectl-patch/ - and https://kubectl.docs.kubernetes.io/references/kustomize/kustomization/patchesstrategicmerge/. - x-kubernetes-preserve-unknown-fields: true - patchesJson6902: - description: |- - PatchesJSON6902 is a list of RFC 6902 JSON Patch declarations used to modify resources. - See https://tools.ietf.org/html/rfc6902 and https://kubectl.docs.kubernetes.io/references/kustomize/kustomization/patchesjson6902/. - type: string - preconditions: - description: |- - AnyAllConditions are used to determine if a policy rule should be applied by evaluating a - set of conditions. The declaration can contain nested `any` or `all` statements. - See: https://kyverno.io/docs/writing-policies/preconditions/ - properties: - all: - description: |- - AllConditions enable variable-based conditional rule execution. This is useful for - finer control of when an rule is applied. A condition can reference object data - using JMESPath notation. - Here, all of the conditions need to pass - items: - description: Condition defines variable-based - conditional criteria for rule execution. - properties: - key: - description: Key is the context entry (using - JMESPath) for conditional rule evaluation. - x-kubernetes-preserve-unknown-fields: true - message: - description: Message is an optional display - message - type: string - operator: - description: |- - Operator is the conditional operation to perform. Valid operators are: - Equals, NotEquals, In, AnyIn, AllIn, NotIn, AnyNotIn, AllNotIn, GreaterThanOrEquals, - GreaterThan, LessThanOrEquals, LessThan, DurationGreaterThanOrEquals, DurationGreaterThan, - DurationLessThanOrEquals, DurationLessThan - enum: - - Equals - - NotEquals - - In - - AnyIn - - AllIn - - NotIn - - AnyNotIn - - AllNotIn - - GreaterThanOrEquals - - GreaterThan - - LessThanOrEquals - - LessThan - - DurationGreaterThanOrEquals - - DurationGreaterThan - - DurationLessThanOrEquals - - DurationLessThan - type: string - value: - description: |- - Value is the conditional value, or set of values. The values can be fixed set - or can be variables declared using JMESPath. - x-kubernetes-preserve-unknown-fields: true - type: object - type: array - any: - description: |- - AnyConditions enable variable-based conditional rule execution. This is useful for - finer control of when an rule is applied. A condition can reference object data - using JMESPath notation. - Here, at least one of the conditions need to pass - items: - description: Condition defines variable-based - conditional criteria for rule execution. - properties: - key: - description: Key is the context entry (using - JMESPath) for conditional rule evaluation. - x-kubernetes-preserve-unknown-fields: true - message: - description: Message is an optional display - message - type: string - operator: - description: |- - Operator is the conditional operation to perform. Valid operators are: - Equals, NotEquals, In, AnyIn, AllIn, NotIn, AnyNotIn, AllNotIn, GreaterThanOrEquals, - GreaterThan, LessThanOrEquals, LessThan, DurationGreaterThanOrEquals, DurationGreaterThan, - DurationLessThanOrEquals, DurationLessThan - enum: - - Equals - - NotEquals - - In - - AnyIn - - AllIn - - NotIn - - AnyNotIn - - AllNotIn - - GreaterThanOrEquals - - GreaterThan - - LessThanOrEquals - - LessThan - - DurationGreaterThanOrEquals - - DurationGreaterThan - - DurationLessThanOrEquals - - DurationLessThan - type: string - value: - description: |- - Value is the conditional value, or set of values. The values can be fixed set - or can be variables declared using JMESPath. - x-kubernetes-preserve-unknown-fields: true - type: object - type: array - type: object - x-kubernetes-preserve-unknown-fields: true - type: object - type: array - mutateExistingOnPolicyUpdate: - description: MutateExistingOnPolicyUpdate controls if the - mutateExisting rule will be applied on policy events. - type: boolean - patchStrategicMerge: - description: |- - PatchStrategicMerge is a strategic merge patch used to modify resources. - See https://kubernetes.io/docs/tasks/manage-kubernetes-objects/update-api-object-kubectl-patch/ - and https://kubectl.docs.kubernetes.io/references/kustomize/kustomization/patchesstrategicmerge/. - x-kubernetes-preserve-unknown-fields: true - patchesJson6902: - description: |- - PatchesJSON6902 is a list of RFC 6902 JSON Patch declarations used to modify resources. - See https://tools.ietf.org/html/rfc6902 and https://kubectl.docs.kubernetes.io/references/kustomize/kustomization/patchesjson6902/. - type: string - targets: - description: Targets defines the target resources to be - mutated. - items: - description: TargetResourceSpec defines targets for mutating - existing resources. - properties: - apiVersion: - description: APIVersion specifies resource apiVersion. - type: string - context: - description: Context defines variables and data sources - that can be used during rule execution. - items: - description: |- - ContextEntry adds variables and data sources to a rule Context. Either a - ConfigMap reference or a APILookup must be provided. - oneOf: - - required: - - configMap - - required: - - apiCall - - required: - - imageRegistry - - required: - - variable - - required: - - globalReference - properties: - apiCall: - description: |- - APICall is an HTTP request to the Kubernetes API server, or other JSON web service. - The data returned is stored in the context with the name for the context entry. - properties: - data: - description: |- - The data object specifies the POST data sent to the server. - Only applicable when the method field is set to POST. - items: - description: RequestData contains the - HTTP POST data - properties: - key: - description: Key is a unique identifier - for the data value - type: string - value: - description: Value is the data value - x-kubernetes-preserve-unknown-fields: true - required: - - key - - value - type: object - type: array - default: - description: |- - Default is an optional arbitrary JSON object that the context - value is set to, if the apiCall returns error. - x-kubernetes-preserve-unknown-fields: true - jmesPath: - description: |- - JMESPath is an optional JSON Match Expression that can be used to - transform the JSON response returned from the server. For example - a JMESPath of "items | length(@)" applied to the API server response - for the URLPath "/apis/apps/v1/deployments" will return the total count - of deployments across all namespaces. - type: string - method: - default: GET - description: Method is the HTTP request - type (GET or POST). Defaults to GET. - enum: - - GET - - POST - type: string - service: - description: |- - Service is an API call to a JSON web service. - This is used for non-Kubernetes API server calls. - It's mutually exclusive with the URLPath field. - properties: - caBundle: - description: |- - CABundle is a PEM encoded CA bundle which will be used to validate - the server certificate. - type: string - headers: - description: Headers is a list of optional - HTTP headers to be included in the - request. - items: - properties: - key: - description: Key is the header - key - type: string - value: - description: Value is the header - value - type: string - required: - - key - - value - type: object - type: array - url: - description: |- - URL is the JSON web service URL. A typical form is - `https://{service}.{namespace}:{port}/{path}`. - type: string - required: - - url - type: object - urlPath: - description: |- - URLPath is the URL path to be used in the HTTP GET or POST request to the - Kubernetes API server (e.g. "/api/v1/namespaces" or "/apis/apps/v1/deployments"). - The format required is the same format used by the `kubectl get --raw` command. - See https://kyverno.io/docs/writing-policies/external-data-sources/#variables-from-kubernetes-api-server-calls - for details. - It's mutually exclusive with the Service field. - type: string - type: object - configMap: - description: ConfigMap is the ConfigMap reference. - properties: - name: - description: Name is the ConfigMap name. - type: string - namespace: - description: Namespace is the ConfigMap - namespace. - type: string - required: - - name - type: object - globalReference: - description: GlobalContextEntryReference is - a reference to a cached global context entry. - properties: - jmesPath: - description: |- - JMESPath is an optional JSON Match Expression that can be used to - transform the JSON response returned from the server. For example - a JMESPath of "items | length(@)" applied to the API server response - for the URLPath "/apis/apps/v1/deployments" will return the total count - of deployments across all namespaces. - type: string - name: - description: Name of the global context - entry - type: string - required: - - name - type: object - imageRegistry: - description: |- - ImageRegistry defines requests to an OCI/Docker V2 registry to fetch image - details. - properties: - imageRegistryCredentials: - description: ImageRegistryCredentials provides - credentials that will be used for authentication - with registry - properties: - allowInsecureRegistry: - description: AllowInsecureRegistry allows - insecure access to a registry. - type: boolean - providers: - description: |- - Providers specifies a list of OCI Registry names, whose authentication providers are provided. - It can be of one of these values: default,google,azure,amazon,github. - items: - description: ImageRegistryCredentialsProvidersType - provides the list of credential - providers required. - enum: - - default - - amazon - - azure - - google - - github - type: string - type: array - secrets: - description: |- - Secrets specifies a list of secrets that are provided for credentials. - Secrets must live in the Kyverno namespace. - items: - type: string - type: array - type: object - jmesPath: - description: |- - JMESPath is an optional JSON Match Expression that can be used to - transform the ImageData struct returned as a result of processing - the image reference. - type: string - reference: - description: |- - Reference is image reference to a container image in the registry. - Example: ghcr.io/kyverno/kyverno:latest - type: string - required: - - reference - type: object - name: - description: Name is the variable name. - type: string - variable: - description: Variable defines an arbitrary JMESPath - context variable that can be defined inline. - properties: - default: - description: |- - Default is an optional arbitrary JSON object that the variable may take if the JMESPath - expression evaluates to nil - x-kubernetes-preserve-unknown-fields: true - jmesPath: - description: |- - JMESPath is an optional JMESPath Expression that can be used to - transform the variable. - type: string - value: - description: Value is any arbitrary JSON - object representable in YAML or JSON form. - x-kubernetes-preserve-unknown-fields: true - type: object - required: - - name - type: object - type: array - kind: - description: Kind specifies resource kind. - type: string - name: - description: Name specifies the resource name. - type: string - namespace: - description: Namespace specifies resource namespace. - type: string - preconditions: - description: |- - Preconditions are used to determine if a policy rule should be applied by evaluating a - set of conditions. The declaration can contain nested `any` or `all` statements. A direct list - of conditions (without `any` or `all` statements is supported for backwards compatibility but - will be deprecated in the next major release. - See: https://kyverno.io/docs/writing-policies/preconditions/ - x-kubernetes-preserve-unknown-fields: true - selector: - description: Selector allows you to select target - resources with their labels. - properties: - matchExpressions: - description: matchExpressions is a list of label - selector requirements. The requirements are - ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key that the - selector applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - uid: - description: UID specifies the resource uid. - type: string - type: object - type: array - type: object - name: - description: Name is a label to identify the rule, It must be - unique within the policy. - maxLength: 63 - type: string - preconditions: - description: |- - Preconditions are used to determine if a policy rule should be applied by evaluating a - set of conditions. The declaration can contain nested `any` or `all` statements. A direct list - of conditions (without `any` or `all` statements is supported for backwards compatibility but - will be deprecated in the next major release. - See: https://kyverno.io/docs/writing-policies/preconditions/ - x-kubernetes-preserve-unknown-fields: true - reportProperties: - additionalProperties: - type: string - description: ReportProperties are the additional properties - from the rule that will be added to the policy report result - type: object - skipBackgroundRequests: - default: true - description: |- - SkipBackgroundRequests bypasses admission requests that are sent by the background controller. - The default value is set to "true", it must be set to "false" to apply - generate and mutateExisting rules to those requests. - type: boolean - validate: - description: Validation is used to validate matching resources. - properties: - allowExistingViolations: - default: true - description: AllowExistingViolations allows prexisting violating - resources to continue violating a policy. - type: boolean - anyPattern: - description: |- - AnyPattern specifies list of validation patterns. At least one of the patterns - must be satisfied for the validation rule to succeed. - x-kubernetes-preserve-unknown-fields: true - assert: - description: Assert defines a kyverno-json assertion tree. - type: object - x-kubernetes-preserve-unknown-fields: true - cel: - description: CEL allows validation checks using the Common - Expression Language (https://kubernetes.io/docs/reference/using-api/cel/). - properties: - auditAnnotations: - description: AuditAnnotations contains CEL expressions - which are used to produce audit annotations for the - audit event of the API request. - items: - description: AuditAnnotation describes how to produce - an audit annotation for an API request. - properties: - key: - description: |- - key specifies the audit annotation key. The audit annotation keys of - a ValidatingAdmissionPolicy must be unique. The key must be a qualified - name ([A-Za-z0-9][-A-Za-z0-9_.]*) no more than 63 bytes in length. - - The key is combined with the resource name of the - ValidatingAdmissionPolicy to construct an audit annotation key: - "{ValidatingAdmissionPolicy name}/{key}". - - If an admission webhook uses the same resource name as this ValidatingAdmissionPolicy - and the same audit annotation key, the annotation key will be identical. - In this case, the first annotation written with the key will be included - in the audit event and all subsequent annotations with the same key - will be discarded. - - Required. - type: string - valueExpression: - description: |- - valueExpression represents the expression which is evaluated by CEL to - produce an audit annotation value. The expression must evaluate to either - a string or null value. If the expression evaluates to a string, the - audit annotation is included with the string value. If the expression - evaluates to null or empty string the audit annotation will be omitted. - The valueExpression may be no longer than 5kb in length. - If the result of the valueExpression is more than 10kb in length, it - will be truncated to 10kb. - - If multiple ValidatingAdmissionPolicyBinding resources match an - API request, then the valueExpression will be evaluated for - each binding. All unique values produced by the valueExpressions - will be joined together in a comma-separated list. - - Required. - type: string - required: - - key - - valueExpression - type: object - type: array - expressions: - description: Expressions is a list of CELExpression - types. - items: - description: Validation specifies the CEL expression - which is used to apply the validation. - properties: - expression: - description: "Expression represents the expression - which will be evaluated by CEL.\nref: https://github.com/google/cel-spec\nCEL - expressions have access to the contents of the - API request/response, organized into CEL variables - as well as some other useful variables:\n\n- - 'object' - The object from the incoming request. - The value is null for DELETE requests.\n- 'oldObject' - - The existing object. The value is null for - CREATE requests.\n- 'request' - Attributes of - the API request([ref](/pkg/apis/admission/types.go#AdmissionRequest)).\n- - 'params' - Parameter resource referred to by - the policy binding being evaluated. Only populated - if the policy has a ParamKind.\n- 'namespaceObject' - - The namespace object that the incoming object - belongs to. The value is null for cluster-scoped - resources.\n- 'variables' - Map of composited - variables, from its name to its lazily evaluated - value.\n For example, a variable named 'foo' - can be accessed as 'variables.foo'.\n- 'authorizer' - - A CEL Authorizer. May be used to perform authorization - checks for the principal (user or service account) - of the request.\n See https://pkg.go.dev/k8s.io/apiserver/pkg/cel/library#Authz\n- - 'authorizer.requestResource' - A CEL ResourceCheck - constructed from the 'authorizer' and configured - with the\n request resource.\n\nThe `apiVersion`, - `kind`, `metadata.name` and `metadata.generateName` - are always accessible from the root of the\nobject. - No other metadata properties are accessible.\n\nOnly - property names of the form `[a-zA-Z_.-/][a-zA-Z0-9_.-/]*` - are accessible.\nAccessible property names are - escaped according to the following rules when - accessed in the expression:\n- '__' escapes - to '__underscores__'\n- '.' escapes to '__dot__'\n- - '-' escapes to '__dash__'\n- '/' escapes to - '__slash__'\n- Property names that exactly match - a CEL RESERVED keyword escape to '__{keyword}__'. - The keywords are:\n\t \"true\", \"false\", - \"null\", \"in\", \"as\", \"break\", \"const\", - \"continue\", \"else\", \"for\", \"function\", - \"if\",\n\t \"import\", \"let\", \"loop\", - \"package\", \"namespace\", \"return\".\nExamples:\n - \ - Expression accessing a property named \"namespace\": - {\"Expression\": \"object.__namespace__ > 0\"}\n - \ - Expression accessing a property named \"x-prop\": - {\"Expression\": \"object.x__dash__prop > 0\"}\n - \ - Expression accessing a property named \"redact__d\": - {\"Expression\": \"object.redact__underscores__d - > 0\"}\n\nEquality on arrays with list type - of 'set' or 'map' ignores element order, i.e. - [1, 2] == [2, 1].\nConcatenation on arrays with - x-kubernetes-list-type use the semantics of - the list type:\n - 'set': `X + Y` performs - a union where the array positions of all elements - in `X` are preserved and\n non-intersecting - elements in `Y` are appended, retaining their - partial order.\n - 'map': `X + Y` performs - a merge where the array positions of all keys - in `X` are preserved but the values\n are - overwritten by values in `Y` when the key sets - of `X` and `Y` intersect. Elements in `Y` with\n - \ non-intersecting keys are appended, retaining - their partial order.\nRequired." - type: string - message: - description: |- - Message represents the message displayed when validation fails. The message is required if the Expression contains - line breaks. The message must not contain line breaks. - If unset, the message is "failed rule: {Rule}". - e.g. "must be a URL with the host matching spec.host" - If the Expression contains line breaks. Message is required. - The message must not contain line breaks. - If unset, the message is "failed Expression: {Expression}". - type: string - messageExpression: - description: |- - messageExpression declares a CEL expression that evaluates to the validation failure message that is returned when this rule fails. - Since messageExpression is used as a failure message, it must evaluate to a string. - If both message and messageExpression are present on a validation, then messageExpression will be used if validation fails. - If messageExpression results in a runtime error, the runtime error is logged, and the validation failure message is produced - as if the messageExpression field were unset. If messageExpression evaluates to an empty string, a string with only spaces, or a string - that contains line breaks, then the validation failure message will also be produced as if the messageExpression field were unset, and - the fact that messageExpression produced an empty string/string with only spaces/string with line breaks will be logged. - messageExpression has access to all the same variables as the `expression` except for 'authorizer' and 'authorizer.requestResource'. - Example: - "object.x must be less than max ("+string(params.max)+")" - type: string - reason: - description: |- - Reason represents a machine-readable description of why this validation failed. - If this is the first validation in the list to fail, this reason, as well as the - corresponding HTTP response code, are used in the - HTTP response to the client. - The currently supported reasons are: "Unauthorized", "Forbidden", "Invalid", "RequestEntityTooLarge". - If not set, StatusReasonInvalid is used in the response to the client. - type: string - required: - - expression - type: object - type: array - generate: - default: false - description: |- - Generate specifies whether to generate a Kubernetes ValidatingAdmissionPolicy from the rule. - Optional. Defaults to "false" if not specified. - type: boolean - paramKind: - description: ParamKind is a tuple of Group Kind and - Version. - properties: - apiVersion: - description: |- - APIVersion is the API group version the resources belong to. - In format of "group/version". - Required. - type: string - kind: - description: |- - Kind is the API kind the resources belong to. - Required. - type: string - type: object - x-kubernetes-map-type: atomic - paramRef: - description: ParamRef references a parameter resource. - properties: - name: - description: |- - name is the name of the resource being referenced. - - One of `name` or `selector` must be set, but `name` and `selector` are - mutually exclusive properties. If one is set, the other must be unset. - - A single parameter used for all admission requests can be configured - by setting the `name` field, leaving `selector` blank, and setting namespace - if `paramKind` is namespace-scoped. - type: string - namespace: - description: |- - namespace is the namespace of the referenced resource. Allows limiting - the search for params to a specific namespace. Applies to both `name` and - `selector` fields. - - A per-namespace parameter may be used by specifying a namespace-scoped - `paramKind` in the policy and leaving this field empty. - - - If `paramKind` is cluster-scoped, this field MUST be unset. Setting this - field results in a configuration error. - - - If `paramKind` is namespace-scoped, the namespace of the object being - evaluated for admission will be used when this field is left unset. Take - care that if this is left empty the binding must not match any cluster-scoped - resources, which will result in an error. - type: string - parameterNotFoundAction: - description: |- - `parameterNotFoundAction` controls the behavior of the binding when the resource - exists, and name or selector is valid, but there are no parameters - matched by the binding. If the value is set to `Allow`, then no - matched parameters will be treated as successful validation by the binding. - If set to `Deny`, then no matched parameters will be subject to the - `failurePolicy` of the policy. - - Allowed values are `Allow` or `Deny` - - Required - type: string - selector: - description: |- - selector can be used to match multiple param objects based on their labels. - Supply selector: {} to match all resources of the ParamKind. - - If multiple params are found, they are all evaluated with the policy expressions - and the results are ANDed together. - - One of `name` or `selector` must be set, but `name` and `selector` are - mutually exclusive properties. If one is set, the other must be unset. - properties: - matchExpressions: - description: matchExpressions is a list of label - selector requirements. The requirements are - ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key that - the selector applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - type: object - x-kubernetes-map-type: atomic - variables: - description: |- - Variables contain definitions of variables that can be used in composition of other expressions. - Each variable is defined as a named CEL expression. - The variables defined here will be available under `variables` in other expressions of the policy. - items: - description: Variable is the definition of a variable - that is used for composition. A variable is defined - as a named expression. - properties: - expression: - description: |- - Expression is the expression that will be evaluated as the value of the variable. - The CEL expression has access to the same identifiers as the CEL expressions in Validation. - type: string - name: - description: |- - Name is the name of the variable. The name must be a valid CEL identifier and unique among all variables. - The variable can be accessed in other expressions through `variables` - For example, if name is "foo", the variable will be available as `variables.foo` - type: string - required: - - expression - - name - type: object - x-kubernetes-map-type: atomic - type: array - type: object - deny: - description: Deny defines conditions used to pass or fail - a validation rule. - properties: - conditions: - description: |- - Multiple conditions can be declared under an `any` or `all` statement. A direct list - of conditions (without `any` or `all` statements) is also supported for backwards compatibility - but will be deprecated in the next major release. - See: https://kyverno.io/docs/writing-policies/validate/#deny-rules - x-kubernetes-preserve-unknown-fields: true - type: object - failureAction: - description: |- - FailureAction defines if a validation policy rule violation should block - the admission review request (Enforce), or allow (Audit) the admission review request - and report an error in a policy report. Optional. - Allowed values are Audit or Enforce. - enum: - - Audit - - Enforce - type: string - failureActionOverrides: - description: |- - FailureActionOverrides is a Cluster Policy attribute that specifies FailureAction - namespace-wise. It overrides FailureAction for the specified namespaces. - items: - properties: - action: - description: ValidationFailureAction defines the policy - validation failure action - enum: - - audit - - enforce - - Audit - - Enforce - type: string - namespaceSelector: - description: |- - A label selector is a label query over a set of resources. The result of matchLabels and - matchExpressions are ANDed. An empty label selector matches all objects. A null - label selector matches no objects. - properties: - matchExpressions: - description: matchExpressions is a list of label - selector requirements. The requirements are - ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key that the - selector applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - namespaces: - items: - type: string - type: array - type: object - type: array - foreach: - description: ForEach applies validate rules to a list of - sub-elements by creating a context for each entry in the - list and looping over it to apply the specified logic. - items: - description: ForEachValidation applies validate rules - to a list of sub-elements by creating a context for - each entry in the list and looping over it to apply - the specified logic. - properties: - anyPattern: - description: |- - AnyPattern specifies list of validation patterns. At least one of the patterns - must be satisfied for the validation rule to succeed. - x-kubernetes-preserve-unknown-fields: true - context: - description: Context defines variables and data sources - that can be used during rule execution. - items: - description: |- - ContextEntry adds variables and data sources to a rule Context. Either a - ConfigMap reference or a APILookup must be provided. - oneOf: - - required: - - configMap - - required: - - apiCall - - required: - - imageRegistry - - required: - - variable - - required: - - globalReference - properties: - apiCall: - description: |- - APICall is an HTTP request to the Kubernetes API server, or other JSON web service. - The data returned is stored in the context with the name for the context entry. - properties: - data: - description: |- - The data object specifies the POST data sent to the server. - Only applicable when the method field is set to POST. - items: - description: RequestData contains the - HTTP POST data - properties: - key: - description: Key is a unique identifier - for the data value - type: string - value: - description: Value is the data value - x-kubernetes-preserve-unknown-fields: true - required: - - key - - value - type: object - type: array - default: - description: |- - Default is an optional arbitrary JSON object that the context - value is set to, if the apiCall returns error. - x-kubernetes-preserve-unknown-fields: true - jmesPath: - description: |- - JMESPath is an optional JSON Match Expression that can be used to - transform the JSON response returned from the server. For example - a JMESPath of "items | length(@)" applied to the API server response - for the URLPath "/apis/apps/v1/deployments" will return the total count - of deployments across all namespaces. - type: string - method: - default: GET - description: Method is the HTTP request - type (GET or POST). Defaults to GET. - enum: - - GET - - POST - type: string - service: - description: |- - Service is an API call to a JSON web service. - This is used for non-Kubernetes API server calls. - It's mutually exclusive with the URLPath field. - properties: - caBundle: - description: |- - CABundle is a PEM encoded CA bundle which will be used to validate - the server certificate. - type: string - headers: - description: Headers is a list of optional - HTTP headers to be included in the - request. - items: - properties: - key: - description: Key is the header - key - type: string - value: - description: Value is the header - value - type: string - required: - - key - - value - type: object - type: array - url: - description: |- - URL is the JSON web service URL. A typical form is - `https://{service}.{namespace}:{port}/{path}`. - type: string - required: - - url - type: object - urlPath: - description: |- - URLPath is the URL path to be used in the HTTP GET or POST request to the - Kubernetes API server (e.g. "/api/v1/namespaces" or "/apis/apps/v1/deployments"). - The format required is the same format used by the `kubectl get --raw` command. - See https://kyverno.io/docs/writing-policies/external-data-sources/#variables-from-kubernetes-api-server-calls - for details. - It's mutually exclusive with the Service field. - type: string - type: object - configMap: - description: ConfigMap is the ConfigMap reference. - properties: - name: - description: Name is the ConfigMap name. - type: string - namespace: - description: Namespace is the ConfigMap - namespace. - type: string - required: - - name - type: object - globalReference: - description: GlobalContextEntryReference is - a reference to a cached global context entry. - properties: - jmesPath: - description: |- - JMESPath is an optional JSON Match Expression that can be used to - transform the JSON response returned from the server. For example - a JMESPath of "items | length(@)" applied to the API server response - for the URLPath "/apis/apps/v1/deployments" will return the total count - of deployments across all namespaces. - type: string - name: - description: Name of the global context - entry - type: string - required: - - name - type: object - imageRegistry: - description: |- - ImageRegistry defines requests to an OCI/Docker V2 registry to fetch image - details. - properties: - imageRegistryCredentials: - description: ImageRegistryCredentials provides - credentials that will be used for authentication - with registry - properties: - allowInsecureRegistry: - description: AllowInsecureRegistry allows - insecure access to a registry. - type: boolean - providers: - description: |- - Providers specifies a list of OCI Registry names, whose authentication providers are provided. - It can be of one of these values: default,google,azure,amazon,github. - items: - description: ImageRegistryCredentialsProvidersType - provides the list of credential - providers required. - enum: - - default - - amazon - - azure - - google - - github - type: string - type: array - secrets: - description: |- - Secrets specifies a list of secrets that are provided for credentials. - Secrets must live in the Kyverno namespace. - items: - type: string - type: array - type: object - jmesPath: - description: |- - JMESPath is an optional JSON Match Expression that can be used to - transform the ImageData struct returned as a result of processing - the image reference. - type: string - reference: - description: |- - Reference is image reference to a container image in the registry. - Example: ghcr.io/kyverno/kyverno:latest - type: string - required: - - reference - type: object - name: - description: Name is the variable name. - type: string - variable: - description: Variable defines an arbitrary JMESPath - context variable that can be defined inline. - properties: - default: - description: |- - Default is an optional arbitrary JSON object that the variable may take if the JMESPath - expression evaluates to nil - x-kubernetes-preserve-unknown-fields: true - jmesPath: - description: |- - JMESPath is an optional JMESPath Expression that can be used to - transform the variable. - type: string - value: - description: Value is any arbitrary JSON - object representable in YAML or JSON form. - x-kubernetes-preserve-unknown-fields: true - type: object - required: - - name - type: object - type: array - deny: - description: Deny defines conditions used to pass - or fail a validation rule. - properties: - conditions: - description: |- - Multiple conditions can be declared under an `any` or `all` statement. A direct list - of conditions (without `any` or `all` statements) is also supported for backwards compatibility - but will be deprecated in the next major release. - See: https://kyverno.io/docs/writing-policies/validate/#deny-rules - x-kubernetes-preserve-unknown-fields: true - type: object - elementScope: - description: |- - ElementScope specifies whether to use the current list element as the scope for validation. Defaults to "true" if not specified. - When set to "false", "request.object" is used as the validation scope within the foreach - block to allow referencing other elements in the subtree. - type: boolean - foreach: - description: Foreach declares a nested foreach iterator - x-kubernetes-preserve-unknown-fields: true - list: - description: |- - List specifies a JMESPath expression that results in one or more elements - to which the validation logic is applied. - type: string - pattern: - description: Pattern specifies an overlay-style pattern - used to check resources. - x-kubernetes-preserve-unknown-fields: true - preconditions: - description: |- - AnyAllConditions are used to determine if a policy rule should be applied by evaluating a - set of conditions. The declaration can contain nested `any` or `all` statements. - See: https://kyverno.io/docs/writing-policies/preconditions/ - properties: - all: - description: |- - AllConditions enable variable-based conditional rule execution. This is useful for - finer control of when an rule is applied. A condition can reference object data - using JMESPath notation. - Here, all of the conditions need to pass - items: - description: Condition defines variable-based - conditional criteria for rule execution. - properties: - key: - description: Key is the context entry (using - JMESPath) for conditional rule evaluation. - x-kubernetes-preserve-unknown-fields: true - message: - description: Message is an optional display - message - type: string - operator: - description: |- - Operator is the conditional operation to perform. Valid operators are: - Equals, NotEquals, In, AnyIn, AllIn, NotIn, AnyNotIn, AllNotIn, GreaterThanOrEquals, - GreaterThan, LessThanOrEquals, LessThan, DurationGreaterThanOrEquals, DurationGreaterThan, - DurationLessThanOrEquals, DurationLessThan - enum: - - Equals - - NotEquals - - In - - AnyIn - - AllIn - - NotIn - - AnyNotIn - - AllNotIn - - GreaterThanOrEquals - - GreaterThan - - LessThanOrEquals - - LessThan - - DurationGreaterThanOrEquals - - DurationGreaterThan - - DurationLessThanOrEquals - - DurationLessThan - type: string - value: - description: |- - Value is the conditional value, or set of values. The values can be fixed set - or can be variables declared using JMESPath. - x-kubernetes-preserve-unknown-fields: true - type: object - type: array - any: - description: |- - AnyConditions enable variable-based conditional rule execution. This is useful for - finer control of when an rule is applied. A condition can reference object data - using JMESPath notation. - Here, at least one of the conditions need to pass - items: - description: Condition defines variable-based - conditional criteria for rule execution. - properties: - key: - description: Key is the context entry (using - JMESPath) for conditional rule evaluation. - x-kubernetes-preserve-unknown-fields: true - message: - description: Message is an optional display - message - type: string - operator: - description: |- - Operator is the conditional operation to perform. Valid operators are: - Equals, NotEquals, In, AnyIn, AllIn, NotIn, AnyNotIn, AllNotIn, GreaterThanOrEquals, - GreaterThan, LessThanOrEquals, LessThan, DurationGreaterThanOrEquals, DurationGreaterThan, - DurationLessThanOrEquals, DurationLessThan - enum: - - Equals - - NotEquals - - In - - AnyIn - - AllIn - - NotIn - - AnyNotIn - - AllNotIn - - GreaterThanOrEquals - - GreaterThan - - LessThanOrEquals - - LessThan - - DurationGreaterThanOrEquals - - DurationGreaterThan - - DurationLessThanOrEquals - - DurationLessThan - type: string - value: - description: |- - Value is the conditional value, or set of values. The values can be fixed set - or can be variables declared using JMESPath. - x-kubernetes-preserve-unknown-fields: true - type: object - type: array - type: object - x-kubernetes-preserve-unknown-fields: true - type: object - type: array - manifests: - description: Manifest specifies conditions for manifest - verification - properties: - annotationDomain: - description: AnnotationDomain is custom domain of annotation - for message and signature. Default is "cosign.sigstore.dev". - type: string - attestors: - description: Attestors specified the required attestors - (i.e. authorities) - items: - properties: - count: - description: |- - Count specifies the required number of entries that must match. If the count is null, all entries must match - (a logical AND). If the count is 1, at least one entry must match (a logical OR). If the count contains a - value N, then N must be less than or equal to the size of entries, and at least N entries must match. - minimum: 1 - type: integer - entries: - description: |- - Entries contains the available attestors. An attestor can be a static key, - attributes for keyless verification, or a nested attestor declaration. - items: - properties: - annotations: - additionalProperties: - type: string - description: |- - Annotations are used for image verification. - Every specified key-value pair must exist and match in the verified payload. - The payload may contain other key-value pairs. - type: object - attestor: - description: Attestor is a nested set of - Attestor used to specify a more complex - set of match authorities. - x-kubernetes-preserve-unknown-fields: true - certificates: - description: Certificates specifies one - or more certificates. - properties: - cert: - description: Cert is an optional PEM-encoded - public certificate. - type: string - certChain: - description: CertChain is an optional - PEM encoded set of certificates used - to verify. - type: string - ctlog: - description: |- - CTLog (certificate timestamp log) provides a configuration for validation of Signed Certificate - Timestamps (SCTs). If the value is unset, the default behavior by Cosign is used. - properties: - ignoreSCT: - description: |- - IgnoreSCT defines whether to use the Signed Certificate Timestamp (SCT) log to check for a certificate - timestamp. Default is false. Set to true if this was opted out during signing. - type: boolean - pubkey: - description: PubKey, if set, is - used to validate SCTs against - a custom source. - type: string - tsaCertChain: - description: |- - TSACertChain, if set, is the PEM-encoded certificate chain file for the RFC3161 timestamp authority. Must - contain the root CA certificate. Optionally may contain intermediate CA certificates, and - may contain the leaf TSA certificate if not present in the timestamurce. - type: string - type: object - rekor: - description: |- - Rekor provides configuration for the Rekor transparency log service. If an empty object - is provided the public instance of Rekor (https://rekor.sigstore.dev) is used. - properties: - ignoreTlog: - description: IgnoreTlog skips transparency - log verification. - type: boolean - pubkey: - description: |- - RekorPubKey is an optional PEM-encoded public key to use for a custom Rekor. - If set, this will be used to validate transparency log signatures from a custom Rekor. - type: string - url: - description: URL is the address - of the transparency log. Defaults - to the public Rekor log instance - https://rekor.sigstore.dev. - type: string - type: object - type: object - keyless: - description: |- - Keyless is a set of attribute used to verify a Sigstore keyless attestor. - See https://github.com/sigstore/cosign/blob/main/KEYLESS.md. - properties: - additionalExtensions: - additionalProperties: - type: string - description: AdditionalExtensions are - certificate-extensions used for keyless - signing. - type: object - ctlog: - description: |- - CTLog (certificate timestamp log) provides a configuration for validation of Signed Certificate - Timestamps (SCTs). If the value is unset, the default behavior by Cosign is used. - properties: - ignoreSCT: - description: |- - IgnoreSCT defines whether to use the Signed Certificate Timestamp (SCT) log to check for a certificate - timestamp. Default is false. Set to true if this was opted out during signing. - type: boolean - pubkey: - description: PubKey, if set, is - used to validate SCTs against - a custom source. - type: string - tsaCertChain: - description: |- - TSACertChain, if set, is the PEM-encoded certificate chain file for the RFC3161 timestamp authority. Must - contain the root CA certificate. Optionally may contain intermediate CA certificates, and - may contain the leaf TSA certificate if not present in the timestamurce. - type: string - type: object - issuer: - description: Issuer is the certificate - issuer used for keyless signing. - type: string - issuerRegExp: - description: IssuerRegExp is the regular - expression to match certificate issuer - used for keyless signing. - type: string - rekor: - description: |- - Rekor provides configuration for the Rekor transparency log service. If an empty object - is provided the public instance of Rekor (https://rekor.sigstore.dev) is used. - properties: - ignoreTlog: - description: IgnoreTlog skips transparency - log verification. - type: boolean - pubkey: - description: |- - RekorPubKey is an optional PEM-encoded public key to use for a custom Rekor. - If set, this will be used to validate transparency log signatures from a custom Rekor. - type: string - url: - description: URL is the address - of the transparency log. Defaults - to the public Rekor log instance - https://rekor.sigstore.dev. - type: string - type: object - roots: - description: |- - Roots is an optional set of PEM encoded trusted root certificates. - If not provided, the system roots are used. - type: string - subject: - description: Subject is the verified - identity used for keyless signing, - for example the email address. - type: string - subjectRegExp: - description: SubjectRegExp is the regular - expression to match identity used - for keyless signing, for example the - email address. - type: string - type: object - keys: - description: Keys specifies one or more - public keys. - properties: - ctlog: - description: |- - CTLog (certificate timestamp log) provides a configuration for validation of Signed Certificate - Timestamps (SCTs). If the value is unset, the default behavior by Cosign is used. - properties: - ignoreSCT: - description: |- - IgnoreSCT defines whether to use the Signed Certificate Timestamp (SCT) log to check for a certificate - timestamp. Default is false. Set to true if this was opted out during signing. - type: boolean - pubkey: - description: PubKey, if set, is - used to validate SCTs against - a custom source. - type: string - tsaCertChain: - description: |- - TSACertChain, if set, is the PEM-encoded certificate chain file for the RFC3161 timestamp authority. Must - contain the root CA certificate. Optionally may contain intermediate CA certificates, and - may contain the leaf TSA certificate if not present in the timestamurce. - type: string - type: object - kms: - description: |- - KMS provides the URI to the public key stored in a Key Management System. See: - https://github.com/sigstore/cosign/blob/main/KMS.md - type: string - publicKeys: - description: |- - Keys is a set of X.509 public keys used to verify image signatures. The keys can be directly - specified or can be a variable reference to a key specified in a ConfigMap (see - https://kyverno.io/docs/writing-policies/variables/), or reference a standard Kubernetes Secret - elsewhere in the cluster by specifying it in the format "k8s:///". - The named Secret must specify a key `cosign.pub` containing the public key used for - verification, (see https://github.com/sigstore/cosign/blob/main/KMS.md#kubernetes-secret). - When multiple keys are specified each key is processed as a separate staticKey entry - (.attestors[*].entries.keys) within the set of attestors and the count is applied across the keys. - type: string - rekor: - description: |- - Rekor provides configuration for the Rekor transparency log service. If an empty object - is provided the public instance of Rekor (https://rekor.sigstore.dev) is used. - properties: - ignoreTlog: - description: IgnoreTlog skips transparency - log verification. - type: boolean - pubkey: - description: |- - RekorPubKey is an optional PEM-encoded public key to use for a custom Rekor. - If set, this will be used to validate transparency log signatures from a custom Rekor. - type: string - url: - description: URL is the address - of the transparency log. Defaults - to the public Rekor log instance - https://rekor.sigstore.dev. - type: string - type: object - secret: - description: Reference to a Secret resource - that contains a public key - properties: - name: - description: Name of the secret. - The provided secret must contain - a key named cosign.pub. - type: string - namespace: - description: Namespace name where - the Secret exists. - type: string - required: - - name - - namespace - type: object - signatureAlgorithm: - default: sha256 - description: Deprecated. Use attestor.signatureAlgorithm - instead. - type: string - type: object - repository: - description: |- - Repository is an optional alternate OCI repository to use for signatures and attestations that match this rule. - If specified Repository will override other OCI image repository locations for this Attestor. - type: string - signatureAlgorithm: - default: sha256 - description: Specify signature algorithm - for public keys. Supported values are - sha224, sha256, sha384 and sha512. - type: string - type: object - type: array - type: object - type: array - dryRun: - description: DryRun configuration - properties: - enable: - type: boolean - namespace: - type: string - type: object - ignoreFields: - description: Fields which will be ignored while comparing - manifests. - items: - properties: - fields: - items: - type: string - type: array - objects: - items: - properties: - group: - type: string - kind: - type: string - name: - type: string - namespace: - type: string - version: - type: string - type: object - type: array - type: object - type: array - repository: - description: |- - Repository is an optional alternate OCI repository to use for resource bundle reference. - The repository can be overridden per Attestor or Attestation. - type: string - type: object - message: - description: Message specifies a custom message to be displayed - on failure. - type: string - pattern: - description: Pattern specifies an overlay-style pattern - used to check resources. - x-kubernetes-preserve-unknown-fields: true - podSecurity: - description: |- - PodSecurity applies exemptions for Kubernetes Pod Security admission - by specifying exclusions for Pod Security Standards controls. - properties: - exclude: - description: Exclude specifies the Pod Security Standard - controls to be excluded. - items: - description: PodSecurityStandard specifies the Pod - Security Standard controls to be excluded. - properties: - controlName: - description: |- - ControlName specifies the name of the Pod Security Standard control. - See: https://kubernetes.io/docs/concepts/security/pod-security-standards/ - enum: - - HostProcess - - Host Namespaces - - Privileged Containers - - Capabilities - - HostPath Volumes - - Host Ports - - AppArmor - - SELinux - - /proc Mount Type - - Seccomp - - Sysctls - - Volume Types - - Privilege Escalation - - Running as Non-root - - Running as Non-root user - type: string - images: - description: |- - Images selects matching containers and applies the container level PSS. - Each image is the image name consisting of the registry address, repository, image, and tag. - Empty list matches no containers, PSS checks are applied at the pod level only. - Wildcards ('*' and '?') are allowed. See: https://kubernetes.io/docs/concepts/containers/images. - items: - type: string - type: array - restrictedField: - description: |- - RestrictedField selects the field for the given Pod Security Standard control. - When not set, all restricted fields for the control are selected. - type: string - values: - description: Values defines the allowed values - that can be excluded. - items: - type: string - type: array - required: - - controlName - type: object - type: array - level: - description: |- - Level defines the Pod Security Standard level to be applied to workloads. - Allowed values are privileged, baseline, and restricted. - enum: - - privileged - - baseline - - restricted - type: string - version: - description: |- - Version defines the Pod Security Standard versions that Kubernetes supports. - Allowed values are v1.19, v1.20, v1.21, v1.22, v1.23, v1.24, v1.25, v1.26, v1.27, v1.28, v1.29, latest. Defaults to latest. - enum: - - v1.19 - - v1.20 - - v1.21 - - v1.22 - - v1.23 - - v1.24 - - v1.25 - - v1.26 - - v1.27 - - v1.28 - - v1.29 - - latest - type: string - type: object - type: object - verifyImages: - description: VerifyImages is used to verify image signatures - and mutate them to add a digest - items: - description: |- - ImageVerification validates that images that match the specified pattern - are signed with the supplied public key. Once the image is verified it is - mutated to include the SHA digest retrieved during the registration. - properties: - additionalExtensions: - additionalProperties: - type: string - description: Deprecated. - type: object - annotations: - additionalProperties: - type: string - description: Deprecated. Use annotations per Attestor - instead. - type: object - attestations: - description: |- - Attestations are optional checks for signed in-toto Statements used to verify the image. - See https://github.com/in-toto/attestation. Kyverno fetches signed attestations from the - OCI registry and decodes them into a list of Statement declarations. - items: - description: |- - Attestation are checks for signed in-toto Statements that are used to verify the image. - See https://github.com/in-toto/attestation. Kyverno fetches signed attestations from the - OCI registry and decodes them into a list of Statements. - properties: - attestors: - description: Attestors specify the required attestors - (i.e. authorities). - items: - properties: - count: - description: |- - Count specifies the required number of entries that must match. If the count is null, all entries must match - (a logical AND). If the count is 1, at least one entry must match (a logical OR). If the count contains a - value N, then N must be less than or equal to the size of entries, and at least N entries must match. - minimum: 1 - type: integer - entries: - description: |- - Entries contains the available attestors. An attestor can be a static key, - attributes for keyless verification, or a nested attestor declaration. - items: - properties: - annotations: - additionalProperties: - type: string - description: |- - Annotations are used for image verification. - Every specified key-value pair must exist and match in the verified payload. - The payload may contain other key-value pairs. - type: object - attestor: - description: Attestor is a nested set - of Attestor used to specify a more - complex set of match authorities. - x-kubernetes-preserve-unknown-fields: true - certificates: - description: Certificates specifies - one or more certificates. - properties: - cert: - description: Cert is an optional - PEM-encoded public certificate. - type: string - certChain: - description: CertChain is an optional - PEM encoded set of certificates - used to verify. - type: string - ctlog: - description: |- - CTLog (certificate timestamp log) provides a configuration for validation of Signed Certificate - Timestamps (SCTs). If the value is unset, the default behavior by Cosign is used. - properties: - ignoreSCT: - description: |- - IgnoreSCT defines whether to use the Signed Certificate Timestamp (SCT) log to check for a certificate - timestamp. Default is false. Set to true if this was opted out during signing. - type: boolean - pubkey: - description: PubKey, if set, - is used to validate SCTs against - a custom source. - type: string - tsaCertChain: - description: |- - TSACertChain, if set, is the PEM-encoded certificate chain file for the RFC3161 timestamp authority. Must - contain the root CA certificate. Optionally may contain intermediate CA certificates, and - may contain the leaf TSA certificate if not present in the timestamurce. - type: string - type: object - rekor: - description: |- - Rekor provides configuration for the Rekor transparency log service. If an empty object - is provided the public instance of Rekor (https://rekor.sigstore.dev) is used. - properties: - ignoreTlog: - description: IgnoreTlog skips - transparency log verification. - type: boolean - pubkey: - description: |- - RekorPubKey is an optional PEM-encoded public key to use for a custom Rekor. - If set, this will be used to validate transparency log signatures from a custom Rekor. - type: string - url: - description: URL is the address - of the transparency log. Defaults - to the public Rekor log instance - https://rekor.sigstore.dev. - type: string - type: object - type: object - keyless: - description: |- - Keyless is a set of attribute used to verify a Sigstore keyless attestor. - See https://github.com/sigstore/cosign/blob/main/KEYLESS.md. - properties: - additionalExtensions: - additionalProperties: - type: string - description: AdditionalExtensions - are certificate-extensions used - for keyless signing. - type: object - ctlog: - description: |- - CTLog (certificate timestamp log) provides a configuration for validation of Signed Certificate - Timestamps (SCTs). If the value is unset, the default behavior by Cosign is used. - properties: - ignoreSCT: - description: |- - IgnoreSCT defines whether to use the Signed Certificate Timestamp (SCT) log to check for a certificate - timestamp. Default is false. Set to true if this was opted out during signing. - type: boolean - pubkey: - description: PubKey, if set, - is used to validate SCTs against - a custom source. - type: string - tsaCertChain: - description: |- - TSACertChain, if set, is the PEM-encoded certificate chain file for the RFC3161 timestamp authority. Must - contain the root CA certificate. Optionally may contain intermediate CA certificates, and - may contain the leaf TSA certificate if not present in the timestamurce. - type: string - type: object - issuer: - description: Issuer is the certificate - issuer used for keyless signing. - type: string - issuerRegExp: - description: IssuerRegExp is the - regular expression to match certificate - issuer used for keyless signing. - type: string - rekor: - description: |- - Rekor provides configuration for the Rekor transparency log service. If an empty object - is provided the public instance of Rekor (https://rekor.sigstore.dev) is used. - properties: - ignoreTlog: - description: IgnoreTlog skips - transparency log verification. - type: boolean - pubkey: - description: |- - RekorPubKey is an optional PEM-encoded public key to use for a custom Rekor. - If set, this will be used to validate transparency log signatures from a custom Rekor. - type: string - url: - description: URL is the address - of the transparency log. Defaults - to the public Rekor log instance - https://rekor.sigstore.dev. - type: string - type: object - roots: - description: |- - Roots is an optional set of PEM encoded trusted root certificates. - If not provided, the system roots are used. - type: string - subject: - description: Subject is the verified - identity used for keyless signing, - for example the email address. - type: string - subjectRegExp: - description: SubjectRegExp is the - regular expression to match identity - used for keyless signing, for - example the email address. - type: string - type: object - keys: - description: Keys specifies one or more - public keys. - properties: - ctlog: - description: |- - CTLog (certificate timestamp log) provides a configuration for validation of Signed Certificate - Timestamps (SCTs). If the value is unset, the default behavior by Cosign is used. - properties: - ignoreSCT: - description: |- - IgnoreSCT defines whether to use the Signed Certificate Timestamp (SCT) log to check for a certificate - timestamp. Default is false. Set to true if this was opted out during signing. - type: boolean - pubkey: - description: PubKey, if set, - is used to validate SCTs against - a custom source. - type: string - tsaCertChain: - description: |- - TSACertChain, if set, is the PEM-encoded certificate chain file for the RFC3161 timestamp authority. Must - contain the root CA certificate. Optionally may contain intermediate CA certificates, and - may contain the leaf TSA certificate if not present in the timestamurce. - type: string - type: object - kms: - description: |- - KMS provides the URI to the public key stored in a Key Management System. See: - https://github.com/sigstore/cosign/blob/main/KMS.md - type: string - publicKeys: - description: |- - Keys is a set of X.509 public keys used to verify image signatures. The keys can be directly - specified or can be a variable reference to a key specified in a ConfigMap (see - https://kyverno.io/docs/writing-policies/variables/), or reference a standard Kubernetes Secret - elsewhere in the cluster by specifying it in the format "k8s:///". - The named Secret must specify a key `cosign.pub` containing the public key used for - verification, (see https://github.com/sigstore/cosign/blob/main/KMS.md#kubernetes-secret). - When multiple keys are specified each key is processed as a separate staticKey entry - (.attestors[*].entries.keys) within the set of attestors and the count is applied across the keys. - type: string - rekor: - description: |- - Rekor provides configuration for the Rekor transparency log service. If an empty object - is provided the public instance of Rekor (https://rekor.sigstore.dev) is used. - properties: - ignoreTlog: - description: IgnoreTlog skips - transparency log verification. - type: boolean - pubkey: - description: |- - RekorPubKey is an optional PEM-encoded public key to use for a custom Rekor. - If set, this will be used to validate transparency log signatures from a custom Rekor. - type: string - url: - description: URL is the address - of the transparency log. Defaults - to the public Rekor log instance - https://rekor.sigstore.dev. - type: string - type: object - secret: - description: Reference to a Secret - resource that contains a public - key - properties: - name: - description: Name of the secret. - The provided secret must contain - a key named cosign.pub. - type: string - namespace: - description: Namespace name - where the Secret exists. - type: string - required: - - name - - namespace - type: object - signatureAlgorithm: - default: sha256 - description: Deprecated. Use attestor.signatureAlgorithm - instead. - type: string - type: object - repository: - description: |- - Repository is an optional alternate OCI repository to use for signatures and attestations that match this rule. - If specified Repository will override other OCI image repository locations for this Attestor. - type: string - signatureAlgorithm: - default: sha256 - description: Specify signature algorithm - for public keys. Supported values - are sha224, sha256, sha384 and sha512. - type: string - type: object - type: array - type: object - type: array - conditions: - description: |- - Conditions are used to verify attributes within a Predicate. If no Conditions are specified - the attestation check is satisfied as long there are predicates that match the predicate type. - items: - description: |- - AnyAllConditions consists of conditions wrapped denoting a logical criteria to be fulfilled. - AnyConditions get fulfilled when at least one of its sub-conditions passes. - AllConditions get fulfilled only when all of its sub-conditions pass. - properties: - all: - description: |- - AllConditions enable variable-based conditional rule execution. This is useful for - finer control of when an rule is applied. A condition can reference object data - using JMESPath notation. - Here, all of the conditions need to pass - items: - description: Condition defines variable-based - conditional criteria for rule execution. - properties: - key: - description: Key is the context entry - (using JMESPath) for conditional rule - evaluation. - x-kubernetes-preserve-unknown-fields: true - message: - description: Message is an optional - display message - type: string - operator: - description: |- - Operator is the conditional operation to perform. Valid operators are: - Equals, NotEquals, In, AnyIn, AllIn, NotIn, AnyNotIn, AllNotIn, GreaterThanOrEquals, - GreaterThan, LessThanOrEquals, LessThan, DurationGreaterThanOrEquals, DurationGreaterThan, - DurationLessThanOrEquals, DurationLessThan - enum: - - Equals - - NotEquals - - In - - AnyIn - - AllIn - - NotIn - - AnyNotIn - - AllNotIn - - GreaterThanOrEquals - - GreaterThan - - LessThanOrEquals - - LessThan - - DurationGreaterThanOrEquals - - DurationGreaterThan - - DurationLessThanOrEquals - - DurationLessThan - type: string - value: - description: |- - Value is the conditional value, or set of values. The values can be fixed set - or can be variables declared using JMESPath. - x-kubernetes-preserve-unknown-fields: true - type: object - type: array - any: - description: |- - AnyConditions enable variable-based conditional rule execution. This is useful for - finer control of when an rule is applied. A condition can reference object data - using JMESPath notation. - Here, at least one of the conditions need to pass - items: - description: Condition defines variable-based - conditional criteria for rule execution. - properties: - key: - description: Key is the context entry - (using JMESPath) for conditional rule - evaluation. - x-kubernetes-preserve-unknown-fields: true - message: - description: Message is an optional - display message - type: string - operator: - description: |- - Operator is the conditional operation to perform. Valid operators are: - Equals, NotEquals, In, AnyIn, AllIn, NotIn, AnyNotIn, AllNotIn, GreaterThanOrEquals, - GreaterThan, LessThanOrEquals, LessThan, DurationGreaterThanOrEquals, DurationGreaterThan, - DurationLessThanOrEquals, DurationLessThan - enum: - - Equals - - NotEquals - - In - - AnyIn - - AllIn - - NotIn - - AnyNotIn - - AllNotIn - - GreaterThanOrEquals - - GreaterThan - - LessThanOrEquals - - LessThan - - DurationGreaterThanOrEquals - - DurationGreaterThan - - DurationLessThanOrEquals - - DurationLessThan - type: string - value: - description: |- - Value is the conditional value, or set of values. The values can be fixed set - or can be variables declared using JMESPath. - x-kubernetes-preserve-unknown-fields: true - type: object - type: array - type: object - type: array - name: - description: Name is the variable name. - type: string - predicateType: - description: Deprecated in favour of 'Type', to - be removed soon - type: string - type: - description: Type defines the type of attestation - contained within the Statement. - type: string - type: object - type: array - attestors: - description: Attestors specified the required attestors - (i.e. authorities) - items: - properties: - count: - description: |- - Count specifies the required number of entries that must match. If the count is null, all entries must match - (a logical AND). If the count is 1, at least one entry must match (a logical OR). If the count contains a - value N, then N must be less than or equal to the size of entries, and at least N entries must match. - minimum: 1 - type: integer - entries: - description: |- - Entries contains the available attestors. An attestor can be a static key, - attributes for keyless verification, or a nested attestor declaration. - items: - properties: - annotations: - additionalProperties: - type: string - description: |- - Annotations are used for image verification. - Every specified key-value pair must exist and match in the verified payload. - The payload may contain other key-value pairs. - type: object - attestor: - description: Attestor is a nested set of Attestor - used to specify a more complex set of match - authorities. - x-kubernetes-preserve-unknown-fields: true - certificates: - description: Certificates specifies one or - more certificates. - properties: - cert: - description: Cert is an optional PEM-encoded - public certificate. - type: string - certChain: - description: CertChain is an optional - PEM encoded set of certificates used - to verify. - type: string - ctlog: - description: |- - CTLog (certificate timestamp log) provides a configuration for validation of Signed Certificate - Timestamps (SCTs). If the value is unset, the default behavior by Cosign is used. - properties: - ignoreSCT: - description: |- - IgnoreSCT defines whether to use the Signed Certificate Timestamp (SCT) log to check for a certificate - timestamp. Default is false. Set to true if this was opted out during signing. - type: boolean - pubkey: - description: PubKey, if set, is used - to validate SCTs against a custom - source. - type: string - tsaCertChain: - description: |- - TSACertChain, if set, is the PEM-encoded certificate chain file for the RFC3161 timestamp authority. Must - contain the root CA certificate. Optionally may contain intermediate CA certificates, and - may contain the leaf TSA certificate if not present in the timestamurce. - type: string - type: object - rekor: - description: |- - Rekor provides configuration for the Rekor transparency log service. If an empty object - is provided the public instance of Rekor (https://rekor.sigstore.dev) is used. - properties: - ignoreTlog: - description: IgnoreTlog skips transparency - log verification. - type: boolean - pubkey: - description: |- - RekorPubKey is an optional PEM-encoded public key to use for a custom Rekor. - If set, this will be used to validate transparency log signatures from a custom Rekor. - type: string - url: - description: URL is the address of - the transparency log. Defaults to - the public Rekor log instance https://rekor.sigstore.dev. - type: string - type: object - type: object - keyless: - description: |- - Keyless is a set of attribute used to verify a Sigstore keyless attestor. - See https://github.com/sigstore/cosign/blob/main/KEYLESS.md. - properties: - additionalExtensions: - additionalProperties: - type: string - description: AdditionalExtensions are - certificate-extensions used for keyless - signing. - type: object - ctlog: - description: |- - CTLog (certificate timestamp log) provides a configuration for validation of Signed Certificate - Timestamps (SCTs). If the value is unset, the default behavior by Cosign is used. - properties: - ignoreSCT: - description: |- - IgnoreSCT defines whether to use the Signed Certificate Timestamp (SCT) log to check for a certificate - timestamp. Default is false. Set to true if this was opted out during signing. - type: boolean - pubkey: - description: PubKey, if set, is used - to validate SCTs against a custom - source. - type: string - tsaCertChain: - description: |- - TSACertChain, if set, is the PEM-encoded certificate chain file for the RFC3161 timestamp authority. Must - contain the root CA certificate. Optionally may contain intermediate CA certificates, and - may contain the leaf TSA certificate if not present in the timestamurce. - type: string - type: object - issuer: - description: Issuer is the certificate - issuer used for keyless signing. - type: string - issuerRegExp: - description: IssuerRegExp is the regular - expression to match certificate issuer - used for keyless signing. - type: string - rekor: - description: |- - Rekor provides configuration for the Rekor transparency log service. If an empty object - is provided the public instance of Rekor (https://rekor.sigstore.dev) is used. - properties: - ignoreTlog: - description: IgnoreTlog skips transparency - log verification. - type: boolean - pubkey: - description: |- - RekorPubKey is an optional PEM-encoded public key to use for a custom Rekor. - If set, this will be used to validate transparency log signatures from a custom Rekor. - type: string - url: - description: URL is the address of - the transparency log. Defaults to - the public Rekor log instance https://rekor.sigstore.dev. - type: string - type: object - roots: - description: |- - Roots is an optional set of PEM encoded trusted root certificates. - If not provided, the system roots are used. - type: string - subject: - description: Subject is the verified identity - used for keyless signing, for example - the email address. - type: string - subjectRegExp: - description: SubjectRegExp is the regular - expression to match identity used for - keyless signing, for example the email - address. - type: string - type: object - keys: - description: Keys specifies one or more public - keys. - properties: - ctlog: - description: |- - CTLog (certificate timestamp log) provides a configuration for validation of Signed Certificate - Timestamps (SCTs). If the value is unset, the default behavior by Cosign is used. - properties: - ignoreSCT: - description: |- - IgnoreSCT defines whether to use the Signed Certificate Timestamp (SCT) log to check for a certificate - timestamp. Default is false. Set to true if this was opted out during signing. - type: boolean - pubkey: - description: PubKey, if set, is used - to validate SCTs against a custom - source. - type: string - tsaCertChain: - description: |- - TSACertChain, if set, is the PEM-encoded certificate chain file for the RFC3161 timestamp authority. Must - contain the root CA certificate. Optionally may contain intermediate CA certificates, and - may contain the leaf TSA certificate if not present in the timestamurce. - type: string - type: object - kms: - description: |- - KMS provides the URI to the public key stored in a Key Management System. See: - https://github.com/sigstore/cosign/blob/main/KMS.md - type: string - publicKeys: - description: |- - Keys is a set of X.509 public keys used to verify image signatures. The keys can be directly - specified or can be a variable reference to a key specified in a ConfigMap (see - https://kyverno.io/docs/writing-policies/variables/), or reference a standard Kubernetes Secret - elsewhere in the cluster by specifying it in the format "k8s:///". - The named Secret must specify a key `cosign.pub` containing the public key used for - verification, (see https://github.com/sigstore/cosign/blob/main/KMS.md#kubernetes-secret). - When multiple keys are specified each key is processed as a separate staticKey entry - (.attestors[*].entries.keys) within the set of attestors and the count is applied across the keys. - type: string - rekor: - description: |- - Rekor provides configuration for the Rekor transparency log service. If an empty object - is provided the public instance of Rekor (https://rekor.sigstore.dev) is used. - properties: - ignoreTlog: - description: IgnoreTlog skips transparency - log verification. - type: boolean - pubkey: - description: |- - RekorPubKey is an optional PEM-encoded public key to use for a custom Rekor. - If set, this will be used to validate transparency log signatures from a custom Rekor. - type: string - url: - description: URL is the address of - the transparency log. Defaults to - the public Rekor log instance https://rekor.sigstore.dev. - type: string - type: object - secret: - description: Reference to a Secret resource - that contains a public key - properties: - name: - description: Name of the secret. The - provided secret must contain a key - named cosign.pub. - type: string - namespace: - description: Namespace name where - the Secret exists. - type: string - required: - - name - - namespace - type: object - signatureAlgorithm: - default: sha256 - description: Deprecated. Use attestor.signatureAlgorithm - instead. - type: string - type: object - repository: - description: |- - Repository is an optional alternate OCI repository to use for signatures and attestations that match this rule. - If specified Repository will override other OCI image repository locations for this Attestor. - type: string - signatureAlgorithm: - default: sha256 - description: Specify signature algorithm for - public keys. Supported values are sha224, - sha256, sha384 and sha512. - type: string - type: object - type: array - type: object - type: array - cosignOCI11: - description: |- - CosignOCI11 enables the experimental OCI 1.1 behaviour in cosign image verification. - Defaults to false. - type: boolean - failureAction: - description: Allowed values are Audit or Enforce. - enum: - - Audit - - Enforce - type: string - image: - description: Deprecated. Use ImageReferences instead. - type: string - imageReferences: - description: |- - ImageReferences is a list of matching image reference patterns. At least one pattern in the - list must match the image for the rule to apply. Each image reference consists of a registry - address (defaults to docker.io), repository, image, and tag (defaults to latest). - Wildcards ('*' and '?') are allowed. See: https://kubernetes.io/docs/concepts/containers/images. - items: - type: string - type: array - imageRegistryCredentials: - description: ImageRegistryCredentials provides credentials - that will be used for authentication with registry. - properties: - allowInsecureRegistry: - description: AllowInsecureRegistry allows insecure - access to a registry. - type: boolean - providers: - description: |- - Providers specifies a list of OCI Registry names, whose authentication providers are provided. - It can be of one of these values: default,google,azure,amazon,github. - items: - description: ImageRegistryCredentialsProvidersType - provides the list of credential providers required. - enum: - - default - - amazon - - azure - - google - - github - type: string - type: array - secrets: - description: |- - Secrets specifies a list of secrets that are provided for credentials. - Secrets must live in the Kyverno namespace. - items: - type: string - type: array - type: object - issuer: - description: Deprecated. Use KeylessAttestor instead. - type: string - key: - description: Deprecated. Use StaticKeyAttestor instead. - type: string - mutateDigest: - default: true - description: |- - MutateDigest enables replacement of image tags with digests. - Defaults to true. - type: boolean - repository: - description: |- - Repository is an optional alternate OCI repository to use for image signatures and attestations that match this rule. - If specified Repository will override the default OCI image repository configured for the installation. - The repository can also be overridden per Attestor or Attestation. - type: string - required: - default: true - description: Required validates that images are verified - i.e. have matched passed a signature or attestation - check. - type: boolean - roots: - description: Deprecated. Use KeylessAttestor instead. - type: string - skipImageReferences: - description: |- - SkipImageReferences is a list of matching image reference patterns that should be skipped. - At least one pattern in the list must match the image for the rule to be skipped. Each image reference - consists of a registry address (defaults to docker.io), repository, image, and tag (defaults to latest). - Wildcards ('*' and '?') are allowed. See: https://kubernetes.io/docs/concepts/containers/images. - items: - type: string - type: array - subject: - description: Deprecated. Use KeylessAttestor instead. - type: string - type: - description: |- - Type specifies the method of signature validation. The allowed options - are Cosign, Sigstore Bundle and Notary. By default Cosign is used if a type is not specified. - enum: - - Cosign - - SigstoreBundle - - Notary - type: string - useCache: - default: true - description: UseCache enables caching of image verify - responses for this rule. - type: boolean - validate: - description: |- - Validation checks conditions across multiple image - verification attestations or context entries - properties: - deny: - description: Deny defines conditions used to pass - or fail a validation rule. - properties: - conditions: - description: |- - Multiple conditions can be declared under an `any` or `all` statement. A direct list - of conditions (without `any` or `all` statements) is also supported for backwards compatibility - but will be deprecated in the next major release. - See: https://kyverno.io/docs/writing-policies/validate/#deny-rules - x-kubernetes-preserve-unknown-fields: true - type: object - message: - description: Message specifies a custom message to - be displayed on failure. - type: string - type: object - verifyDigest: - default: true - description: VerifyDigest validates that images have a - digest. - type: boolean - type: object - type: array - required: - - match - - name - type: object - type: array - schemaValidation: - description: Deprecated. - type: boolean - useServerSideApply: - description: |- - UseServerSideApply controls whether to use server-side apply for generate rules - If is set to "true" create & update for generate rules will use apply instead of create/update. - Defaults to "false" if not specified. - type: boolean - validationFailureAction: - default: Audit - description: Deprecated, use validationFailureAction under the validate - rule instead. - enum: - - audit - - enforce - - Audit - - Enforce - type: string - validationFailureActionOverrides: - description: Deprecated, use validationFailureActionOverrides under - the validate rule instead. - items: - properties: - action: - description: ValidationFailureAction defines the policy validation - failure action - enum: - - audit - - enforce - - Audit - - Enforce - type: string - namespaceSelector: - description: |- - A label selector is a label query over a set of resources. The result of matchLabels and - matchExpressions are ANDed. An empty label selector matches all objects. A null - label selector matches no objects. - properties: - matchExpressions: - description: matchExpressions is a list of label selector - requirements. The requirements are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key that the selector - applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - namespaces: - items: - type: string - type: array - type: object - type: array - webhookConfiguration: - description: WebhookConfiguration specifies the custom configuration - for Kubernetes admission webhookconfiguration. - properties: - failurePolicy: - description: |- - FailurePolicy defines how unexpected policy errors and webhook response timeout errors are handled. - Rules within the same policy share the same failure behavior. - This field should not be accessed directly, instead `GetFailurePolicy()` should be used. - Allowed values are Ignore or Fail. Defaults to Fail. - enum: - - Ignore - - Fail - type: string - matchConditions: - description: |- - MatchCondition configures admission webhook matchConditions. - Requires Kubernetes 1.27 or later. - items: - description: MatchCondition represents a condition which must - by fulfilled for a request to be sent to a webhook. - properties: - expression: - description: |- - Expression represents the expression which will be evaluated by CEL. Must evaluate to bool. - CEL expressions have access to the contents of the AdmissionRequest and Authorizer, organized into CEL variables: - - 'object' - The object from the incoming request. The value is null for DELETE requests. - 'oldObject' - The existing object. The value is null for CREATE requests. - 'request' - Attributes of the admission request(/pkg/apis/admission/types.go#AdmissionRequest). - 'authorizer' - A CEL Authorizer. May be used to perform authorization checks for the principal (user or service account) of the request. - See https://pkg.go.dev/k8s.io/apiserver/pkg/cel/library#Authz - 'authorizer.requestResource' - A CEL ResourceCheck constructed from the 'authorizer' and configured with the - request resource. - Documentation on CEL: https://kubernetes.io/docs/reference/using-api/cel/ - - Required. - type: string - name: - description: |- - Name is an identifier for this match condition, used for strategic merging of MatchConditions, - as well as providing an identifier for logging purposes. A good name should be descriptive of - the associated expression. - Name must be a qualified name consisting of alphanumeric characters, '-', '_' or '.', and - must start and end with an alphanumeric character (e.g. 'MyName', or 'my.name', or - '123-abc', regex used for validation is '([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9]') with an - optional DNS subdomain prefix and '/' (e.g. 'example.com/MyName') - - Required. - type: string - required: - - expression - - name - type: object - type: array - timeoutSeconds: - description: |- - TimeoutSeconds specifies the maximum time in seconds allowed to apply this policy. - After the configured time expires, the admission request may fail, or may simply ignore the policy results, - based on the failure policy. The default timeout is 10s, the value must be between 1 and 30 seconds. - format: int32 - type: integer - type: object - webhookTimeoutSeconds: - description: Deprecated, use webhookTimeoutSeconds under webhookConfiguration - instead. - format: int32 - type: integer - type: object - status: - description: Deprecated. Policy metrics are available via the metrics - endpoint - properties: - autogen: - description: AutogenStatus contains autogen status information. - properties: - rules: - description: Rules is a list of Rule instances. It contains auto - generated rules added for pod controllers - items: - description: |- - Rule defines a validation, mutation, or generation control for matching resources. - Each rules contains a match declaration to select resources, and an optional exclude - declaration to specify which resources to exclude. - properties: - celPreconditions: - description: |- - CELPreconditions are used to determine if a policy rule should be applied by evaluating a - set of CEL conditions. It can only be used with the validate.cel subrule - items: - description: MatchCondition represents a condition which - must by fulfilled for a request to be sent to a webhook. - properties: - expression: - description: |- - Expression represents the expression which will be evaluated by CEL. Must evaluate to bool. - CEL expressions have access to the contents of the AdmissionRequest and Authorizer, organized into CEL variables: - - 'object' - The object from the incoming request. The value is null for DELETE requests. - 'oldObject' - The existing object. The value is null for CREATE requests. - 'request' - Attributes of the admission request(/pkg/apis/admission/types.go#AdmissionRequest). - 'authorizer' - A CEL Authorizer. May be used to perform authorization checks for the principal (user or service account) of the request. - See https://pkg.go.dev/k8s.io/apiserver/pkg/cel/library#Authz - 'authorizer.requestResource' - A CEL ResourceCheck constructed from the 'authorizer' and configured with the - request resource. - Documentation on CEL: https://kubernetes.io/docs/reference/using-api/cel/ - - Required. - type: string - name: - description: |- - Name is an identifier for this match condition, used for strategic merging of MatchConditions, - as well as providing an identifier for logging purposes. A good name should be descriptive of - the associated expression. - Name must be a qualified name consisting of alphanumeric characters, '-', '_' or '.', and - must start and end with an alphanumeric character (e.g. 'MyName', or 'my.name', or - '123-abc', regex used for validation is '([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9]') with an - optional DNS subdomain prefix and '/' (e.g. 'example.com/MyName') - - Required. - type: string - required: - - expression - - name - type: object - type: array - context: - description: Context defines variables and data sources - that can be used during rule execution. - items: - description: |- - ContextEntry adds variables and data sources to a rule Context. Either a - ConfigMap reference or a APILookup must be provided. - oneOf: - - required: - - configMap - - required: - - apiCall - - required: - - imageRegistry - - required: - - variable - - required: - - globalReference - properties: - apiCall: - description: |- - APICall is an HTTP request to the Kubernetes API server, or other JSON web service. - The data returned is stored in the context with the name for the context entry. - properties: - data: - description: |- - The data object specifies the POST data sent to the server. - Only applicable when the method field is set to POST. - items: - description: RequestData contains the HTTP POST - data - properties: - key: - description: Key is a unique identifier - for the data value - type: string - value: - description: Value is the data value - x-kubernetes-preserve-unknown-fields: true - required: - - key - - value - type: object - type: array - default: - description: |- - Default is an optional arbitrary JSON object that the context - value is set to, if the apiCall returns error. - x-kubernetes-preserve-unknown-fields: true - jmesPath: - description: |- - JMESPath is an optional JSON Match Expression that can be used to - transform the JSON response returned from the server. For example - a JMESPath of "items | length(@)" applied to the API server response - for the URLPath "/apis/apps/v1/deployments" will return the total count - of deployments across all namespaces. - type: string - method: - default: GET - description: Method is the HTTP request type (GET - or POST). Defaults to GET. - enum: - - GET - - POST - type: string - service: - description: |- - Service is an API call to a JSON web service. - This is used for non-Kubernetes API server calls. - It's mutually exclusive with the URLPath field. - properties: - caBundle: - description: |- - CABundle is a PEM encoded CA bundle which will be used to validate - the server certificate. - type: string - headers: - description: Headers is a list of optional - HTTP headers to be included in the request. - items: - properties: - key: - description: Key is the header key - type: string - value: - description: Value is the header value - type: string - required: - - key - - value - type: object - type: array - url: - description: |- - URL is the JSON web service URL. A typical form is - `https://{service}.{namespace}:{port}/{path}`. - type: string - required: - - url - type: object - urlPath: - description: |- - URLPath is the URL path to be used in the HTTP GET or POST request to the - Kubernetes API server (e.g. "/api/v1/namespaces" or "/apis/apps/v1/deployments"). - The format required is the same format used by the `kubectl get --raw` command. - See https://kyverno.io/docs/writing-policies/external-data-sources/#variables-from-kubernetes-api-server-calls - for details. - It's mutually exclusive with the Service field. - type: string - type: object - configMap: - description: ConfigMap is the ConfigMap reference. - properties: - name: - description: Name is the ConfigMap name. - type: string - namespace: - description: Namespace is the ConfigMap namespace. - type: string - required: - - name - type: object - globalReference: - description: GlobalContextEntryReference is a reference - to a cached global context entry. - properties: - jmesPath: - description: |- - JMESPath is an optional JSON Match Expression that can be used to - transform the JSON response returned from the server. For example - a JMESPath of "items | length(@)" applied to the API server response - for the URLPath "/apis/apps/v1/deployments" will return the total count - of deployments across all namespaces. - type: string - name: - description: Name of the global context entry - type: string - required: - - name - type: object - imageRegistry: - description: |- - ImageRegistry defines requests to an OCI/Docker V2 registry to fetch image - details. - properties: - imageRegistryCredentials: - description: ImageRegistryCredentials provides - credentials that will be used for authentication - with registry - properties: - allowInsecureRegistry: - description: AllowInsecureRegistry allows - insecure access to a registry. - type: boolean - providers: - description: |- - Providers specifies a list of OCI Registry names, whose authentication providers are provided. - It can be of one of these values: default,google,azure,amazon,github. - items: - description: ImageRegistryCredentialsProvidersType - provides the list of credential providers - required. - enum: - - default - - amazon - - azure - - google - - github - type: string - type: array - secrets: - description: |- - Secrets specifies a list of secrets that are provided for credentials. - Secrets must live in the Kyverno namespace. - items: - type: string - type: array - type: object - jmesPath: - description: |- - JMESPath is an optional JSON Match Expression that can be used to - transform the ImageData struct returned as a result of processing - the image reference. - type: string - reference: - description: |- - Reference is image reference to a container image in the registry. - Example: ghcr.io/kyverno/kyverno:latest - type: string - required: - - reference - type: object - name: - description: Name is the variable name. - type: string - variable: - description: Variable defines an arbitrary JMESPath - context variable that can be defined inline. - properties: - default: - description: |- - Default is an optional arbitrary JSON object that the variable may take if the JMESPath - expression evaluates to nil - x-kubernetes-preserve-unknown-fields: true - jmesPath: - description: |- - JMESPath is an optional JMESPath Expression that can be used to - transform the variable. - type: string - value: - description: Value is any arbitrary JSON object - representable in YAML or JSON form. - x-kubernetes-preserve-unknown-fields: true - type: object - required: - - name - type: object - type: array - exclude: - description: |- - ExcludeResources defines when this policy rule should not be applied. The exclude - criteria can include resource information (e.g. kind, name, namespace, labels) - and admission review request information like the name or role. - not: - required: - - any - - all - properties: - all: - description: All allows specifying resources which will - be ANDed - items: - description: ResourceFilter allow users to "AND" or - "OR" between resources - properties: - clusterRoles: - description: ClusterRoles is the list of cluster-wide - role names for the user. - items: - type: string - type: array - resources: - description: ResourceDescription contains information - about the resource being created or modified. - not: - required: - - name - - names - properties: - annotations: - additionalProperties: - type: string - description: |- - Annotations is a map of annotations (key-value pairs of type string). Annotation keys - and values support the wildcard characters "*" (matches zero or many characters) and - "?" (matches at least one character). - type: object - kinds: - description: Kinds is a list of resource kinds. - items: - type: string - type: array - name: - description: |- - Name is the name of the resource. The name supports wildcard characters - "*" (matches zero or many characters) and "?" (at least one character). - NOTE: "Name" is being deprecated in favor of "Names". - type: string - names: - description: |- - Names are the names of the resources. Each name supports wildcard characters - "*" (matches zero or many characters) and "?" (at least one character). - items: - type: string - type: array - namespaceSelector: - description: |- - NamespaceSelector is a label selector for the resource namespace. Label keys and values - in `matchLabels` support the wildcard characters `*` (matches zero or many characters) - and `?` (matches one character).Wildcards allows writing label selectors like - ["storage.k8s.io/*": "*"]. Note that using ["*" : "*"] matches any key and value but - does not match an empty label set. - properties: - matchExpressions: - description: matchExpressions is a list - of label selector requirements. The - requirements are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key - that the selector applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - namespaces: - description: |- - Namespaces is a list of namespaces names. Each name supports wildcard characters - "*" (matches zero or many characters) and "?" (at least one character). - items: - type: string - type: array - operations: - description: Operations can contain values - ["CREATE, "UPDATE", "CONNECT", "DELETE"], - which are used to match a specific action. - items: - description: AdmissionOperation can have - one of the values CREATE, UPDATE, CONNECT, - DELETE, which are used to match a specific - action. - enum: - - CREATE - - CONNECT - - UPDATE - - DELETE - type: string - type: array - selector: - description: |- - Selector is a label selector. Label keys and values in `matchLabels` support the wildcard - characters `*` (matches zero or many characters) and `?` (matches one character). - Wildcards allows writing label selectors like ["storage.k8s.io/*": "*"]. Note that - using ["*" : "*"] matches any key and value but does not match an empty label set. - properties: - matchExpressions: - description: matchExpressions is a list - of label selector requirements. The - requirements are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key - that the selector applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - type: object - roles: - description: Roles is the list of namespaced role - names for the user. - items: - type: string - type: array - subjects: - description: Subjects is the list of subject names - like users, user groups, and service accounts. - items: - description: |- - Subject contains a reference to the object or user identities a role binding applies to. This can either hold a direct API object reference, - or a value for non-objects such as user and group names. - properties: - apiGroup: - description: |- - APIGroup holds the API group of the referenced subject. - Defaults to "" for ServiceAccount subjects. - Defaults to "rbac.authorization.k8s.io" for User and Group subjects. - type: string - kind: - description: |- - Kind of object being referenced. Values defined by this API group are "User", "Group", and "ServiceAccount". - If the Authorizer does not recognized the kind value, the Authorizer should report an error. - type: string - name: - description: Name of the object being referenced. - type: string - namespace: - description: |- - Namespace of the referenced object. If the object kind is non-namespace, such as "User" or "Group", and this value is not empty - the Authorizer should report an error. - type: string - required: - - kind - - name - type: object - x-kubernetes-map-type: atomic - type: array - type: object - type: array - any: - description: Any allows specifying resources which will - be ORed - items: - description: ResourceFilter allow users to "AND" or - "OR" between resources - properties: - clusterRoles: - description: ClusterRoles is the list of cluster-wide - role names for the user. - items: - type: string - type: array - resources: - description: ResourceDescription contains information - about the resource being created or modified. - not: - required: - - name - - names - properties: - annotations: - additionalProperties: - type: string - description: |- - Annotations is a map of annotations (key-value pairs of type string). Annotation keys - and values support the wildcard characters "*" (matches zero or many characters) and - "?" (matches at least one character). - type: object - kinds: - description: Kinds is a list of resource kinds. - items: - type: string - type: array - name: - description: |- - Name is the name of the resource. The name supports wildcard characters - "*" (matches zero or many characters) and "?" (at least one character). - NOTE: "Name" is being deprecated in favor of "Names". - type: string - names: - description: |- - Names are the names of the resources. Each name supports wildcard characters - "*" (matches zero or many characters) and "?" (at least one character). - items: - type: string - type: array - namespaceSelector: - description: |- - NamespaceSelector is a label selector for the resource namespace. Label keys and values - in `matchLabels` support the wildcard characters `*` (matches zero or many characters) - and `?` (matches one character).Wildcards allows writing label selectors like - ["storage.k8s.io/*": "*"]. Note that using ["*" : "*"] matches any key and value but - does not match an empty label set. - properties: - matchExpressions: - description: matchExpressions is a list - of label selector requirements. The - requirements are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key - that the selector applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - namespaces: - description: |- - Namespaces is a list of namespaces names. Each name supports wildcard characters - "*" (matches zero or many characters) and "?" (at least one character). - items: - type: string - type: array - operations: - description: Operations can contain values - ["CREATE, "UPDATE", "CONNECT", "DELETE"], - which are used to match a specific action. - items: - description: AdmissionOperation can have - one of the values CREATE, UPDATE, CONNECT, - DELETE, which are used to match a specific - action. - enum: - - CREATE - - CONNECT - - UPDATE - - DELETE - type: string - type: array - selector: - description: |- - Selector is a label selector. Label keys and values in `matchLabels` support the wildcard - characters `*` (matches zero or many characters) and `?` (matches one character). - Wildcards allows writing label selectors like ["storage.k8s.io/*": "*"]. Note that - using ["*" : "*"] matches any key and value but does not match an empty label set. - properties: - matchExpressions: - description: matchExpressions is a list - of label selector requirements. The - requirements are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key - that the selector applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - type: object - roles: - description: Roles is the list of namespaced role - names for the user. - items: - type: string - type: array - subjects: - description: Subjects is the list of subject names - like users, user groups, and service accounts. - items: - description: |- - Subject contains a reference to the object or user identities a role binding applies to. This can either hold a direct API object reference, - or a value for non-objects such as user and group names. - properties: - apiGroup: - description: |- - APIGroup holds the API group of the referenced subject. - Defaults to "" for ServiceAccount subjects. - Defaults to "rbac.authorization.k8s.io" for User and Group subjects. - type: string - kind: - description: |- - Kind of object being referenced. Values defined by this API group are "User", "Group", and "ServiceAccount". - If the Authorizer does not recognized the kind value, the Authorizer should report an error. - type: string - name: - description: Name of the object being referenced. - type: string - namespace: - description: |- - Namespace of the referenced object. If the object kind is non-namespace, such as "User" or "Group", and this value is not empty - the Authorizer should report an error. - type: string - required: - - kind - - name - type: object - x-kubernetes-map-type: atomic - type: array - type: object - type: array - clusterRoles: - description: ClusterRoles is the list of cluster-wide - role names for the user. - items: - type: string - type: array - resources: - description: |- - ResourceDescription contains information about the resource being created or modified. - Requires at least one tag to be specified when under MatchResources. - Specifying ResourceDescription directly under match is being deprecated. - Please specify under "any" or "all" instead. - not: - required: - - name - - names - properties: - annotations: - additionalProperties: - type: string - description: |- - Annotations is a map of annotations (key-value pairs of type string). Annotation keys - and values support the wildcard characters "*" (matches zero or many characters) and - "?" (matches at least one character). - type: object - kinds: - description: Kinds is a list of resource kinds. - items: - type: string - type: array - name: - description: |- - Name is the name of the resource. The name supports wildcard characters - "*" (matches zero or many characters) and "?" (at least one character). - NOTE: "Name" is being deprecated in favor of "Names". - type: string - names: - description: |- - Names are the names of the resources. Each name supports wildcard characters - "*" (matches zero or many characters) and "?" (at least one character). - items: - type: string - type: array - namespaceSelector: - description: |- - NamespaceSelector is a label selector for the resource namespace. Label keys and values - in `matchLabels` support the wildcard characters `*` (matches zero or many characters) - and `?` (matches one character).Wildcards allows writing label selectors like - ["storage.k8s.io/*": "*"]. Note that using ["*" : "*"] matches any key and value but - does not match an empty label set. - properties: - matchExpressions: - description: matchExpressions is a list of label - selector requirements. The requirements are - ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key that - the selector applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - namespaces: - description: |- - Namespaces is a list of namespaces names. Each name supports wildcard characters - "*" (matches zero or many characters) and "?" (at least one character). - items: - type: string - type: array - operations: - description: Operations can contain values ["CREATE, - "UPDATE", "CONNECT", "DELETE"], which are used - to match a specific action. - items: - description: AdmissionOperation can have one of - the values CREATE, UPDATE, CONNECT, DELETE, - which are used to match a specific action. - enum: - - CREATE - - CONNECT - - UPDATE - - DELETE - type: string - type: array - selector: - description: |- - Selector is a label selector. Label keys and values in `matchLabels` support the wildcard - characters `*` (matches zero or many characters) and `?` (matches one character). - Wildcards allows writing label selectors like ["storage.k8s.io/*": "*"]. Note that - using ["*" : "*"] matches any key and value but does not match an empty label set. - properties: - matchExpressions: - description: matchExpressions is a list of label - selector requirements. The requirements are - ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key that - the selector applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - type: object - roles: - description: Roles is the list of namespaced role names - for the user. - items: - type: string - type: array - subjects: - description: Subjects is the list of subject names like - users, user groups, and service accounts. - items: - description: |- - Subject contains a reference to the object or user identities a role binding applies to. This can either hold a direct API object reference, - or a value for non-objects such as user and group names. - properties: - apiGroup: - description: |- - APIGroup holds the API group of the referenced subject. - Defaults to "" for ServiceAccount subjects. - Defaults to "rbac.authorization.k8s.io" for User and Group subjects. - type: string - kind: - description: |- - Kind of object being referenced. Values defined by this API group are "User", "Group", and "ServiceAccount". - If the Authorizer does not recognized the kind value, the Authorizer should report an error. - type: string - name: - description: Name of the object being referenced. - type: string - namespace: - description: |- - Namespace of the referenced object. If the object kind is non-namespace, such as "User" or "Group", and this value is not empty - the Authorizer should report an error. - type: string - required: - - kind - - name - type: object - x-kubernetes-map-type: atomic - type: array - type: object - generate: - description: Generation is used to create new resources. - properties: - apiVersion: - description: APIVersion specifies resource apiVersion. - type: string - clone: - description: |- - Clone specifies the source resource used to populate each generated resource. - At most one of Data or Clone can be specified. If neither are provided, the generated - resource will be created with default data only. - properties: - name: - description: Name specifies name of the resource. - type: string - namespace: - description: Namespace specifies source resource - namespace. - type: string - type: object - cloneList: - description: CloneList specifies the list of source - resource used to populate each generated resource. - properties: - kinds: - description: Kinds is a list of resource kinds. - items: - type: string - type: array - namespace: - description: Namespace specifies source resource - namespace. - type: string - selector: - description: |- - Selector is a label selector. Label keys and values in `matchLabels`. - wildcard characters are not supported. - properties: - matchExpressions: - description: matchExpressions is a list of label - selector requirements. The requirements are - ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key that - the selector applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - type: object - data: - description: |- - Data provides the resource declaration used to populate each generated resource. - At most one of Data or Clone must be specified. If neither are provided, the generated - resource will be created with default data only. - x-kubernetes-preserve-unknown-fields: true - foreach: - description: ForEach applies generate rules to a list - of sub-elements by creating a context for each entry - in the list and looping over it to apply the specified - logic. - items: - properties: - apiVersion: - description: APIVersion specifies resource apiVersion. - type: string - clone: - description: |- - Clone specifies the source resource used to populate each generated resource. - At most one of Data or Clone can be specified. If neither are provided, the generated - resource will be created with default data only. - properties: - name: - description: Name specifies name of the resource. - type: string - namespace: - description: Namespace specifies source resource - namespace. - type: string - type: object - cloneList: - description: CloneList specifies the list of source - resource used to populate each generated resource. - properties: - kinds: - description: Kinds is a list of resource kinds. - items: - type: string - type: array - namespace: - description: Namespace specifies source resource - namespace. - type: string - selector: - description: |- - Selector is a label selector. Label keys and values in `matchLabels`. - wildcard characters are not supported. - properties: - matchExpressions: - description: matchExpressions is a list - of label selector requirements. The - requirements are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key - that the selector applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - type: object - context: - description: Context defines variables and data - sources that can be used during rule execution. - items: - description: |- - ContextEntry adds variables and data sources to a rule Context. Either a - ConfigMap reference or a APILookup must be provided. - oneOf: - - required: - - configMap - - required: - - apiCall - - required: - - imageRegistry - - required: - - variable - - required: - - globalReference - properties: - apiCall: - description: |- - APICall is an HTTP request to the Kubernetes API server, or other JSON web service. - The data returned is stored in the context with the name for the context entry. - properties: - data: - description: |- - The data object specifies the POST data sent to the server. - Only applicable when the method field is set to POST. - items: - description: RequestData contains - the HTTP POST data - properties: - key: - description: Key is a unique identifier - for the data value - type: string - value: - description: Value is the data - value - x-kubernetes-preserve-unknown-fields: true - required: - - key - - value - type: object - type: array - default: - description: |- - Default is an optional arbitrary JSON object that the context - value is set to, if the apiCall returns error. - x-kubernetes-preserve-unknown-fields: true - jmesPath: - description: |- - JMESPath is an optional JSON Match Expression that can be used to - transform the JSON response returned from the server. For example - a JMESPath of "items | length(@)" applied to the API server response - for the URLPath "/apis/apps/v1/deployments" will return the total count - of deployments across all namespaces. - type: string - method: - default: GET - description: Method is the HTTP request - type (GET or POST). Defaults to GET. - enum: - - GET - - POST - type: string - service: - description: |- - Service is an API call to a JSON web service. - This is used for non-Kubernetes API server calls. - It's mutually exclusive with the URLPath field. - properties: - caBundle: - description: |- - CABundle is a PEM encoded CA bundle which will be used to validate - the server certificate. - type: string - headers: - description: Headers is a list of - optional HTTP headers to be included - in the request. - items: - properties: - key: - description: Key is the header - key - type: string - value: - description: Value is the - header value - type: string - required: - - key - - value - type: object - type: array - url: - description: |- - URL is the JSON web service URL. A typical form is - `https://{service}.{namespace}:{port}/{path}`. - type: string - required: - - url - type: object - urlPath: - description: |- - URLPath is the URL path to be used in the HTTP GET or POST request to the - Kubernetes API server (e.g. "/api/v1/namespaces" or "/apis/apps/v1/deployments"). - The format required is the same format used by the `kubectl get --raw` command. - See https://kyverno.io/docs/writing-policies/external-data-sources/#variables-from-kubernetes-api-server-calls - for details. - It's mutually exclusive with the Service field. - type: string - type: object - configMap: - description: ConfigMap is the ConfigMap - reference. - properties: - name: - description: Name is the ConfigMap name. - type: string - namespace: - description: Namespace is the ConfigMap - namespace. - type: string - required: - - name - type: object - globalReference: - description: GlobalContextEntryReference - is a reference to a cached global context - entry. - properties: - jmesPath: - description: |- - JMESPath is an optional JSON Match Expression that can be used to - transform the JSON response returned from the server. For example - a JMESPath of "items | length(@)" applied to the API server response - for the URLPath "/apis/apps/v1/deployments" will return the total count - of deployments across all namespaces. - type: string - name: - description: Name of the global context - entry - type: string - required: - - name - type: object - imageRegistry: - description: |- - ImageRegistry defines requests to an OCI/Docker V2 registry to fetch image - details. - properties: - imageRegistryCredentials: - description: ImageRegistryCredentials - provides credentials that will be - used for authentication with registry - properties: - allowInsecureRegistry: - description: AllowInsecureRegistry - allows insecure access to a registry. - type: boolean - providers: - description: |- - Providers specifies a list of OCI Registry names, whose authentication providers are provided. - It can be of one of these values: default,google,azure,amazon,github. - items: - description: ImageRegistryCredentialsProvidersType - provides the list of credential - providers required. - enum: - - default - - amazon - - azure - - google - - github - type: string - type: array - secrets: - description: |- - Secrets specifies a list of secrets that are provided for credentials. - Secrets must live in the Kyverno namespace. - items: - type: string - type: array - type: object - jmesPath: - description: |- - JMESPath is an optional JSON Match Expression that can be used to - transform the ImageData struct returned as a result of processing - the image reference. - type: string - reference: - description: |- - Reference is image reference to a container image in the registry. - Example: ghcr.io/kyverno/kyverno:latest - type: string - required: - - reference - type: object - name: - description: Name is the variable name. - type: string - variable: - description: Variable defines an arbitrary - JMESPath context variable that can be - defined inline. - properties: - default: - description: |- - Default is an optional arbitrary JSON object that the variable may take if the JMESPath - expression evaluates to nil - x-kubernetes-preserve-unknown-fields: true - jmesPath: - description: |- - JMESPath is an optional JMESPath Expression that can be used to - transform the variable. - type: string - value: - description: Value is any arbitrary - JSON object representable in YAML - or JSON form. - x-kubernetes-preserve-unknown-fields: true - type: object - required: - - name - type: object - type: array - data: - description: |- - Data provides the resource declaration used to populate each generated resource. - At most one of Data or Clone must be specified. If neither are provided, the generated - resource will be created with default data only. - x-kubernetes-preserve-unknown-fields: true - kind: - description: Kind specifies resource kind. - type: string - list: - description: |- - List specifies a JMESPath expression that results in one or more elements - to which the validation logic is applied. - type: string - name: - description: Name specifies the resource name. - type: string - namespace: - description: Namespace specifies resource namespace. - type: string - preconditions: - description: |- - AnyAllConditions are used to determine if a policy rule should be applied by evaluating a - set of conditions. The declaration can contain nested `any` or `all` statements. - See: https://kyverno.io/docs/writing-policies/preconditions/ - properties: - all: - description: |- - AllConditions enable variable-based conditional rule execution. This is useful for - finer control of when an rule is applied. A condition can reference object data - using JMESPath notation. - Here, all of the conditions need to pass - items: - description: Condition defines variable-based - conditional criteria for rule execution. - properties: - key: - description: Key is the context entry - (using JMESPath) for conditional rule - evaluation. - x-kubernetes-preserve-unknown-fields: true - message: - description: Message is an optional - display message - type: string - operator: - description: |- - Operator is the conditional operation to perform. Valid operators are: - Equals, NotEquals, In, AnyIn, AllIn, NotIn, AnyNotIn, AllNotIn, GreaterThanOrEquals, - GreaterThan, LessThanOrEquals, LessThan, DurationGreaterThanOrEquals, DurationGreaterThan, - DurationLessThanOrEquals, DurationLessThan - enum: - - Equals - - NotEquals - - In - - AnyIn - - AllIn - - NotIn - - AnyNotIn - - AllNotIn - - GreaterThanOrEquals - - GreaterThan - - LessThanOrEquals - - LessThan - - DurationGreaterThanOrEquals - - DurationGreaterThan - - DurationLessThanOrEquals - - DurationLessThan - type: string - value: - description: |- - Value is the conditional value, or set of values. The values can be fixed set - or can be variables declared using JMESPath. - x-kubernetes-preserve-unknown-fields: true - type: object - type: array - any: - description: |- - AnyConditions enable variable-based conditional rule execution. This is useful for - finer control of when an rule is applied. A condition can reference object data - using JMESPath notation. - Here, at least one of the conditions need to pass - items: - description: Condition defines variable-based - conditional criteria for rule execution. - properties: - key: - description: Key is the context entry - (using JMESPath) for conditional rule - evaluation. - x-kubernetes-preserve-unknown-fields: true - message: - description: Message is an optional - display message - type: string - operator: - description: |- - Operator is the conditional operation to perform. Valid operators are: - Equals, NotEquals, In, AnyIn, AllIn, NotIn, AnyNotIn, AllNotIn, GreaterThanOrEquals, - GreaterThan, LessThanOrEquals, LessThan, DurationGreaterThanOrEquals, DurationGreaterThan, - DurationLessThanOrEquals, DurationLessThan - enum: - - Equals - - NotEquals - - In - - AnyIn - - AllIn - - NotIn - - AnyNotIn - - AllNotIn - - GreaterThanOrEquals - - GreaterThan - - LessThanOrEquals - - LessThan - - DurationGreaterThanOrEquals - - DurationGreaterThan - - DurationLessThanOrEquals - - DurationLessThan - type: string - value: - description: |- - Value is the conditional value, or set of values. The values can be fixed set - or can be variables declared using JMESPath. - x-kubernetes-preserve-unknown-fields: true - type: object - type: array - type: object - x-kubernetes-preserve-unknown-fields: true - uid: - description: UID specifies the resource uid. - type: string - type: object - type: array - generateExisting: - description: |- - GenerateExisting controls whether to trigger the rule in existing resources - If is set to "true" the rule will be triggered and applied to existing matched resources. - type: boolean - kind: - description: Kind specifies resource kind. - type: string - name: - description: Name specifies the resource name. - type: string - namespace: - description: Namespace specifies resource namespace. - type: string - orphanDownstreamOnPolicyDelete: - description: |- - OrphanDownstreamOnPolicyDelete controls whether generated resources should be deleted when the rule that generated - them is deleted with synchronization enabled. This option is only applicable to generate rules of the data type. - See https://kyverno.io/docs/writing-policies/generate/#data-examples. - Defaults to "false" if not specified. - type: boolean - synchronize: - description: |- - Synchronize controls if generated resources should be kept in-sync with their source resource. - If Synchronize is set to "true" changes to generated resources will be overwritten with resource - data from Data or the resource specified in the Clone declaration. - Optional. Defaults to "false" if not specified. - type: boolean - uid: - description: UID specifies the resource uid. - type: string - type: object - imageExtractors: - additionalProperties: - items: - properties: - jmesPath: - description: |- - JMESPath is an optional JMESPath expression to apply to the image value. - This is useful when the extracted image begins with a prefix like 'docker://'. - The 'trim_prefix' function may be used to trim the prefix: trim_prefix(@, 'docker://'). - Note - Image digest mutation may not be used when applying a JMESPAth to an image. - type: string - key: - description: |- - Key is an optional name of the field within 'path' that will be used to uniquely identify an image. - Note - this field MUST be unique. - type: string - name: - description: |- - Name is the entry the image will be available under 'images.' in the context. - If this field is not defined, image entries will appear under 'images.custom'. - type: string - path: - description: |- - Path is the path to the object containing the image field in a custom resource. - It should be slash-separated. Each slash-separated key must be a valid YAML key or a wildcard '*'. - Wildcard keys are expanded in case of arrays or objects. - type: string - value: - description: |- - Value is an optional name of the field within 'path' that points to the image URI. - This is useful when a custom 'key' is also defined. - type: string - required: - - path - type: object - type: array - description: |- - ImageExtractors defines a mapping from kinds to ImageExtractorConfigs. - This config is only valid for verifyImages rules. - type: object - match: - description: |- - MatchResources defines when this policy rule should be applied. The match - criteria can include resource information (e.g. kind, name, namespace, labels) - and admission review request information like the user name or role. - At least one kind is required. - not: - required: - - any - - all - properties: - all: - description: All allows specifying resources which will - be ANDed - items: - description: ResourceFilter allow users to "AND" or - "OR" between resources - properties: - clusterRoles: - description: ClusterRoles is the list of cluster-wide - role names for the user. - items: - type: string - type: array - resources: - description: ResourceDescription contains information - about the resource being created or modified. - not: - required: - - name - - names - properties: - annotations: - additionalProperties: - type: string - description: |- - Annotations is a map of annotations (key-value pairs of type string). Annotation keys - and values support the wildcard characters "*" (matches zero or many characters) and - "?" (matches at least one character). - type: object - kinds: - description: Kinds is a list of resource kinds. - items: - type: string - type: array - name: - description: |- - Name is the name of the resource. The name supports wildcard characters - "*" (matches zero or many characters) and "?" (at least one character). - NOTE: "Name" is being deprecated in favor of "Names". - type: string - names: - description: |- - Names are the names of the resources. Each name supports wildcard characters - "*" (matches zero or many characters) and "?" (at least one character). - items: - type: string - type: array - namespaceSelector: - description: |- - NamespaceSelector is a label selector for the resource namespace. Label keys and values - in `matchLabels` support the wildcard characters `*` (matches zero or many characters) - and `?` (matches one character).Wildcards allows writing label selectors like - ["storage.k8s.io/*": "*"]. Note that using ["*" : "*"] matches any key and value but - does not match an empty label set. - properties: - matchExpressions: - description: matchExpressions is a list - of label selector requirements. The - requirements are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key - that the selector applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - namespaces: - description: |- - Namespaces is a list of namespaces names. Each name supports wildcard characters - "*" (matches zero or many characters) and "?" (at least one character). - items: - type: string - type: array - operations: - description: Operations can contain values - ["CREATE, "UPDATE", "CONNECT", "DELETE"], - which are used to match a specific action. - items: - description: AdmissionOperation can have - one of the values CREATE, UPDATE, CONNECT, - DELETE, which are used to match a specific - action. - enum: - - CREATE - - CONNECT - - UPDATE - - DELETE - type: string - type: array - selector: - description: |- - Selector is a label selector. Label keys and values in `matchLabels` support the wildcard - characters `*` (matches zero or many characters) and `?` (matches one character). - Wildcards allows writing label selectors like ["storage.k8s.io/*": "*"]. Note that - using ["*" : "*"] matches any key and value but does not match an empty label set. - properties: - matchExpressions: - description: matchExpressions is a list - of label selector requirements. The - requirements are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key - that the selector applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - type: object - roles: - description: Roles is the list of namespaced role - names for the user. - items: - type: string - type: array - subjects: - description: Subjects is the list of subject names - like users, user groups, and service accounts. - items: - description: |- - Subject contains a reference to the object or user identities a role binding applies to. This can either hold a direct API object reference, - or a value for non-objects such as user and group names. - properties: - apiGroup: - description: |- - APIGroup holds the API group of the referenced subject. - Defaults to "" for ServiceAccount subjects. - Defaults to "rbac.authorization.k8s.io" for User and Group subjects. - type: string - kind: - description: |- - Kind of object being referenced. Values defined by this API group are "User", "Group", and "ServiceAccount". - If the Authorizer does not recognized the kind value, the Authorizer should report an error. - type: string - name: - description: Name of the object being referenced. - type: string - namespace: - description: |- - Namespace of the referenced object. If the object kind is non-namespace, such as "User" or "Group", and this value is not empty - the Authorizer should report an error. - type: string - required: - - kind - - name - type: object - x-kubernetes-map-type: atomic - type: array - type: object - type: array - any: - description: Any allows specifying resources which will - be ORed - items: - description: ResourceFilter allow users to "AND" or - "OR" between resources - properties: - clusterRoles: - description: ClusterRoles is the list of cluster-wide - role names for the user. - items: - type: string - type: array - resources: - description: ResourceDescription contains information - about the resource being created or modified. - not: - required: - - name - - names - properties: - annotations: - additionalProperties: - type: string - description: |- - Annotations is a map of annotations (key-value pairs of type string). Annotation keys - and values support the wildcard characters "*" (matches zero or many characters) and - "?" (matches at least one character). - type: object - kinds: - description: Kinds is a list of resource kinds. - items: - type: string - type: array - name: - description: |- - Name is the name of the resource. The name supports wildcard characters - "*" (matches zero or many characters) and "?" (at least one character). - NOTE: "Name" is being deprecated in favor of "Names". - type: string - names: - description: |- - Names are the names of the resources. Each name supports wildcard characters - "*" (matches zero or many characters) and "?" (at least one character). - items: - type: string - type: array - namespaceSelector: - description: |- - NamespaceSelector is a label selector for the resource namespace. Label keys and values - in `matchLabels` support the wildcard characters `*` (matches zero or many characters) - and `?` (matches one character).Wildcards allows writing label selectors like - ["storage.k8s.io/*": "*"]. Note that using ["*" : "*"] matches any key and value but - does not match an empty label set. - properties: - matchExpressions: - description: matchExpressions is a list - of label selector requirements. The - requirements are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key - that the selector applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - namespaces: - description: |- - Namespaces is a list of namespaces names. Each name supports wildcard characters - "*" (matches zero or many characters) and "?" (at least one character). - items: - type: string - type: array - operations: - description: Operations can contain values - ["CREATE, "UPDATE", "CONNECT", "DELETE"], - which are used to match a specific action. - items: - description: AdmissionOperation can have - one of the values CREATE, UPDATE, CONNECT, - DELETE, which are used to match a specific - action. - enum: - - CREATE - - CONNECT - - UPDATE - - DELETE - type: string - type: array - selector: - description: |- - Selector is a label selector. Label keys and values in `matchLabels` support the wildcard - characters `*` (matches zero or many characters) and `?` (matches one character). - Wildcards allows writing label selectors like ["storage.k8s.io/*": "*"]. Note that - using ["*" : "*"] matches any key and value but does not match an empty label set. - properties: - matchExpressions: - description: matchExpressions is a list - of label selector requirements. The - requirements are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key - that the selector applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - type: object - roles: - description: Roles is the list of namespaced role - names for the user. - items: - type: string - type: array - subjects: - description: Subjects is the list of subject names - like users, user groups, and service accounts. - items: - description: |- - Subject contains a reference to the object or user identities a role binding applies to. This can either hold a direct API object reference, - or a value for non-objects such as user and group names. - properties: - apiGroup: - description: |- - APIGroup holds the API group of the referenced subject. - Defaults to "" for ServiceAccount subjects. - Defaults to "rbac.authorization.k8s.io" for User and Group subjects. - type: string - kind: - description: |- - Kind of object being referenced. Values defined by this API group are "User", "Group", and "ServiceAccount". - If the Authorizer does not recognized the kind value, the Authorizer should report an error. - type: string - name: - description: Name of the object being referenced. - type: string - namespace: - description: |- - Namespace of the referenced object. If the object kind is non-namespace, such as "User" or "Group", and this value is not empty - the Authorizer should report an error. - type: string - required: - - kind - - name - type: object - x-kubernetes-map-type: atomic - type: array - type: object - type: array - clusterRoles: - description: ClusterRoles is the list of cluster-wide - role names for the user. - items: - type: string - type: array - resources: - description: |- - ResourceDescription contains information about the resource being created or modified. - Requires at least one tag to be specified when under MatchResources. - Specifying ResourceDescription directly under match is being deprecated. - Please specify under "any" or "all" instead. - not: - required: - - name - - names - properties: - annotations: - additionalProperties: - type: string - description: |- - Annotations is a map of annotations (key-value pairs of type string). Annotation keys - and values support the wildcard characters "*" (matches zero or many characters) and - "?" (matches at least one character). - type: object - kinds: - description: Kinds is a list of resource kinds. - items: - type: string - type: array - name: - description: |- - Name is the name of the resource. The name supports wildcard characters - "*" (matches zero or many characters) and "?" (at least one character). - NOTE: "Name" is being deprecated in favor of "Names". - type: string - names: - description: |- - Names are the names of the resources. Each name supports wildcard characters - "*" (matches zero or many characters) and "?" (at least one character). - items: - type: string - type: array - namespaceSelector: - description: |- - NamespaceSelector is a label selector for the resource namespace. Label keys and values - in `matchLabels` support the wildcard characters `*` (matches zero or many characters) - and `?` (matches one character).Wildcards allows writing label selectors like - ["storage.k8s.io/*": "*"]. Note that using ["*" : "*"] matches any key and value but - does not match an empty label set. - properties: - matchExpressions: - description: matchExpressions is a list of label - selector requirements. The requirements are - ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key that - the selector applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - namespaces: - description: |- - Namespaces is a list of namespaces names. Each name supports wildcard characters - "*" (matches zero or many characters) and "?" (at least one character). - items: - type: string - type: array - operations: - description: Operations can contain values ["CREATE, - "UPDATE", "CONNECT", "DELETE"], which are used - to match a specific action. - items: - description: AdmissionOperation can have one of - the values CREATE, UPDATE, CONNECT, DELETE, - which are used to match a specific action. - enum: - - CREATE - - CONNECT - - UPDATE - - DELETE - type: string - type: array - selector: - description: |- - Selector is a label selector. Label keys and values in `matchLabels` support the wildcard - characters `*` (matches zero or many characters) and `?` (matches one character). - Wildcards allows writing label selectors like ["storage.k8s.io/*": "*"]. Note that - using ["*" : "*"] matches any key and value but does not match an empty label set. - properties: - matchExpressions: - description: matchExpressions is a list of label - selector requirements. The requirements are - ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key that - the selector applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - type: object - roles: - description: Roles is the list of namespaced role names - for the user. - items: - type: string - type: array - subjects: - description: Subjects is the list of subject names like - users, user groups, and service accounts. - items: - description: |- - Subject contains a reference to the object or user identities a role binding applies to. This can either hold a direct API object reference, - or a value for non-objects such as user and group names. - properties: - apiGroup: - description: |- - APIGroup holds the API group of the referenced subject. - Defaults to "" for ServiceAccount subjects. - Defaults to "rbac.authorization.k8s.io" for User and Group subjects. - type: string - kind: - description: |- - Kind of object being referenced. Values defined by this API group are "User", "Group", and "ServiceAccount". - If the Authorizer does not recognized the kind value, the Authorizer should report an error. - type: string - name: - description: Name of the object being referenced. - type: string - namespace: - description: |- - Namespace of the referenced object. If the object kind is non-namespace, such as "User" or "Group", and this value is not empty - the Authorizer should report an error. - type: string - required: - - kind - - name - type: object - x-kubernetes-map-type: atomic - type: array - type: object - mutate: - description: Mutation is used to modify matching resources. - properties: - foreach: - description: ForEach applies mutation rules to a list - of sub-elements by creating a context for each entry - in the list and looping over it to apply the specified - logic. - items: - description: ForEachMutation applies mutation rules - to a list of sub-elements by creating a context - for each entry in the list and looping over it to - apply the specified logic. - properties: - context: - description: Context defines variables and data - sources that can be used during rule execution. - items: - description: |- - ContextEntry adds variables and data sources to a rule Context. Either a - ConfigMap reference or a APILookup must be provided. - oneOf: - - required: - - configMap - - required: - - apiCall - - required: - - imageRegistry - - required: - - variable - - required: - - globalReference - properties: - apiCall: - description: |- - APICall is an HTTP request to the Kubernetes API server, or other JSON web service. - The data returned is stored in the context with the name for the context entry. - properties: - data: - description: |- - The data object specifies the POST data sent to the server. - Only applicable when the method field is set to POST. - items: - description: RequestData contains - the HTTP POST data - properties: - key: - description: Key is a unique identifier - for the data value - type: string - value: - description: Value is the data - value - x-kubernetes-preserve-unknown-fields: true - required: - - key - - value - type: object - type: array - default: - description: |- - Default is an optional arbitrary JSON object that the context - value is set to, if the apiCall returns error. - x-kubernetes-preserve-unknown-fields: true - jmesPath: - description: |- - JMESPath is an optional JSON Match Expression that can be used to - transform the JSON response returned from the server. For example - a JMESPath of "items | length(@)" applied to the API server response - for the URLPath "/apis/apps/v1/deployments" will return the total count - of deployments across all namespaces. - type: string - method: - default: GET - description: Method is the HTTP request - type (GET or POST). Defaults to GET. - enum: - - GET - - POST - type: string - service: - description: |- - Service is an API call to a JSON web service. - This is used for non-Kubernetes API server calls. - It's mutually exclusive with the URLPath field. - properties: - caBundle: - description: |- - CABundle is a PEM encoded CA bundle which will be used to validate - the server certificate. - type: string - headers: - description: Headers is a list of - optional HTTP headers to be included - in the request. - items: - properties: - key: - description: Key is the header - key - type: string - value: - description: Value is the - header value - type: string - required: - - key - - value - type: object - type: array - url: - description: |- - URL is the JSON web service URL. A typical form is - `https://{service}.{namespace}:{port}/{path}`. - type: string - required: - - url - type: object - urlPath: - description: |- - URLPath is the URL path to be used in the HTTP GET or POST request to the - Kubernetes API server (e.g. "/api/v1/namespaces" or "/apis/apps/v1/deployments"). - The format required is the same format used by the `kubectl get --raw` command. - See https://kyverno.io/docs/writing-policies/external-data-sources/#variables-from-kubernetes-api-server-calls - for details. - It's mutually exclusive with the Service field. - type: string - type: object - configMap: - description: ConfigMap is the ConfigMap - reference. - properties: - name: - description: Name is the ConfigMap name. - type: string - namespace: - description: Namespace is the ConfigMap - namespace. - type: string - required: - - name - type: object - globalReference: - description: GlobalContextEntryReference - is a reference to a cached global context - entry. - properties: - jmesPath: - description: |- - JMESPath is an optional JSON Match Expression that can be used to - transform the JSON response returned from the server. For example - a JMESPath of "items | length(@)" applied to the API server response - for the URLPath "/apis/apps/v1/deployments" will return the total count - of deployments across all namespaces. - type: string - name: - description: Name of the global context - entry - type: string - required: - - name - type: object - imageRegistry: - description: |- - ImageRegistry defines requests to an OCI/Docker V2 registry to fetch image - details. - properties: - imageRegistryCredentials: - description: ImageRegistryCredentials - provides credentials that will be - used for authentication with registry - properties: - allowInsecureRegistry: - description: AllowInsecureRegistry - allows insecure access to a registry. - type: boolean - providers: - description: |- - Providers specifies a list of OCI Registry names, whose authentication providers are provided. - It can be of one of these values: default,google,azure,amazon,github. - items: - description: ImageRegistryCredentialsProvidersType - provides the list of credential - providers required. - enum: - - default - - amazon - - azure - - google - - github - type: string - type: array - secrets: - description: |- - Secrets specifies a list of secrets that are provided for credentials. - Secrets must live in the Kyverno namespace. - items: - type: string - type: array - type: object - jmesPath: - description: |- - JMESPath is an optional JSON Match Expression that can be used to - transform the ImageData struct returned as a result of processing - the image reference. - type: string - reference: - description: |- - Reference is image reference to a container image in the registry. - Example: ghcr.io/kyverno/kyverno:latest - type: string - required: - - reference - type: object - name: - description: Name is the variable name. - type: string - variable: - description: Variable defines an arbitrary - JMESPath context variable that can be - defined inline. - properties: - default: - description: |- - Default is an optional arbitrary JSON object that the variable may take if the JMESPath - expression evaluates to nil - x-kubernetes-preserve-unknown-fields: true - jmesPath: - description: |- - JMESPath is an optional JMESPath Expression that can be used to - transform the variable. - type: string - value: - description: Value is any arbitrary - JSON object representable in YAML - or JSON form. - x-kubernetes-preserve-unknown-fields: true - type: object - required: - - name - type: object - type: array - foreach: - description: Foreach declares a nested foreach - iterator - x-kubernetes-preserve-unknown-fields: true - list: - description: |- - List specifies a JMESPath expression that results in one or more elements - to which the validation logic is applied. - type: string - order: - description: |- - Order defines the iteration order on the list. - Can be Ascending to iterate from first to last element or Descending to iterate in from last to first element. - enum: - - Ascending - - Descending - type: string - patchStrategicMerge: - description: |- - PatchStrategicMerge is a strategic merge patch used to modify resources. - See https://kubernetes.io/docs/tasks/manage-kubernetes-objects/update-api-object-kubectl-patch/ - and https://kubectl.docs.kubernetes.io/references/kustomize/kustomization/patchesstrategicmerge/. - x-kubernetes-preserve-unknown-fields: true - patchesJson6902: - description: |- - PatchesJSON6902 is a list of RFC 6902 JSON Patch declarations used to modify resources. - See https://tools.ietf.org/html/rfc6902 and https://kubectl.docs.kubernetes.io/references/kustomize/kustomization/patchesjson6902/. - type: string - preconditions: - description: |- - AnyAllConditions are used to determine if a policy rule should be applied by evaluating a - set of conditions. The declaration can contain nested `any` or `all` statements. - See: https://kyverno.io/docs/writing-policies/preconditions/ - properties: - all: - description: |- - AllConditions enable variable-based conditional rule execution. This is useful for - finer control of when an rule is applied. A condition can reference object data - using JMESPath notation. - Here, all of the conditions need to pass - items: - description: Condition defines variable-based - conditional criteria for rule execution. - properties: - key: - description: Key is the context entry - (using JMESPath) for conditional rule - evaluation. - x-kubernetes-preserve-unknown-fields: true - message: - description: Message is an optional - display message - type: string - operator: - description: |- - Operator is the conditional operation to perform. Valid operators are: - Equals, NotEquals, In, AnyIn, AllIn, NotIn, AnyNotIn, AllNotIn, GreaterThanOrEquals, - GreaterThan, LessThanOrEquals, LessThan, DurationGreaterThanOrEquals, DurationGreaterThan, - DurationLessThanOrEquals, DurationLessThan - enum: - - Equals - - NotEquals - - In - - AnyIn - - AllIn - - NotIn - - AnyNotIn - - AllNotIn - - GreaterThanOrEquals - - GreaterThan - - LessThanOrEquals - - LessThan - - DurationGreaterThanOrEquals - - DurationGreaterThan - - DurationLessThanOrEquals - - DurationLessThan - type: string - value: - description: |- - Value is the conditional value, or set of values. The values can be fixed set - or can be variables declared using JMESPath. - x-kubernetes-preserve-unknown-fields: true - type: object - type: array - any: - description: |- - AnyConditions enable variable-based conditional rule execution. This is useful for - finer control of when an rule is applied. A condition can reference object data - using JMESPath notation. - Here, at least one of the conditions need to pass - items: - description: Condition defines variable-based - conditional criteria for rule execution. - properties: - key: - description: Key is the context entry - (using JMESPath) for conditional rule - evaluation. - x-kubernetes-preserve-unknown-fields: true - message: - description: Message is an optional - display message - type: string - operator: - description: |- - Operator is the conditional operation to perform. Valid operators are: - Equals, NotEquals, In, AnyIn, AllIn, NotIn, AnyNotIn, AllNotIn, GreaterThanOrEquals, - GreaterThan, LessThanOrEquals, LessThan, DurationGreaterThanOrEquals, DurationGreaterThan, - DurationLessThanOrEquals, DurationLessThan - enum: - - Equals - - NotEquals - - In - - AnyIn - - AllIn - - NotIn - - AnyNotIn - - AllNotIn - - GreaterThanOrEquals - - GreaterThan - - LessThanOrEquals - - LessThan - - DurationGreaterThanOrEquals - - DurationGreaterThan - - DurationLessThanOrEquals - - DurationLessThan - type: string - value: - description: |- - Value is the conditional value, or set of values. The values can be fixed set - or can be variables declared using JMESPath. - x-kubernetes-preserve-unknown-fields: true - type: object - type: array - type: object - x-kubernetes-preserve-unknown-fields: true - type: object - type: array - mutateExistingOnPolicyUpdate: - description: MutateExistingOnPolicyUpdate controls if - the mutateExisting rule will be applied on policy - events. - type: boolean - patchStrategicMerge: - description: |- - PatchStrategicMerge is a strategic merge patch used to modify resources. - See https://kubernetes.io/docs/tasks/manage-kubernetes-objects/update-api-object-kubectl-patch/ - and https://kubectl.docs.kubernetes.io/references/kustomize/kustomization/patchesstrategicmerge/. - x-kubernetes-preserve-unknown-fields: true - patchesJson6902: - description: |- - PatchesJSON6902 is a list of RFC 6902 JSON Patch declarations used to modify resources. - See https://tools.ietf.org/html/rfc6902 and https://kubectl.docs.kubernetes.io/references/kustomize/kustomization/patchesjson6902/. - type: string - targets: - description: Targets defines the target resources to - be mutated. - items: - description: TargetResourceSpec defines targets for - mutating existing resources. - properties: - apiVersion: - description: APIVersion specifies resource apiVersion. - type: string - context: - description: Context defines variables and data - sources that can be used during rule execution. - items: - description: |- - ContextEntry adds variables and data sources to a rule Context. Either a - ConfigMap reference or a APILookup must be provided. - oneOf: - - required: - - configMap - - required: - - apiCall - - required: - - imageRegistry - - required: - - variable - - required: - - globalReference - properties: - apiCall: - description: |- - APICall is an HTTP request to the Kubernetes API server, or other JSON web service. - The data returned is stored in the context with the name for the context entry. - properties: - data: - description: |- - The data object specifies the POST data sent to the server. - Only applicable when the method field is set to POST. - items: - description: RequestData contains - the HTTP POST data - properties: - key: - description: Key is a unique identifier - for the data value - type: string - value: - description: Value is the data - value - x-kubernetes-preserve-unknown-fields: true - required: - - key - - value - type: object - type: array - default: - description: |- - Default is an optional arbitrary JSON object that the context - value is set to, if the apiCall returns error. - x-kubernetes-preserve-unknown-fields: true - jmesPath: - description: |- - JMESPath is an optional JSON Match Expression that can be used to - transform the JSON response returned from the server. For example - a JMESPath of "items | length(@)" applied to the API server response - for the URLPath "/apis/apps/v1/deployments" will return the total count - of deployments across all namespaces. - type: string - method: - default: GET - description: Method is the HTTP request - type (GET or POST). Defaults to GET. - enum: - - GET - - POST - type: string - service: - description: |- - Service is an API call to a JSON web service. - This is used for non-Kubernetes API server calls. - It's mutually exclusive with the URLPath field. - properties: - caBundle: - description: |- - CABundle is a PEM encoded CA bundle which will be used to validate - the server certificate. - type: string - headers: - description: Headers is a list of - optional HTTP headers to be included - in the request. - items: - properties: - key: - description: Key is the header - key - type: string - value: - description: Value is the - header value - type: string - required: - - key - - value - type: object - type: array - url: - description: |- - URL is the JSON web service URL. A typical form is - `https://{service}.{namespace}:{port}/{path}`. - type: string - required: - - url - type: object - urlPath: - description: |- - URLPath is the URL path to be used in the HTTP GET or POST request to the - Kubernetes API server (e.g. "/api/v1/namespaces" or "/apis/apps/v1/deployments"). - The format required is the same format used by the `kubectl get --raw` command. - See https://kyverno.io/docs/writing-policies/external-data-sources/#variables-from-kubernetes-api-server-calls - for details. - It's mutually exclusive with the Service field. - type: string - type: object - configMap: - description: ConfigMap is the ConfigMap - reference. - properties: - name: - description: Name is the ConfigMap name. - type: string - namespace: - description: Namespace is the ConfigMap - namespace. - type: string - required: - - name - type: object - globalReference: - description: GlobalContextEntryReference - is a reference to a cached global context - entry. - properties: - jmesPath: - description: |- - JMESPath is an optional JSON Match Expression that can be used to - transform the JSON response returned from the server. For example - a JMESPath of "items | length(@)" applied to the API server response - for the URLPath "/apis/apps/v1/deployments" will return the total count - of deployments across all namespaces. - type: string - name: - description: Name of the global context - entry - type: string - required: - - name - type: object - imageRegistry: - description: |- - ImageRegistry defines requests to an OCI/Docker V2 registry to fetch image - details. - properties: - imageRegistryCredentials: - description: ImageRegistryCredentials - provides credentials that will be - used for authentication with registry - properties: - allowInsecureRegistry: - description: AllowInsecureRegistry - allows insecure access to a registry. - type: boolean - providers: - description: |- - Providers specifies a list of OCI Registry names, whose authentication providers are provided. - It can be of one of these values: default,google,azure,amazon,github. - items: - description: ImageRegistryCredentialsProvidersType - provides the list of credential - providers required. - enum: - - default - - amazon - - azure - - google - - github - type: string - type: array - secrets: - description: |- - Secrets specifies a list of secrets that are provided for credentials. - Secrets must live in the Kyverno namespace. - items: - type: string - type: array - type: object - jmesPath: - description: |- - JMESPath is an optional JSON Match Expression that can be used to - transform the ImageData struct returned as a result of processing - the image reference. - type: string - reference: - description: |- - Reference is image reference to a container image in the registry. - Example: ghcr.io/kyverno/kyverno:latest - type: string - required: - - reference - type: object - name: - description: Name is the variable name. - type: string - variable: - description: Variable defines an arbitrary - JMESPath context variable that can be - defined inline. - properties: - default: - description: |- - Default is an optional arbitrary JSON object that the variable may take if the JMESPath - expression evaluates to nil - x-kubernetes-preserve-unknown-fields: true - jmesPath: - description: |- - JMESPath is an optional JMESPath Expression that can be used to - transform the variable. - type: string - value: - description: Value is any arbitrary - JSON object representable in YAML - or JSON form. - x-kubernetes-preserve-unknown-fields: true - type: object - required: - - name - type: object - type: array - kind: - description: Kind specifies resource kind. - type: string - name: - description: Name specifies the resource name. - type: string - namespace: - description: Namespace specifies resource namespace. - type: string - preconditions: - description: |- - Preconditions are used to determine if a policy rule should be applied by evaluating a - set of conditions. The declaration can contain nested `any` or `all` statements. A direct list - of conditions (without `any` or `all` statements is supported for backwards compatibility but - will be deprecated in the next major release. - See: https://kyverno.io/docs/writing-policies/preconditions/ - x-kubernetes-preserve-unknown-fields: true - selector: - description: Selector allows you to select target - resources with their labels. - properties: - matchExpressions: - description: matchExpressions is a list of - label selector requirements. The requirements - are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key that - the selector applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - uid: - description: UID specifies the resource uid. - type: string - type: object - type: array - type: object - name: - description: Name is a label to identify the rule, It must - be unique within the policy. - maxLength: 63 - type: string - preconditions: - description: |- - Preconditions are used to determine if a policy rule should be applied by evaluating a - set of conditions. The declaration can contain nested `any` or `all` statements. A direct list - of conditions (without `any` or `all` statements is supported for backwards compatibility but - will be deprecated in the next major release. - See: https://kyverno.io/docs/writing-policies/preconditions/ - x-kubernetes-preserve-unknown-fields: true - reportProperties: - additionalProperties: - type: string - description: ReportProperties are the additional properties - from the rule that will be added to the policy report - result - type: object - skipBackgroundRequests: - default: true - description: |- - SkipBackgroundRequests bypasses admission requests that are sent by the background controller. - The default value is set to "true", it must be set to "false" to apply - generate and mutateExisting rules to those requests. - type: boolean - validate: - description: Validation is used to validate matching resources. - properties: - allowExistingViolations: - default: true - description: AllowExistingViolations allows prexisting - violating resources to continue violating a policy. - type: boolean - anyPattern: - description: |- - AnyPattern specifies list of validation patterns. At least one of the patterns - must be satisfied for the validation rule to succeed. - x-kubernetes-preserve-unknown-fields: true - assert: - description: Assert defines a kyverno-json assertion - tree. - type: object - x-kubernetes-preserve-unknown-fields: true - cel: - description: CEL allows validation checks using the - Common Expression Language (https://kubernetes.io/docs/reference/using-api/cel/). - properties: - auditAnnotations: - description: AuditAnnotations contains CEL expressions - which are used to produce audit annotations for - the audit event of the API request. - items: - description: AuditAnnotation describes how to - produce an audit annotation for an API request. - properties: - key: - description: |- - key specifies the audit annotation key. The audit annotation keys of - a ValidatingAdmissionPolicy must be unique. The key must be a qualified - name ([A-Za-z0-9][-A-Za-z0-9_.]*) no more than 63 bytes in length. - - The key is combined with the resource name of the - ValidatingAdmissionPolicy to construct an audit annotation key: - "{ValidatingAdmissionPolicy name}/{key}". - - If an admission webhook uses the same resource name as this ValidatingAdmissionPolicy - and the same audit annotation key, the annotation key will be identical. - In this case, the first annotation written with the key will be included - in the audit event and all subsequent annotations with the same key - will be discarded. - - Required. - type: string - valueExpression: - description: |- - valueExpression represents the expression which is evaluated by CEL to - produce an audit annotation value. The expression must evaluate to either - a string or null value. If the expression evaluates to a string, the - audit annotation is included with the string value. If the expression - evaluates to null or empty string the audit annotation will be omitted. - The valueExpression may be no longer than 5kb in length. - If the result of the valueExpression is more than 10kb in length, it - will be truncated to 10kb. - - If multiple ValidatingAdmissionPolicyBinding resources match an - API request, then the valueExpression will be evaluated for - each binding. All unique values produced by the valueExpressions - will be joined together in a comma-separated list. - - Required. - type: string - required: - - key - - valueExpression - type: object - type: array - expressions: - description: Expressions is a list of CELExpression - types. - items: - description: Validation specifies the CEL expression - which is used to apply the validation. - properties: - expression: - description: "Expression represents the expression - which will be evaluated by CEL.\nref: https://github.com/google/cel-spec\nCEL - expressions have access to the contents - of the API request/response, organized into - CEL variables as well as some other useful - variables:\n\n- 'object' - The object from - the incoming request. The value is null - for DELETE requests.\n- 'oldObject' - The - existing object. The value is null for CREATE - requests.\n- 'request' - Attributes of the - API request([ref](/pkg/apis/admission/types.go#AdmissionRequest)).\n- - 'params' - Parameter resource referred to - by the policy binding being evaluated. Only - populated if the policy has a ParamKind.\n- - 'namespaceObject' - The namespace object - that the incoming object belongs to. The - value is null for cluster-scoped resources.\n- - 'variables' - Map of composited variables, - from its name to its lazily evaluated value.\n - \ For example, a variable named 'foo' can - be accessed as 'variables.foo'.\n- 'authorizer' - - A CEL Authorizer. May be used to perform - authorization checks for the principal (user - or service account) of the request.\n See - https://pkg.go.dev/k8s.io/apiserver/pkg/cel/library#Authz\n- - 'authorizer.requestResource' - A CEL ResourceCheck - constructed from the 'authorizer' and configured - with the\n request resource.\n\nThe `apiVersion`, - `kind`, `metadata.name` and `metadata.generateName` - are always accessible from the root of the\nobject. - No other metadata properties are accessible.\n\nOnly - property names of the form `[a-zA-Z_.-/][a-zA-Z0-9_.-/]*` - are accessible.\nAccessible property names - are escaped according to the following rules - when accessed in the expression:\n- '__' - escapes to '__underscores__'\n- '.' escapes - to '__dot__'\n- '-' escapes to '__dash__'\n- - '/' escapes to '__slash__'\n- Property names - that exactly match a CEL RESERVED keyword - escape to '__{keyword}__'. The keywords - are:\n\t \"true\", \"false\", \"null\", - \"in\", \"as\", \"break\", \"const\", \"continue\", - \"else\", \"for\", \"function\", \"if\",\n\t - \ \"import\", \"let\", \"loop\", \"package\", - \"namespace\", \"return\".\nExamples:\n - \ - Expression accessing a property named - \"namespace\": {\"Expression\": \"object.__namespace__ - > 0\"}\n - Expression accessing a property - named \"x-prop\": {\"Expression\": \"object.x__dash__prop - > 0\"}\n - Expression accessing a property - named \"redact__d\": {\"Expression\": \"object.redact__underscores__d - > 0\"}\n\nEquality on arrays with list type - of 'set' or 'map' ignores element order, - i.e. [1, 2] == [2, 1].\nConcatenation on - arrays with x-kubernetes-list-type use the - semantics of the list type:\n - 'set': - `X + Y` performs a union where the array - positions of all elements in `X` are preserved - and\n non-intersecting elements in `Y` - are appended, retaining their partial order.\n - \ - 'map': `X + Y` performs a merge where - the array positions of all keys in `X` are - preserved but the values\n are overwritten - by values in `Y` when the key sets of `X` - and `Y` intersect. Elements in `Y` with\n - \ non-intersecting keys are appended, - retaining their partial order.\nRequired." - type: string - message: - description: |- - Message represents the message displayed when validation fails. The message is required if the Expression contains - line breaks. The message must not contain line breaks. - If unset, the message is "failed rule: {Rule}". - e.g. "must be a URL with the host matching spec.host" - If the Expression contains line breaks. Message is required. - The message must not contain line breaks. - If unset, the message is "failed Expression: {Expression}". - type: string - messageExpression: - description: |- - messageExpression declares a CEL expression that evaluates to the validation failure message that is returned when this rule fails. - Since messageExpression is used as a failure message, it must evaluate to a string. - If both message and messageExpression are present on a validation, then messageExpression will be used if validation fails. - If messageExpression results in a runtime error, the runtime error is logged, and the validation failure message is produced - as if the messageExpression field were unset. If messageExpression evaluates to an empty string, a string with only spaces, or a string - that contains line breaks, then the validation failure message will also be produced as if the messageExpression field were unset, and - the fact that messageExpression produced an empty string/string with only spaces/string with line breaks will be logged. - messageExpression has access to all the same variables as the `expression` except for 'authorizer' and 'authorizer.requestResource'. - Example: - "object.x must be less than max ("+string(params.max)+")" - type: string - reason: - description: |- - Reason represents a machine-readable description of why this validation failed. - If this is the first validation in the list to fail, this reason, as well as the - corresponding HTTP response code, are used in the - HTTP response to the client. - The currently supported reasons are: "Unauthorized", "Forbidden", "Invalid", "RequestEntityTooLarge". - If not set, StatusReasonInvalid is used in the response to the client. - type: string - required: - - expression - type: object - type: array - generate: - default: false - description: |- - Generate specifies whether to generate a Kubernetes ValidatingAdmissionPolicy from the rule. - Optional. Defaults to "false" if not specified. - type: boolean - paramKind: - description: ParamKind is a tuple of Group Kind - and Version. - properties: - apiVersion: - description: |- - APIVersion is the API group version the resources belong to. - In format of "group/version". - Required. - type: string - kind: - description: |- - Kind is the API kind the resources belong to. - Required. - type: string - type: object - x-kubernetes-map-type: atomic - paramRef: - description: ParamRef references a parameter resource. - properties: - name: - description: |- - name is the name of the resource being referenced. - - One of `name` or `selector` must be set, but `name` and `selector` are - mutually exclusive properties. If one is set, the other must be unset. - - A single parameter used for all admission requests can be configured - by setting the `name` field, leaving `selector` blank, and setting namespace - if `paramKind` is namespace-scoped. - type: string - namespace: - description: |- - namespace is the namespace of the referenced resource. Allows limiting - the search for params to a specific namespace. Applies to both `name` and - `selector` fields. - - A per-namespace parameter may be used by specifying a namespace-scoped - `paramKind` in the policy and leaving this field empty. - - - If `paramKind` is cluster-scoped, this field MUST be unset. Setting this - field results in a configuration error. - - - If `paramKind` is namespace-scoped, the namespace of the object being - evaluated for admission will be used when this field is left unset. Take - care that if this is left empty the binding must not match any cluster-scoped - resources, which will result in an error. - type: string - parameterNotFoundAction: - description: |- - `parameterNotFoundAction` controls the behavior of the binding when the resource - exists, and name or selector is valid, but there are no parameters - matched by the binding. If the value is set to `Allow`, then no - matched parameters will be treated as successful validation by the binding. - If set to `Deny`, then no matched parameters will be subject to the - `failurePolicy` of the policy. - - Allowed values are `Allow` or `Deny` - - Required - type: string - selector: - description: |- - selector can be used to match multiple param objects based on their labels. - Supply selector: {} to match all resources of the ParamKind. - - If multiple params are found, they are all evaluated with the policy expressions - and the results are ANDed together. - - One of `name` or `selector` must be set, but `name` and `selector` are - mutually exclusive properties. If one is set, the other must be unset. - properties: - matchExpressions: - description: matchExpressions is a list - of label selector requirements. The requirements - are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key - that the selector applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - type: object - x-kubernetes-map-type: atomic - variables: - description: |- - Variables contain definitions of variables that can be used in composition of other expressions. - Each variable is defined as a named CEL expression. - The variables defined here will be available under `variables` in other expressions of the policy. - items: - description: Variable is the definition of a variable - that is used for composition. A variable is - defined as a named expression. - properties: - expression: - description: |- - Expression is the expression that will be evaluated as the value of the variable. - The CEL expression has access to the same identifiers as the CEL expressions in Validation. - type: string - name: - description: |- - Name is the name of the variable. The name must be a valid CEL identifier and unique among all variables. - The variable can be accessed in other expressions through `variables` - For example, if name is "foo", the variable will be available as `variables.foo` - type: string - required: - - expression - - name - type: object - x-kubernetes-map-type: atomic - type: array - type: object - deny: - description: Deny defines conditions used to pass or - fail a validation rule. - properties: - conditions: - description: |- - Multiple conditions can be declared under an `any` or `all` statement. A direct list - of conditions (without `any` or `all` statements) is also supported for backwards compatibility - but will be deprecated in the next major release. - See: https://kyverno.io/docs/writing-policies/validate/#deny-rules - x-kubernetes-preserve-unknown-fields: true - type: object - failureAction: - description: |- - FailureAction defines if a validation policy rule violation should block - the admission review request (Enforce), or allow (Audit) the admission review request - and report an error in a policy report. Optional. - Allowed values are Audit or Enforce. - enum: - - Audit - - Enforce - type: string - failureActionOverrides: - description: |- - FailureActionOverrides is a Cluster Policy attribute that specifies FailureAction - namespace-wise. It overrides FailureAction for the specified namespaces. - items: - properties: - action: - description: ValidationFailureAction defines the - policy validation failure action - enum: - - audit - - enforce - - Audit - - Enforce - type: string - namespaceSelector: - description: |- - A label selector is a label query over a set of resources. The result of matchLabels and - matchExpressions are ANDed. An empty label selector matches all objects. A null - label selector matches no objects. - properties: - matchExpressions: - description: matchExpressions is a list of - label selector requirements. The requirements - are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key that - the selector applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - namespaces: - items: - type: string - type: array - type: object - type: array - foreach: - description: ForEach applies validate rules to a list - of sub-elements by creating a context for each entry - in the list and looping over it to apply the specified - logic. - items: - description: ForEachValidation applies validate rules - to a list of sub-elements by creating a context - for each entry in the list and looping over it to - apply the specified logic. - properties: - anyPattern: - description: |- - AnyPattern specifies list of validation patterns. At least one of the patterns - must be satisfied for the validation rule to succeed. - x-kubernetes-preserve-unknown-fields: true - context: - description: Context defines variables and data - sources that can be used during rule execution. - items: - description: |- - ContextEntry adds variables and data sources to a rule Context. Either a - ConfigMap reference or a APILookup must be provided. - oneOf: - - required: - - configMap - - required: - - apiCall - - required: - - imageRegistry - - required: - - variable - - required: - - globalReference - properties: - apiCall: - description: |- - APICall is an HTTP request to the Kubernetes API server, or other JSON web service. - The data returned is stored in the context with the name for the context entry. - properties: - data: - description: |- - The data object specifies the POST data sent to the server. - Only applicable when the method field is set to POST. - items: - description: RequestData contains - the HTTP POST data - properties: - key: - description: Key is a unique identifier - for the data value - type: string - value: - description: Value is the data - value - x-kubernetes-preserve-unknown-fields: true - required: - - key - - value - type: object - type: array - default: - description: |- - Default is an optional arbitrary JSON object that the context - value is set to, if the apiCall returns error. - x-kubernetes-preserve-unknown-fields: true - jmesPath: - description: |- - JMESPath is an optional JSON Match Expression that can be used to - transform the JSON response returned from the server. For example - a JMESPath of "items | length(@)" applied to the API server response - for the URLPath "/apis/apps/v1/deployments" will return the total count - of deployments across all namespaces. - type: string - method: - default: GET - description: Method is the HTTP request - type (GET or POST). Defaults to GET. - enum: - - GET - - POST - type: string - service: - description: |- - Service is an API call to a JSON web service. - This is used for non-Kubernetes API server calls. - It's mutually exclusive with the URLPath field. - properties: - caBundle: - description: |- - CABundle is a PEM encoded CA bundle which will be used to validate - the server certificate. - type: string - headers: - description: Headers is a list of - optional HTTP headers to be included - in the request. - items: - properties: - key: - description: Key is the header - key - type: string - value: - description: Value is the - header value - type: string - required: - - key - - value - type: object - type: array - url: - description: |- - URL is the JSON web service URL. A typical form is - `https://{service}.{namespace}:{port}/{path}`. - type: string - required: - - url - type: object - urlPath: - description: |- - URLPath is the URL path to be used in the HTTP GET or POST request to the - Kubernetes API server (e.g. "/api/v1/namespaces" or "/apis/apps/v1/deployments"). - The format required is the same format used by the `kubectl get --raw` command. - See https://kyverno.io/docs/writing-policies/external-data-sources/#variables-from-kubernetes-api-server-calls - for details. - It's mutually exclusive with the Service field. - type: string - type: object - configMap: - description: ConfigMap is the ConfigMap - reference. - properties: - name: - description: Name is the ConfigMap name. - type: string - namespace: - description: Namespace is the ConfigMap - namespace. - type: string - required: - - name - type: object - globalReference: - description: GlobalContextEntryReference - is a reference to a cached global context - entry. - properties: - jmesPath: - description: |- - JMESPath is an optional JSON Match Expression that can be used to - transform the JSON response returned from the server. For example - a JMESPath of "items | length(@)" applied to the API server response - for the URLPath "/apis/apps/v1/deployments" will return the total count - of deployments across all namespaces. - type: string - name: - description: Name of the global context - entry - type: string - required: - - name - type: object - imageRegistry: - description: |- - ImageRegistry defines requests to an OCI/Docker V2 registry to fetch image - details. - properties: - imageRegistryCredentials: - description: ImageRegistryCredentials - provides credentials that will be - used for authentication with registry - properties: - allowInsecureRegistry: - description: AllowInsecureRegistry - allows insecure access to a registry. - type: boolean - providers: - description: |- - Providers specifies a list of OCI Registry names, whose authentication providers are provided. - It can be of one of these values: default,google,azure,amazon,github. - items: - description: ImageRegistryCredentialsProvidersType - provides the list of credential - providers required. - enum: - - default - - amazon - - azure - - google - - github - type: string - type: array - secrets: - description: |- - Secrets specifies a list of secrets that are provided for credentials. - Secrets must live in the Kyverno namespace. - items: - type: string - type: array - type: object - jmesPath: - description: |- - JMESPath is an optional JSON Match Expression that can be used to - transform the ImageData struct returned as a result of processing - the image reference. - type: string - reference: - description: |- - Reference is image reference to a container image in the registry. - Example: ghcr.io/kyverno/kyverno:latest - type: string - required: - - reference - type: object - name: - description: Name is the variable name. - type: string - variable: - description: Variable defines an arbitrary - JMESPath context variable that can be - defined inline. - properties: - default: - description: |- - Default is an optional arbitrary JSON object that the variable may take if the JMESPath - expression evaluates to nil - x-kubernetes-preserve-unknown-fields: true - jmesPath: - description: |- - JMESPath is an optional JMESPath Expression that can be used to - transform the variable. - type: string - value: - description: Value is any arbitrary - JSON object representable in YAML - or JSON form. - x-kubernetes-preserve-unknown-fields: true - type: object - required: - - name - type: object - type: array - deny: - description: Deny defines conditions used to pass - or fail a validation rule. - properties: - conditions: - description: |- - Multiple conditions can be declared under an `any` or `all` statement. A direct list - of conditions (without `any` or `all` statements) is also supported for backwards compatibility - but will be deprecated in the next major release. - See: https://kyverno.io/docs/writing-policies/validate/#deny-rules - x-kubernetes-preserve-unknown-fields: true - type: object - elementScope: - description: |- - ElementScope specifies whether to use the current list element as the scope for validation. Defaults to "true" if not specified. - When set to "false", "request.object" is used as the validation scope within the foreach - block to allow referencing other elements in the subtree. - type: boolean - foreach: - description: Foreach declares a nested foreach - iterator - x-kubernetes-preserve-unknown-fields: true - list: - description: |- - List specifies a JMESPath expression that results in one or more elements - to which the validation logic is applied. - type: string - pattern: - description: Pattern specifies an overlay-style - pattern used to check resources. - x-kubernetes-preserve-unknown-fields: true - preconditions: - description: |- - AnyAllConditions are used to determine if a policy rule should be applied by evaluating a - set of conditions. The declaration can contain nested `any` or `all` statements. - See: https://kyverno.io/docs/writing-policies/preconditions/ - properties: - all: - description: |- - AllConditions enable variable-based conditional rule execution. This is useful for - finer control of when an rule is applied. A condition can reference object data - using JMESPath notation. - Here, all of the conditions need to pass - items: - description: Condition defines variable-based - conditional criteria for rule execution. - properties: - key: - description: Key is the context entry - (using JMESPath) for conditional rule - evaluation. - x-kubernetes-preserve-unknown-fields: true - message: - description: Message is an optional - display message - type: string - operator: - description: |- - Operator is the conditional operation to perform. Valid operators are: - Equals, NotEquals, In, AnyIn, AllIn, NotIn, AnyNotIn, AllNotIn, GreaterThanOrEquals, - GreaterThan, LessThanOrEquals, LessThan, DurationGreaterThanOrEquals, DurationGreaterThan, - DurationLessThanOrEquals, DurationLessThan - enum: - - Equals - - NotEquals - - In - - AnyIn - - AllIn - - NotIn - - AnyNotIn - - AllNotIn - - GreaterThanOrEquals - - GreaterThan - - LessThanOrEquals - - LessThan - - DurationGreaterThanOrEquals - - DurationGreaterThan - - DurationLessThanOrEquals - - DurationLessThan - type: string - value: - description: |- - Value is the conditional value, or set of values. The values can be fixed set - or can be variables declared using JMESPath. - x-kubernetes-preserve-unknown-fields: true - type: object - type: array - any: - description: |- - AnyConditions enable variable-based conditional rule execution. This is useful for - finer control of when an rule is applied. A condition can reference object data - using JMESPath notation. - Here, at least one of the conditions need to pass - items: - description: Condition defines variable-based - conditional criteria for rule execution. - properties: - key: - description: Key is the context entry - (using JMESPath) for conditional rule - evaluation. - x-kubernetes-preserve-unknown-fields: true - message: - description: Message is an optional - display message - type: string - operator: - description: |- - Operator is the conditional operation to perform. Valid operators are: - Equals, NotEquals, In, AnyIn, AllIn, NotIn, AnyNotIn, AllNotIn, GreaterThanOrEquals, - GreaterThan, LessThanOrEquals, LessThan, DurationGreaterThanOrEquals, DurationGreaterThan, - DurationLessThanOrEquals, DurationLessThan - enum: - - Equals - - NotEquals - - In - - AnyIn - - AllIn - - NotIn - - AnyNotIn - - AllNotIn - - GreaterThanOrEquals - - GreaterThan - - LessThanOrEquals - - LessThan - - DurationGreaterThanOrEquals - - DurationGreaterThan - - DurationLessThanOrEquals - - DurationLessThan - type: string - value: - description: |- - Value is the conditional value, or set of values. The values can be fixed set - or can be variables declared using JMESPath. - x-kubernetes-preserve-unknown-fields: true - type: object - type: array - type: object - x-kubernetes-preserve-unknown-fields: true - type: object - type: array - manifests: - description: Manifest specifies conditions for manifest - verification - properties: - annotationDomain: - description: AnnotationDomain is custom domain of - annotation for message and signature. Default - is "cosign.sigstore.dev". - type: string - attestors: - description: Attestors specified the required attestors - (i.e. authorities) - items: - properties: - count: - description: |- - Count specifies the required number of entries that must match. If the count is null, all entries must match - (a logical AND). If the count is 1, at least one entry must match (a logical OR). If the count contains a - value N, then N must be less than or equal to the size of entries, and at least N entries must match. - minimum: 1 - type: integer - entries: - description: |- - Entries contains the available attestors. An attestor can be a static key, - attributes for keyless verification, or a nested attestor declaration. - items: - properties: - annotations: - additionalProperties: - type: string - description: |- - Annotations are used for image verification. - Every specified key-value pair must exist and match in the verified payload. - The payload may contain other key-value pairs. - type: object - attestor: - description: Attestor is a nested set - of Attestor used to specify a more - complex set of match authorities. - x-kubernetes-preserve-unknown-fields: true - certificates: - description: Certificates specifies - one or more certificates. - properties: - cert: - description: Cert is an optional - PEM-encoded public certificate. - type: string - certChain: - description: CertChain is an optional - PEM encoded set of certificates - used to verify. - type: string - ctlog: - description: |- - CTLog (certificate timestamp log) provides a configuration for validation of Signed Certificate - Timestamps (SCTs). If the value is unset, the default behavior by Cosign is used. - properties: - ignoreSCT: - description: |- - IgnoreSCT defines whether to use the Signed Certificate Timestamp (SCT) log to check for a certificate - timestamp. Default is false. Set to true if this was opted out during signing. - type: boolean - pubkey: - description: PubKey, if set, - is used to validate SCTs against - a custom source. - type: string - tsaCertChain: - description: |- - TSACertChain, if set, is the PEM-encoded certificate chain file for the RFC3161 timestamp authority. Must - contain the root CA certificate. Optionally may contain intermediate CA certificates, and - may contain the leaf TSA certificate if not present in the timestamurce. - type: string - type: object - rekor: - description: |- - Rekor provides configuration for the Rekor transparency log service. If an empty object - is provided the public instance of Rekor (https://rekor.sigstore.dev) is used. - properties: - ignoreTlog: - description: IgnoreTlog skips - transparency log verification. - type: boolean - pubkey: - description: |- - RekorPubKey is an optional PEM-encoded public key to use for a custom Rekor. - If set, this will be used to validate transparency log signatures from a custom Rekor. - type: string - url: - description: URL is the address - of the transparency log. Defaults - to the public Rekor log instance - https://rekor.sigstore.dev. - type: string - type: object - type: object - keyless: - description: |- - Keyless is a set of attribute used to verify a Sigstore keyless attestor. - See https://github.com/sigstore/cosign/blob/main/KEYLESS.md. - properties: - additionalExtensions: - additionalProperties: - type: string - description: AdditionalExtensions - are certificate-extensions used - for keyless signing. - type: object - ctlog: - description: |- - CTLog (certificate timestamp log) provides a configuration for validation of Signed Certificate - Timestamps (SCTs). If the value is unset, the default behavior by Cosign is used. - properties: - ignoreSCT: - description: |- - IgnoreSCT defines whether to use the Signed Certificate Timestamp (SCT) log to check for a certificate - timestamp. Default is false. Set to true if this was opted out during signing. - type: boolean - pubkey: - description: PubKey, if set, - is used to validate SCTs against - a custom source. - type: string - tsaCertChain: - description: |- - TSACertChain, if set, is the PEM-encoded certificate chain file for the RFC3161 timestamp authority. Must - contain the root CA certificate. Optionally may contain intermediate CA certificates, and - may contain the leaf TSA certificate if not present in the timestamurce. - type: string - type: object - issuer: - description: Issuer is the certificate - issuer used for keyless signing. - type: string - issuerRegExp: - description: IssuerRegExp is the - regular expression to match certificate - issuer used for keyless signing. - type: string - rekor: - description: |- - Rekor provides configuration for the Rekor transparency log service. If an empty object - is provided the public instance of Rekor (https://rekor.sigstore.dev) is used. - properties: - ignoreTlog: - description: IgnoreTlog skips - transparency log verification. - type: boolean - pubkey: - description: |- - RekorPubKey is an optional PEM-encoded public key to use for a custom Rekor. - If set, this will be used to validate transparency log signatures from a custom Rekor. - type: string - url: - description: URL is the address - of the transparency log. Defaults - to the public Rekor log instance - https://rekor.sigstore.dev. - type: string - type: object - roots: - description: |- - Roots is an optional set of PEM encoded trusted root certificates. - If not provided, the system roots are used. - type: string - subject: - description: Subject is the verified - identity used for keyless signing, - for example the email address. - type: string - subjectRegExp: - description: SubjectRegExp is the - regular expression to match identity - used for keyless signing, for - example the email address. - type: string - type: object - keys: - description: Keys specifies one or more - public keys. - properties: - ctlog: - description: |- - CTLog (certificate timestamp log) provides a configuration for validation of Signed Certificate - Timestamps (SCTs). If the value is unset, the default behavior by Cosign is used. - properties: - ignoreSCT: - description: |- - IgnoreSCT defines whether to use the Signed Certificate Timestamp (SCT) log to check for a certificate - timestamp. Default is false. Set to true if this was opted out during signing. - type: boolean - pubkey: - description: PubKey, if set, - is used to validate SCTs against - a custom source. - type: string - tsaCertChain: - description: |- - TSACertChain, if set, is the PEM-encoded certificate chain file for the RFC3161 timestamp authority. Must - contain the root CA certificate. Optionally may contain intermediate CA certificates, and - may contain the leaf TSA certificate if not present in the timestamurce. - type: string - type: object - kms: - description: |- - KMS provides the URI to the public key stored in a Key Management System. See: - https://github.com/sigstore/cosign/blob/main/KMS.md - type: string - publicKeys: - description: |- - Keys is a set of X.509 public keys used to verify image signatures. The keys can be directly - specified or can be a variable reference to a key specified in a ConfigMap (see - https://kyverno.io/docs/writing-policies/variables/), or reference a standard Kubernetes Secret - elsewhere in the cluster by specifying it in the format "k8s:///". - The named Secret must specify a key `cosign.pub` containing the public key used for - verification, (see https://github.com/sigstore/cosign/blob/main/KMS.md#kubernetes-secret). - When multiple keys are specified each key is processed as a separate staticKey entry - (.attestors[*].entries.keys) within the set of attestors and the count is applied across the keys. - type: string - rekor: - description: |- - Rekor provides configuration for the Rekor transparency log service. If an empty object - is provided the public instance of Rekor (https://rekor.sigstore.dev) is used. - properties: - ignoreTlog: - description: IgnoreTlog skips - transparency log verification. - type: boolean - pubkey: - description: |- - RekorPubKey is an optional PEM-encoded public key to use for a custom Rekor. - If set, this will be used to validate transparency log signatures from a custom Rekor. - type: string - url: - description: URL is the address - of the transparency log. Defaults - to the public Rekor log instance - https://rekor.sigstore.dev. - type: string - type: object - secret: - description: Reference to a Secret - resource that contains a public - key - properties: - name: - description: Name of the secret. - The provided secret must contain - a key named cosign.pub. - type: string - namespace: - description: Namespace name - where the Secret exists. - type: string - required: - - name - - namespace - type: object - signatureAlgorithm: - default: sha256 - description: Deprecated. Use attestor.signatureAlgorithm - instead. - type: string - type: object - repository: - description: |- - Repository is an optional alternate OCI repository to use for signatures and attestations that match this rule. - If specified Repository will override other OCI image repository locations for this Attestor. - type: string - signatureAlgorithm: - default: sha256 - description: Specify signature algorithm - for public keys. Supported values - are sha224, sha256, sha384 and sha512. - type: string - type: object - type: array - type: object - type: array - dryRun: - description: DryRun configuration - properties: - enable: - type: boolean - namespace: - type: string - type: object - ignoreFields: - description: Fields which will be ignored while - comparing manifests. - items: - properties: - fields: - items: - type: string - type: array - objects: - items: - properties: - group: - type: string - kind: - type: string - name: - type: string - namespace: - type: string - version: - type: string - type: object - type: array - type: object - type: array - repository: - description: |- - Repository is an optional alternate OCI repository to use for resource bundle reference. - The repository can be overridden per Attestor or Attestation. - type: string - type: object - message: - description: Message specifies a custom message to be - displayed on failure. - type: string - pattern: - description: Pattern specifies an overlay-style pattern - used to check resources. - x-kubernetes-preserve-unknown-fields: true - podSecurity: - description: |- - PodSecurity applies exemptions for Kubernetes Pod Security admission - by specifying exclusions for Pod Security Standards controls. - properties: - exclude: - description: Exclude specifies the Pod Security - Standard controls to be excluded. - items: - description: PodSecurityStandard specifies the - Pod Security Standard controls to be excluded. - properties: - controlName: - description: |- - ControlName specifies the name of the Pod Security Standard control. - See: https://kubernetes.io/docs/concepts/security/pod-security-standards/ - enum: - - HostProcess - - Host Namespaces - - Privileged Containers - - Capabilities - - HostPath Volumes - - Host Ports - - AppArmor - - SELinux - - /proc Mount Type - - Seccomp - - Sysctls - - Volume Types - - Privilege Escalation - - Running as Non-root - - Running as Non-root user - type: string - images: - description: |- - Images selects matching containers and applies the container level PSS. - Each image is the image name consisting of the registry address, repository, image, and tag. - Empty list matches no containers, PSS checks are applied at the pod level only. - Wildcards ('*' and '?') are allowed. See: https://kubernetes.io/docs/concepts/containers/images. - items: - type: string - type: array - restrictedField: - description: |- - RestrictedField selects the field for the given Pod Security Standard control. - When not set, all restricted fields for the control are selected. - type: string - values: - description: Values defines the allowed values - that can be excluded. - items: - type: string - type: array - required: - - controlName - type: object - type: array - level: - description: |- - Level defines the Pod Security Standard level to be applied to workloads. - Allowed values are privileged, baseline, and restricted. - enum: - - privileged - - baseline - - restricted - type: string - version: - description: |- - Version defines the Pod Security Standard versions that Kubernetes supports. - Allowed values are v1.19, v1.20, v1.21, v1.22, v1.23, v1.24, v1.25, v1.26, v1.27, v1.28, v1.29, latest. Defaults to latest. - enum: - - v1.19 - - v1.20 - - v1.21 - - v1.22 - - v1.23 - - v1.24 - - v1.25 - - v1.26 - - v1.27 - - v1.28 - - v1.29 - - latest - type: string - type: object - type: object - verifyImages: - description: VerifyImages is used to verify image signatures - and mutate them to add a digest - items: - description: |- - ImageVerification validates that images that match the specified pattern - are signed with the supplied public key. Once the image is verified it is - mutated to include the SHA digest retrieved during the registration. - properties: - additionalExtensions: - additionalProperties: - type: string - description: Deprecated. - type: object - annotations: - additionalProperties: - type: string - description: Deprecated. Use annotations per Attestor - instead. - type: object - attestations: - description: |- - Attestations are optional checks for signed in-toto Statements used to verify the image. - See https://github.com/in-toto/attestation. Kyverno fetches signed attestations from the - OCI registry and decodes them into a list of Statement declarations. - items: - description: |- - Attestation are checks for signed in-toto Statements that are used to verify the image. - See https://github.com/in-toto/attestation. Kyverno fetches signed attestations from the - OCI registry and decodes them into a list of Statements. - properties: - attestors: - description: Attestors specify the required - attestors (i.e. authorities). - items: - properties: - count: - description: |- - Count specifies the required number of entries that must match. If the count is null, all entries must match - (a logical AND). If the count is 1, at least one entry must match (a logical OR). If the count contains a - value N, then N must be less than or equal to the size of entries, and at least N entries must match. - minimum: 1 - type: integer - entries: - description: |- - Entries contains the available attestors. An attestor can be a static key, - attributes for keyless verification, or a nested attestor declaration. - items: - properties: - annotations: - additionalProperties: - type: string - description: |- - Annotations are used for image verification. - Every specified key-value pair must exist and match in the verified payload. - The payload may contain other key-value pairs. - type: object - attestor: - description: Attestor is a nested - set of Attestor used to specify - a more complex set of match authorities. - x-kubernetes-preserve-unknown-fields: true - certificates: - description: Certificates specifies - one or more certificates. - properties: - cert: - description: Cert is an optional - PEM-encoded public certificate. - type: string - certChain: - description: CertChain is an - optional PEM encoded set of - certificates used to verify. - type: string - ctlog: - description: |- - CTLog (certificate timestamp log) provides a configuration for validation of Signed Certificate - Timestamps (SCTs). If the value is unset, the default behavior by Cosign is used. - properties: - ignoreSCT: - description: |- - IgnoreSCT defines whether to use the Signed Certificate Timestamp (SCT) log to check for a certificate - timestamp. Default is false. Set to true if this was opted out during signing. - type: boolean - pubkey: - description: PubKey, if - set, is used to validate - SCTs against a custom - source. - type: string - tsaCertChain: - description: |- - TSACertChain, if set, is the PEM-encoded certificate chain file for the RFC3161 timestamp authority. Must - contain the root CA certificate. Optionally may contain intermediate CA certificates, and - may contain the leaf TSA certificate if not present in the timestamurce. - type: string - type: object - rekor: - description: |- - Rekor provides configuration for the Rekor transparency log service. If an empty object - is provided the public instance of Rekor (https://rekor.sigstore.dev) is used. - properties: - ignoreTlog: - description: IgnoreTlog - skips transparency log - verification. - type: boolean - pubkey: - description: |- - RekorPubKey is an optional PEM-encoded public key to use for a custom Rekor. - If set, this will be used to validate transparency log signatures from a custom Rekor. - type: string - url: - description: URL is the - address of the transparency - log. Defaults to the public - Rekor log instance https://rekor.sigstore.dev. - type: string - type: object - type: object - keyless: - description: |- - Keyless is a set of attribute used to verify a Sigstore keyless attestor. - See https://github.com/sigstore/cosign/blob/main/KEYLESS.md. - properties: - additionalExtensions: - additionalProperties: - type: string - description: AdditionalExtensions - are certificate-extensions - used for keyless signing. - type: object - ctlog: - description: |- - CTLog (certificate timestamp log) provides a configuration for validation of Signed Certificate - Timestamps (SCTs). If the value is unset, the default behavior by Cosign is used. - properties: - ignoreSCT: - description: |- - IgnoreSCT defines whether to use the Signed Certificate Timestamp (SCT) log to check for a certificate - timestamp. Default is false. Set to true if this was opted out during signing. - type: boolean - pubkey: - description: PubKey, if - set, is used to validate - SCTs against a custom - source. - type: string - tsaCertChain: - description: |- - TSACertChain, if set, is the PEM-encoded certificate chain file for the RFC3161 timestamp authority. Must - contain the root CA certificate. Optionally may contain intermediate CA certificates, and - may contain the leaf TSA certificate if not present in the timestamurce. - type: string - type: object - issuer: - description: Issuer is the certificate - issuer used for keyless signing. - type: string - issuerRegExp: - description: IssuerRegExp is - the regular expression to - match certificate issuer used - for keyless signing. - type: string - rekor: - description: |- - Rekor provides configuration for the Rekor transparency log service. If an empty object - is provided the public instance of Rekor (https://rekor.sigstore.dev) is used. - properties: - ignoreTlog: - description: IgnoreTlog - skips transparency log - verification. - type: boolean - pubkey: - description: |- - RekorPubKey is an optional PEM-encoded public key to use for a custom Rekor. - If set, this will be used to validate transparency log signatures from a custom Rekor. - type: string - url: - description: URL is the - address of the transparency - log. Defaults to the public - Rekor log instance https://rekor.sigstore.dev. - type: string - type: object - roots: - description: |- - Roots is an optional set of PEM encoded trusted root certificates. - If not provided, the system roots are used. - type: string - subject: - description: Subject is the - verified identity used for - keyless signing, for example - the email address. - type: string - subjectRegExp: - description: SubjectRegExp is - the regular expression to - match identity used for keyless - signing, for example the email - address. - type: string - type: object - keys: - description: Keys specifies one - or more public keys. - properties: - ctlog: - description: |- - CTLog (certificate timestamp log) provides a configuration for validation of Signed Certificate - Timestamps (SCTs). If the value is unset, the default behavior by Cosign is used. - properties: - ignoreSCT: - description: |- - IgnoreSCT defines whether to use the Signed Certificate Timestamp (SCT) log to check for a certificate - timestamp. Default is false. Set to true if this was opted out during signing. - type: boolean - pubkey: - description: PubKey, if - set, is used to validate - SCTs against a custom - source. - type: string - tsaCertChain: - description: |- - TSACertChain, if set, is the PEM-encoded certificate chain file for the RFC3161 timestamp authority. Must - contain the root CA certificate. Optionally may contain intermediate CA certificates, and - may contain the leaf TSA certificate if not present in the timestamurce. - type: string - type: object - kms: - description: |- - KMS provides the URI to the public key stored in a Key Management System. See: - https://github.com/sigstore/cosign/blob/main/KMS.md - type: string - publicKeys: - description: |- - Keys is a set of X.509 public keys used to verify image signatures. The keys can be directly - specified or can be a variable reference to a key specified in a ConfigMap (see - https://kyverno.io/docs/writing-policies/variables/), or reference a standard Kubernetes Secret - elsewhere in the cluster by specifying it in the format "k8s:///". - The named Secret must specify a key `cosign.pub` containing the public key used for - verification, (see https://github.com/sigstore/cosign/blob/main/KMS.md#kubernetes-secret). - When multiple keys are specified each key is processed as a separate staticKey entry - (.attestors[*].entries.keys) within the set of attestors and the count is applied across the keys. - type: string - rekor: - description: |- - Rekor provides configuration for the Rekor transparency log service. If an empty object - is provided the public instance of Rekor (https://rekor.sigstore.dev) is used. - properties: - ignoreTlog: - description: IgnoreTlog - skips transparency log - verification. - type: boolean - pubkey: - description: |- - RekorPubKey is an optional PEM-encoded public key to use for a custom Rekor. - If set, this will be used to validate transparency log signatures from a custom Rekor. - type: string - url: - description: URL is the - address of the transparency - log. Defaults to the public - Rekor log instance https://rekor.sigstore.dev. - type: string - type: object - secret: - description: Reference to a - Secret resource that contains - a public key - properties: - name: - description: Name of the - secret. The provided secret - must contain a key named - cosign.pub. - type: string - namespace: - description: Namespace name - where the Secret exists. - type: string - required: - - name - - namespace - type: object - signatureAlgorithm: - default: sha256 - description: Deprecated. Use - attestor.signatureAlgorithm - instead. - type: string - type: object - repository: - description: |- - Repository is an optional alternate OCI repository to use for signatures and attestations that match this rule. - If specified Repository will override other OCI image repository locations for this Attestor. - type: string - signatureAlgorithm: - default: sha256 - description: Specify signature algorithm - for public keys. Supported values - are sha224, sha256, sha384 and - sha512. - type: string - type: object - type: array - type: object - type: array - conditions: - description: |- - Conditions are used to verify attributes within a Predicate. If no Conditions are specified - the attestation check is satisfied as long there are predicates that match the predicate type. - items: - description: |- - AnyAllConditions consists of conditions wrapped denoting a logical criteria to be fulfilled. - AnyConditions get fulfilled when at least one of its sub-conditions passes. - AllConditions get fulfilled only when all of its sub-conditions pass. - properties: - all: - description: |- - AllConditions enable variable-based conditional rule execution. This is useful for - finer control of when an rule is applied. A condition can reference object data - using JMESPath notation. - Here, all of the conditions need to pass - items: - description: Condition defines variable-based - conditional criteria for rule execution. - properties: - key: - description: Key is the context - entry (using JMESPath) for conditional - rule evaluation. - x-kubernetes-preserve-unknown-fields: true - message: - description: Message is an optional - display message - type: string - operator: - description: |- - Operator is the conditional operation to perform. Valid operators are: - Equals, NotEquals, In, AnyIn, AllIn, NotIn, AnyNotIn, AllNotIn, GreaterThanOrEquals, - GreaterThan, LessThanOrEquals, LessThan, DurationGreaterThanOrEquals, DurationGreaterThan, - DurationLessThanOrEquals, DurationLessThan - enum: - - Equals - - NotEquals - - In - - AnyIn - - AllIn - - NotIn - - AnyNotIn - - AllNotIn - - GreaterThanOrEquals - - GreaterThan - - LessThanOrEquals - - LessThan - - DurationGreaterThanOrEquals - - DurationGreaterThan - - DurationLessThanOrEquals - - DurationLessThan - type: string - value: - description: |- - Value is the conditional value, or set of values. The values can be fixed set - or can be variables declared using JMESPath. - x-kubernetes-preserve-unknown-fields: true - type: object - type: array - any: - description: |- - AnyConditions enable variable-based conditional rule execution. This is useful for - finer control of when an rule is applied. A condition can reference object data - using JMESPath notation. - Here, at least one of the conditions need to pass - items: - description: Condition defines variable-based - conditional criteria for rule execution. - properties: - key: - description: Key is the context - entry (using JMESPath) for conditional - rule evaluation. - x-kubernetes-preserve-unknown-fields: true - message: - description: Message is an optional - display message - type: string - operator: - description: |- - Operator is the conditional operation to perform. Valid operators are: - Equals, NotEquals, In, AnyIn, AllIn, NotIn, AnyNotIn, AllNotIn, GreaterThanOrEquals, - GreaterThan, LessThanOrEquals, LessThan, DurationGreaterThanOrEquals, DurationGreaterThan, - DurationLessThanOrEquals, DurationLessThan - enum: - - Equals - - NotEquals - - In - - AnyIn - - AllIn - - NotIn - - AnyNotIn - - AllNotIn - - GreaterThanOrEquals - - GreaterThan - - LessThanOrEquals - - LessThan - - DurationGreaterThanOrEquals - - DurationGreaterThan - - DurationLessThanOrEquals - - DurationLessThan - type: string - value: - description: |- - Value is the conditional value, or set of values. The values can be fixed set - or can be variables declared using JMESPath. - x-kubernetes-preserve-unknown-fields: true - type: object - type: array - type: object - type: array - name: - description: Name is the variable name. - type: string - predicateType: - description: Deprecated in favour of 'Type', - to be removed soon - type: string - type: - description: Type defines the type of attestation - contained within the Statement. - type: string - type: object - type: array - attestors: - description: Attestors specified the required attestors - (i.e. authorities) - items: - properties: - count: - description: |- - Count specifies the required number of entries that must match. If the count is null, all entries must match - (a logical AND). If the count is 1, at least one entry must match (a logical OR). If the count contains a - value N, then N must be less than or equal to the size of entries, and at least N entries must match. - minimum: 1 - type: integer - entries: - description: |- - Entries contains the available attestors. An attestor can be a static key, - attributes for keyless verification, or a nested attestor declaration. - items: - properties: - annotations: - additionalProperties: - type: string - description: |- - Annotations are used for image verification. - Every specified key-value pair must exist and match in the verified payload. - The payload may contain other key-value pairs. - type: object - attestor: - description: Attestor is a nested set - of Attestor used to specify a more complex - set of match authorities. - x-kubernetes-preserve-unknown-fields: true - certificates: - description: Certificates specifies one - or more certificates. - properties: - cert: - description: Cert is an optional PEM-encoded - public certificate. - type: string - certChain: - description: CertChain is an optional - PEM encoded set of certificates - used to verify. - type: string - ctlog: - description: |- - CTLog (certificate timestamp log) provides a configuration for validation of Signed Certificate - Timestamps (SCTs). If the value is unset, the default behavior by Cosign is used. - properties: - ignoreSCT: - description: |- - IgnoreSCT defines whether to use the Signed Certificate Timestamp (SCT) log to check for a certificate - timestamp. Default is false. Set to true if this was opted out during signing. - type: boolean - pubkey: - description: PubKey, if set, is - used to validate SCTs against - a custom source. - type: string - tsaCertChain: - description: |- - TSACertChain, if set, is the PEM-encoded certificate chain file for the RFC3161 timestamp authority. Must - contain the root CA certificate. Optionally may contain intermediate CA certificates, and - may contain the leaf TSA certificate if not present in the timestamurce. - type: string - type: object - rekor: - description: |- - Rekor provides configuration for the Rekor transparency log service. If an empty object - is provided the public instance of Rekor (https://rekor.sigstore.dev) is used. - properties: - ignoreTlog: - description: IgnoreTlog skips - transparency log verification. - type: boolean - pubkey: - description: |- - RekorPubKey is an optional PEM-encoded public key to use for a custom Rekor. - If set, this will be used to validate transparency log signatures from a custom Rekor. - type: string - url: - description: URL is the address - of the transparency log. Defaults - to the public Rekor log instance - https://rekor.sigstore.dev. - type: string - type: object - type: object - keyless: - description: |- - Keyless is a set of attribute used to verify a Sigstore keyless attestor. - See https://github.com/sigstore/cosign/blob/main/KEYLESS.md. - properties: - additionalExtensions: - additionalProperties: - type: string - description: AdditionalExtensions - are certificate-extensions used - for keyless signing. - type: object - ctlog: - description: |- - CTLog (certificate timestamp log) provides a configuration for validation of Signed Certificate - Timestamps (SCTs). If the value is unset, the default behavior by Cosign is used. - properties: - ignoreSCT: - description: |- - IgnoreSCT defines whether to use the Signed Certificate Timestamp (SCT) log to check for a certificate - timestamp. Default is false. Set to true if this was opted out during signing. - type: boolean - pubkey: - description: PubKey, if set, is - used to validate SCTs against - a custom source. - type: string - tsaCertChain: - description: |- - TSACertChain, if set, is the PEM-encoded certificate chain file for the RFC3161 timestamp authority. Must - contain the root CA certificate. Optionally may contain intermediate CA certificates, and - may contain the leaf TSA certificate if not present in the timestamurce. - type: string - type: object - issuer: - description: Issuer is the certificate - issuer used for keyless signing. - type: string - issuerRegExp: - description: IssuerRegExp is the regular - expression to match certificate - issuer used for keyless signing. - type: string - rekor: - description: |- - Rekor provides configuration for the Rekor transparency log service. If an empty object - is provided the public instance of Rekor (https://rekor.sigstore.dev) is used. - properties: - ignoreTlog: - description: IgnoreTlog skips - transparency log verification. - type: boolean - pubkey: - description: |- - RekorPubKey is an optional PEM-encoded public key to use for a custom Rekor. - If set, this will be used to validate transparency log signatures from a custom Rekor. - type: string - url: - description: URL is the address - of the transparency log. Defaults - to the public Rekor log instance - https://rekor.sigstore.dev. - type: string - type: object - roots: - description: |- - Roots is an optional set of PEM encoded trusted root certificates. - If not provided, the system roots are used. - type: string - subject: - description: Subject is the verified - identity used for keyless signing, - for example the email address. - type: string - subjectRegExp: - description: SubjectRegExp is the - regular expression to match identity - used for keyless signing, for example - the email address. - type: string - type: object - keys: - description: Keys specifies one or more - public keys. - properties: - ctlog: - description: |- - CTLog (certificate timestamp log) provides a configuration for validation of Signed Certificate - Timestamps (SCTs). If the value is unset, the default behavior by Cosign is used. - properties: - ignoreSCT: - description: |- - IgnoreSCT defines whether to use the Signed Certificate Timestamp (SCT) log to check for a certificate - timestamp. Default is false. Set to true if this was opted out during signing. - type: boolean - pubkey: - description: PubKey, if set, is - used to validate SCTs against - a custom source. - type: string - tsaCertChain: - description: |- - TSACertChain, if set, is the PEM-encoded certificate chain file for the RFC3161 timestamp authority. Must - contain the root CA certificate. Optionally may contain intermediate CA certificates, and - may contain the leaf TSA certificate if not present in the timestamurce. - type: string - type: object - kms: - description: |- - KMS provides the URI to the public key stored in a Key Management System. See: - https://github.com/sigstore/cosign/blob/main/KMS.md - type: string - publicKeys: - description: |- - Keys is a set of X.509 public keys used to verify image signatures. The keys can be directly - specified or can be a variable reference to a key specified in a ConfigMap (see - https://kyverno.io/docs/writing-policies/variables/), or reference a standard Kubernetes Secret - elsewhere in the cluster by specifying it in the format "k8s:///". - The named Secret must specify a key `cosign.pub` containing the public key used for - verification, (see https://github.com/sigstore/cosign/blob/main/KMS.md#kubernetes-secret). - When multiple keys are specified each key is processed as a separate staticKey entry - (.attestors[*].entries.keys) within the set of attestors and the count is applied across the keys. - type: string - rekor: - description: |- - Rekor provides configuration for the Rekor transparency log service. If an empty object - is provided the public instance of Rekor (https://rekor.sigstore.dev) is used. - properties: - ignoreTlog: - description: IgnoreTlog skips - transparency log verification. - type: boolean - pubkey: - description: |- - RekorPubKey is an optional PEM-encoded public key to use for a custom Rekor. - If set, this will be used to validate transparency log signatures from a custom Rekor. - type: string - url: - description: URL is the address - of the transparency log. Defaults - to the public Rekor log instance - https://rekor.sigstore.dev. - type: string - type: object - secret: - description: Reference to a Secret - resource that contains a public - key - properties: - name: - description: Name of the secret. - The provided secret must contain - a key named cosign.pub. - type: string - namespace: - description: Namespace name where - the Secret exists. - type: string - required: - - name - - namespace - type: object - signatureAlgorithm: - default: sha256 - description: Deprecated. Use attestor.signatureAlgorithm - instead. - type: string - type: object - repository: - description: |- - Repository is an optional alternate OCI repository to use for signatures and attestations that match this rule. - If specified Repository will override other OCI image repository locations for this Attestor. - type: string - signatureAlgorithm: - default: sha256 - description: Specify signature algorithm - for public keys. Supported values are - sha224, sha256, sha384 and sha512. - type: string - type: object - type: array - type: object - type: array - cosignOCI11: - description: |- - CosignOCI11 enables the experimental OCI 1.1 behaviour in cosign image verification. - Defaults to false. - type: boolean - failureAction: - description: Allowed values are Audit or Enforce. - enum: - - Audit - - Enforce - type: string - image: - description: Deprecated. Use ImageReferences instead. - type: string - imageReferences: - description: |- - ImageReferences is a list of matching image reference patterns. At least one pattern in the - list must match the image for the rule to apply. Each image reference consists of a registry - address (defaults to docker.io), repository, image, and tag (defaults to latest). - Wildcards ('*' and '?') are allowed. See: https://kubernetes.io/docs/concepts/containers/images. - items: - type: string - type: array - imageRegistryCredentials: - description: ImageRegistryCredentials provides credentials - that will be used for authentication with registry. - properties: - allowInsecureRegistry: - description: AllowInsecureRegistry allows insecure - access to a registry. - type: boolean - providers: - description: |- - Providers specifies a list of OCI Registry names, whose authentication providers are provided. - It can be of one of these values: default,google,azure,amazon,github. - items: - description: ImageRegistryCredentialsProvidersType - provides the list of credential providers - required. - enum: - - default - - amazon - - azure - - google - - github - type: string - type: array - secrets: - description: |- - Secrets specifies a list of secrets that are provided for credentials. - Secrets must live in the Kyverno namespace. - items: - type: string - type: array - type: object - issuer: - description: Deprecated. Use KeylessAttestor instead. - type: string - key: - description: Deprecated. Use StaticKeyAttestor instead. - type: string - mutateDigest: - default: true - description: |- - MutateDigest enables replacement of image tags with digests. - Defaults to true. - type: boolean - repository: - description: |- - Repository is an optional alternate OCI repository to use for image signatures and attestations that match this rule. - If specified Repository will override the default OCI image repository configured for the installation. - The repository can also be overridden per Attestor or Attestation. - type: string - required: - default: true - description: Required validates that images are verified - i.e. have matched passed a signature or attestation - check. - type: boolean - roots: - description: Deprecated. Use KeylessAttestor instead. - type: string - skipImageReferences: - description: |- - SkipImageReferences is a list of matching image reference patterns that should be skipped. - At least one pattern in the list must match the image for the rule to be skipped. Each image reference - consists of a registry address (defaults to docker.io), repository, image, and tag (defaults to latest). - Wildcards ('*' and '?') are allowed. See: https://kubernetes.io/docs/concepts/containers/images. - items: - type: string - type: array - subject: - description: Deprecated. Use KeylessAttestor instead. - type: string - type: - description: |- - Type specifies the method of signature validation. The allowed options - are Cosign, Sigstore Bundle and Notary. By default Cosign is used if a type is not specified. - enum: - - Cosign - - SigstoreBundle - - Notary - type: string - useCache: - default: true - description: UseCache enables caching of image verify - responses for this rule. - type: boolean - validate: - description: |- - Validation checks conditions across multiple image - verification attestations or context entries - properties: - deny: - description: Deny defines conditions used to pass - or fail a validation rule. - properties: - conditions: - description: |- - Multiple conditions can be declared under an `any` or `all` statement. A direct list - of conditions (without `any` or `all` statements) is also supported for backwards compatibility - but will be deprecated in the next major release. - See: https://kyverno.io/docs/writing-policies/validate/#deny-rules - x-kubernetes-preserve-unknown-fields: true - type: object - message: - description: Message specifies a custom message - to be displayed on failure. - type: string - type: object - verifyDigest: - default: true - description: VerifyDigest validates that images have - a digest. - type: boolean - type: object - type: array - required: - - match - - name - type: object - type: array - type: object - conditions: - items: - description: Condition contains details for one aspect of the current - state of this API Resource. - properties: - lastTransitionTime: - description: |- - lastTransitionTime is the last time the condition transitioned from one status to another. - This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable. - format: date-time - type: string - message: - description: |- - message is a human readable message indicating details about the transition. - This may be an empty string. - maxLength: 32768 - type: string - observedGeneration: - description: |- - observedGeneration represents the .metadata.generation that the condition was set based upon. - For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date - with respect to the current state of the instance. - format: int64 - minimum: 0 - type: integer - reason: - description: |- - reason contains a programmatic identifier indicating the reason for the condition's last transition. - Producers of specific condition types may define expected values and meanings for this field, - and whether the values are considered a guaranteed API. - The value should be a CamelCase string. - This field may not be empty. - maxLength: 1024 - minLength: 1 - pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ - type: string - status: - description: status of the condition, one of True, False, Unknown. - enum: - - "True" - - "False" - - Unknown - type: string - type: - description: type of condition in CamelCase or in foo.example.com/CamelCase. - maxLength: 316 - pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ - type: string - required: - - lastTransitionTime - - message - - reason - - status - - type - type: object - type: array - ready: - description: Deprecated in favor of Conditions - type: boolean - rulecount: - description: |- - RuleCountStatus contains four variables which describes counts for - validate, generate, mutate and verify images rules - properties: - generate: - description: Count for generate rules in policy - type: integer - mutate: - description: Count for mutate rules in policy - type: integer - validate: - description: Count for validate rules in policy - type: integer - verifyimages: - description: Count for verify image rules in policy - type: integer - required: - - generate - - mutate - - validate - - verifyimages - type: object - validatingadmissionpolicy: - description: ValidatingAdmissionPolicy contains status information - properties: - generated: - description: Generated indicates whether a validating admission - policy is generated from the policy or not - type: boolean - message: - description: |- - Message is a human readable message indicating details about the generation of validating admission policy - It is an empty string when validating admission policy is successfully generated. - type: string - required: - - generated - - message - type: object - type: object - required: - - spec - type: object - served: true - storage: true - subresources: - status: {} - - additionalPrinterColumns: - - jsonPath: .spec.admission - name: ADMISSION - type: boolean - - jsonPath: .spec.background - name: BACKGROUND - type: boolean - - jsonPath: .status.conditions[?(@.type == "Ready")].status - name: READY - type: string - - jsonPath: .metadata.creationTimestamp - name: AGE - type: date - - jsonPath: .spec.failurePolicy - name: FAILURE POLICY - priority: 1 - type: string - - jsonPath: .status.rulecount.validate - name: VALIDATE - priority: 1 - type: integer - - jsonPath: .status.rulecount.mutate - name: MUTATE - priority: 1 - type: integer - - jsonPath: .status.rulecount.generate - name: GENERATE - priority: 1 - type: integer - - jsonPath: .status.rulecount.verifyimages - name: VERIFY IMAGES - priority: 1 - type: integer - - jsonPath: .status.conditions[?(@.type == "Ready")].message - name: MESSAGE - type: string - name: v2beta1 - schema: - openAPIV3Schema: - description: |- - Policy declares validation, mutation, and generation behaviors for matching resources. - See: https://kyverno.io/docs/writing-policies/ for more information. - properties: - apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - type: string - kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - metadata: - type: object - spec: - description: Spec defines policy behaviors and contains one or more rules. - properties: - admission: - default: true - description: |- - Admission controls if rules are applied during admission. - Optional. Default value is "true". - type: boolean - applyRules: - description: |- - ApplyRules controls how rules in a policy are applied. Rule are processed in - the order of declaration. When set to `One` processing stops after a rule has - been applied i.e. the rule matches and results in a pass, fail, or error. When - set to `All` all rules in the policy are processed. The default is `All`. - enum: - - All - - One - type: string - background: - default: true - description: |- - Background controls if rules are applied to existing resources during a background scan. - Optional. Default value is "true". The value must be set to "false" if the policy rule - uses variables that are only available in the admission review request (e.g. user name). - type: boolean - emitWarning: - default: false - description: |- - EmitWarning enables API response warnings for mutate policy rules or validate policy rules with validationFailureAction set to Audit. - Enabling this option will extend admission request processing times. The default value is "false". - type: boolean - failurePolicy: - description: Deprecated, use failurePolicy under the webhookConfiguration - instead. - enum: - - Ignore - - Fail - type: string - generateExisting: - description: Deprecated, use generateExisting under the generate rule - instead - type: boolean - generateExistingOnPolicyUpdate: - description: Deprecated, use generateExisting instead - type: boolean - mutateExistingOnPolicyUpdate: - description: Deprecated, use mutateExistingOnPolicyUpdate under the - mutate rule instead - type: boolean - rules: - description: |- - Rules is a list of Rule instances. A Policy contains multiple rules and - each rule can validate, mutate, or generate resources. - items: - description: |- - Rule defines a validation, mutation, or generation control for matching resources. - Each rules contains a match declaration to select resources, and an optional exclude - declaration to specify which resources to exclude. - properties: - celPreconditions: - description: |- - CELPreconditions are used to determine if a policy rule should be applied by evaluating a - set of CEL conditions. It can only be used with the validate.cel subrule - items: - description: MatchCondition represents a condition which must - by fulfilled for a request to be sent to a webhook. - properties: - expression: - description: |- - Expression represents the expression which will be evaluated by CEL. Must evaluate to bool. - CEL expressions have access to the contents of the AdmissionRequest and Authorizer, organized into CEL variables: - - 'object' - The object from the incoming request. The value is null for DELETE requests. - 'oldObject' - The existing object. The value is null for CREATE requests. - 'request' - Attributes of the admission request(/pkg/apis/admission/types.go#AdmissionRequest). - 'authorizer' - A CEL Authorizer. May be used to perform authorization checks for the principal (user or service account) of the request. - See https://pkg.go.dev/k8s.io/apiserver/pkg/cel/library#Authz - 'authorizer.requestResource' - A CEL ResourceCheck constructed from the 'authorizer' and configured with the - request resource. - Documentation on CEL: https://kubernetes.io/docs/reference/using-api/cel/ - - Required. - type: string - name: - description: |- - Name is an identifier for this match condition, used for strategic merging of MatchConditions, - as well as providing an identifier for logging purposes. A good name should be descriptive of - the associated expression. - Name must be a qualified name consisting of alphanumeric characters, '-', '_' or '.', and - must start and end with an alphanumeric character (e.g. 'MyName', or 'my.name', or - '123-abc', regex used for validation is '([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9]') with an - optional DNS subdomain prefix and '/' (e.g. 'example.com/MyName') - - Required. - type: string - required: - - expression - - name - type: object - type: array - context: - description: Context defines variables and data sources that - can be used during rule execution. - items: - description: |- - ContextEntry adds variables and data sources to a rule Context. Either a - ConfigMap reference or a APILookup must be provided. - oneOf: - - required: - - configMap - - required: - - apiCall - - required: - - imageRegistry - - required: - - variable - - required: - - globalReference - properties: - apiCall: - description: |- - APICall is an HTTP request to the Kubernetes API server, or other JSON web service. - The data returned is stored in the context with the name for the context entry. - properties: - data: - description: |- - The data object specifies the POST data sent to the server. - Only applicable when the method field is set to POST. - items: - description: RequestData contains the HTTP POST - data - properties: - key: - description: Key is a unique identifier for - the data value - type: string - value: - description: Value is the data value - x-kubernetes-preserve-unknown-fields: true - required: - - key - - value - type: object - type: array - default: - description: |- - Default is an optional arbitrary JSON object that the context - value is set to, if the apiCall returns error. - x-kubernetes-preserve-unknown-fields: true - jmesPath: - description: |- - JMESPath is an optional JSON Match Expression that can be used to - transform the JSON response returned from the server. For example - a JMESPath of "items | length(@)" applied to the API server response - for the URLPath "/apis/apps/v1/deployments" will return the total count - of deployments across all namespaces. - type: string - method: - default: GET - description: Method is the HTTP request type (GET - or POST). Defaults to GET. - enum: - - GET - - POST - type: string - service: - description: |- - Service is an API call to a JSON web service. - This is used for non-Kubernetes API server calls. - It's mutually exclusive with the URLPath field. - properties: - caBundle: - description: |- - CABundle is a PEM encoded CA bundle which will be used to validate - the server certificate. - type: string - headers: - description: Headers is a list of optional HTTP - headers to be included in the request. - items: - properties: - key: - description: Key is the header key - type: string - value: - description: Value is the header value - type: string - required: - - key - - value - type: object - type: array - url: - description: |- - URL is the JSON web service URL. A typical form is - `https://{service}.{namespace}:{port}/{path}`. - type: string - required: - - url - type: object - urlPath: - description: |- - URLPath is the URL path to be used in the HTTP GET or POST request to the - Kubernetes API server (e.g. "/api/v1/namespaces" or "/apis/apps/v1/deployments"). - The format required is the same format used by the `kubectl get --raw` command. - See https://kyverno.io/docs/writing-policies/external-data-sources/#variables-from-kubernetes-api-server-calls - for details. - It's mutually exclusive with the Service field. - type: string - type: object - configMap: - description: ConfigMap is the ConfigMap reference. - properties: - name: - description: Name is the ConfigMap name. - type: string - namespace: - description: Namespace is the ConfigMap namespace. - type: string - required: - - name - type: object - globalReference: - description: GlobalContextEntryReference is a reference - to a cached global context entry. - properties: - jmesPath: - description: |- - JMESPath is an optional JSON Match Expression that can be used to - transform the JSON response returned from the server. For example - a JMESPath of "items | length(@)" applied to the API server response - for the URLPath "/apis/apps/v1/deployments" will return the total count - of deployments across all namespaces. - type: string - name: - description: Name of the global context entry - type: string - required: - - name - type: object - imageRegistry: - description: |- - ImageRegistry defines requests to an OCI/Docker V2 registry to fetch image - details. - properties: - imageRegistryCredentials: - description: ImageRegistryCredentials provides credentials - that will be used for authentication with registry - properties: - allowInsecureRegistry: - description: AllowInsecureRegistry allows insecure - access to a registry. - type: boolean - providers: - description: |- - Providers specifies a list of OCI Registry names, whose authentication providers are provided. - It can be of one of these values: default,google,azure,amazon,github. - items: - description: ImageRegistryCredentialsProvidersType - provides the list of credential providers - required. - enum: - - default - - amazon - - azure - - google - - github - type: string - type: array - secrets: - description: |- - Secrets specifies a list of secrets that are provided for credentials. - Secrets must live in the Kyverno namespace. - items: - type: string - type: array - type: object - jmesPath: - description: |- - JMESPath is an optional JSON Match Expression that can be used to - transform the ImageData struct returned as a result of processing - the image reference. - type: string - reference: - description: |- - Reference is image reference to a container image in the registry. - Example: ghcr.io/kyverno/kyverno:latest - type: string - required: - - reference - type: object - name: - description: Name is the variable name. - type: string - variable: - description: Variable defines an arbitrary JMESPath context - variable that can be defined inline. - properties: - default: - description: |- - Default is an optional arbitrary JSON object that the variable may take if the JMESPath - expression evaluates to nil - x-kubernetes-preserve-unknown-fields: true - jmesPath: - description: |- - JMESPath is an optional JMESPath Expression that can be used to - transform the variable. - type: string - value: - description: Value is any arbitrary JSON object representable - in YAML or JSON form. - x-kubernetes-preserve-unknown-fields: true - type: object - required: - - name - type: object - type: array - exclude: - description: |- - ExcludeResources defines when this policy rule should not be applied. The exclude - criteria can include resource information (e.g. kind, name, namespace, labels) - and admission review request information like the name or role. - not: - required: - - any - - all - properties: - all: - description: All allows specifying resources which will - be ANDed - items: - description: ResourceFilter allow users to "AND" or "OR" - between resources - properties: - clusterRoles: - description: ClusterRoles is the list of cluster-wide - role names for the user. - items: - type: string - type: array - resources: - description: ResourceDescription contains information - about the resource being created or modified. - not: - required: - - name - - names - properties: - annotations: - additionalProperties: - type: string - description: |- - Annotations is a map of annotations (key-value pairs of type string). Annotation keys - and values support the wildcard characters "*" (matches zero or many characters) and - "?" (matches at least one character). - type: object - kinds: - description: Kinds is a list of resource kinds. - items: - type: string - type: array - name: - description: |- - Name is the name of the resource. The name supports wildcard characters - "*" (matches zero or many characters) and "?" (at least one character). - NOTE: "Name" is being deprecated in favor of "Names". - type: string - names: - description: |- - Names are the names of the resources. Each name supports wildcard characters - "*" (matches zero or many characters) and "?" (at least one character). - items: - type: string - type: array - namespaceSelector: - description: |- - NamespaceSelector is a label selector for the resource namespace. Label keys and values - in `matchLabels` support the wildcard characters `*` (matches zero or many characters) - and `?` (matches one character).Wildcards allows writing label selectors like - ["storage.k8s.io/*": "*"]. Note that using ["*" : "*"] matches any key and value but - does not match an empty label set. - properties: - matchExpressions: - description: matchExpressions is a list of - label selector requirements. The requirements - are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key that - the selector applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - namespaces: - description: |- - Namespaces is a list of namespaces names. Each name supports wildcard characters - "*" (matches zero or many characters) and "?" (at least one character). - items: - type: string - type: array - operations: - description: Operations can contain values ["CREATE, - "UPDATE", "CONNECT", "DELETE"], which are used - to match a specific action. - items: - description: AdmissionOperation can have one - of the values CREATE, UPDATE, CONNECT, DELETE, - which are used to match a specific action. - enum: - - CREATE - - CONNECT - - UPDATE - - DELETE - type: string - type: array - selector: - description: |- - Selector is a label selector. Label keys and values in `matchLabels` support the wildcard - characters `*` (matches zero or many characters) and `?` (matches one character). - Wildcards allows writing label selectors like ["storage.k8s.io/*": "*"]. Note that - using ["*" : "*"] matches any key and value but does not match an empty label set. - properties: - matchExpressions: - description: matchExpressions is a list of - label selector requirements. The requirements - are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key that - the selector applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - type: object - roles: - description: Roles is the list of namespaced role - names for the user. - items: - type: string - type: array - subjects: - description: Subjects is the list of subject names - like users, user groups, and service accounts. - items: - description: |- - Subject contains a reference to the object or user identities a role binding applies to. This can either hold a direct API object reference, - or a value for non-objects such as user and group names. - properties: - apiGroup: - description: |- - APIGroup holds the API group of the referenced subject. - Defaults to "" for ServiceAccount subjects. - Defaults to "rbac.authorization.k8s.io" for User and Group subjects. - type: string - kind: - description: |- - Kind of object being referenced. Values defined by this API group are "User", "Group", and "ServiceAccount". - If the Authorizer does not recognized the kind value, the Authorizer should report an error. - type: string - name: - description: Name of the object being referenced. - type: string - namespace: - description: |- - Namespace of the referenced object. If the object kind is non-namespace, such as "User" or "Group", and this value is not empty - the Authorizer should report an error. - type: string - required: - - kind - - name - type: object - x-kubernetes-map-type: atomic - type: array - type: object - type: array - any: - description: Any allows specifying resources which will - be ORed - items: - description: ResourceFilter allow users to "AND" or "OR" - between resources - properties: - clusterRoles: - description: ClusterRoles is the list of cluster-wide - role names for the user. - items: - type: string - type: array - resources: - description: ResourceDescription contains information - about the resource being created or modified. - not: - required: - - name - - names - properties: - annotations: - additionalProperties: - type: string - description: |- - Annotations is a map of annotations (key-value pairs of type string). Annotation keys - and values support the wildcard characters "*" (matches zero or many characters) and - "?" (matches at least one character). - type: object - kinds: - description: Kinds is a list of resource kinds. - items: - type: string - type: array - name: - description: |- - Name is the name of the resource. The name supports wildcard characters - "*" (matches zero or many characters) and "?" (at least one character). - NOTE: "Name" is being deprecated in favor of "Names". - type: string - names: - description: |- - Names are the names of the resources. Each name supports wildcard characters - "*" (matches zero or many characters) and "?" (at least one character). - items: - type: string - type: array - namespaceSelector: - description: |- - NamespaceSelector is a label selector for the resource namespace. Label keys and values - in `matchLabels` support the wildcard characters `*` (matches zero or many characters) - and `?` (matches one character).Wildcards allows writing label selectors like - ["storage.k8s.io/*": "*"]. Note that using ["*" : "*"] matches any key and value but - does not match an empty label set. - properties: - matchExpressions: - description: matchExpressions is a list of - label selector requirements. The requirements - are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key that - the selector applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - namespaces: - description: |- - Namespaces is a list of namespaces names. Each name supports wildcard characters - "*" (matches zero or many characters) and "?" (at least one character). - items: - type: string - type: array - operations: - description: Operations can contain values ["CREATE, - "UPDATE", "CONNECT", "DELETE"], which are used - to match a specific action. - items: - description: AdmissionOperation can have one - of the values CREATE, UPDATE, CONNECT, DELETE, - which are used to match a specific action. - enum: - - CREATE - - CONNECT - - UPDATE - - DELETE - type: string - type: array - selector: - description: |- - Selector is a label selector. Label keys and values in `matchLabels` support the wildcard - characters `*` (matches zero or many characters) and `?` (matches one character). - Wildcards allows writing label selectors like ["storage.k8s.io/*": "*"]. Note that - using ["*" : "*"] matches any key and value but does not match an empty label set. - properties: - matchExpressions: - description: matchExpressions is a list of - label selector requirements. The requirements - are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key that - the selector applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - type: object - roles: - description: Roles is the list of namespaced role - names for the user. - items: - type: string - type: array - subjects: - description: Subjects is the list of subject names - like users, user groups, and service accounts. - items: - description: |- - Subject contains a reference to the object or user identities a role binding applies to. This can either hold a direct API object reference, - or a value for non-objects such as user and group names. - properties: - apiGroup: - description: |- - APIGroup holds the API group of the referenced subject. - Defaults to "" for ServiceAccount subjects. - Defaults to "rbac.authorization.k8s.io" for User and Group subjects. - type: string - kind: - description: |- - Kind of object being referenced. Values defined by this API group are "User", "Group", and "ServiceAccount". - If the Authorizer does not recognized the kind value, the Authorizer should report an error. - type: string - name: - description: Name of the object being referenced. - type: string - namespace: - description: |- - Namespace of the referenced object. If the object kind is non-namespace, such as "User" or "Group", and this value is not empty - the Authorizer should report an error. - type: string - required: - - kind - - name - type: object - x-kubernetes-map-type: atomic - type: array - type: object - type: array - type: object - generate: - description: Generation is used to create new resources. - properties: - apiVersion: - description: APIVersion specifies resource apiVersion. - type: string - clone: - description: |- - Clone specifies the source resource used to populate each generated resource. - At most one of Data or Clone can be specified. If neither are provided, the generated - resource will be created with default data only. - properties: - name: - description: Name specifies name of the resource. - type: string - namespace: - description: Namespace specifies source resource namespace. - type: string - type: object - cloneList: - description: CloneList specifies the list of source resource - used to populate each generated resource. - properties: - kinds: - description: Kinds is a list of resource kinds. - items: - type: string - type: array - namespace: - description: Namespace specifies source resource namespace. - type: string - selector: - description: |- - Selector is a label selector. Label keys and values in `matchLabels`. - wildcard characters are not supported. - properties: - matchExpressions: - description: matchExpressions is a list of label - selector requirements. The requirements are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key that the - selector applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - type: object - data: - description: |- - Data provides the resource declaration used to populate each generated resource. - At most one of Data or Clone must be specified. If neither are provided, the generated - resource will be created with default data only. - x-kubernetes-preserve-unknown-fields: true - foreach: - description: ForEach applies generate rules to a list of - sub-elements by creating a context for each entry in the - list and looping over it to apply the specified logic. - items: - properties: - apiVersion: - description: APIVersion specifies resource apiVersion. - type: string - clone: - description: |- - Clone specifies the source resource used to populate each generated resource. - At most one of Data or Clone can be specified. If neither are provided, the generated - resource will be created with default data only. - properties: - name: - description: Name specifies name of the resource. - type: string - namespace: - description: Namespace specifies source resource - namespace. - type: string - type: object - cloneList: - description: CloneList specifies the list of source - resource used to populate each generated resource. - properties: - kinds: - description: Kinds is a list of resource kinds. - items: - type: string - type: array - namespace: - description: Namespace specifies source resource - namespace. - type: string - selector: - description: |- - Selector is a label selector. Label keys and values in `matchLabels`. - wildcard characters are not supported. - properties: - matchExpressions: - description: matchExpressions is a list of - label selector requirements. The requirements - are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key that - the selector applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - type: object - context: - description: Context defines variables and data sources - that can be used during rule execution. - items: - description: |- - ContextEntry adds variables and data sources to a rule Context. Either a - ConfigMap reference or a APILookup must be provided. - oneOf: - - required: - - configMap - - required: - - apiCall - - required: - - imageRegistry - - required: - - variable - - required: - - globalReference - properties: - apiCall: - description: |- - APICall is an HTTP request to the Kubernetes API server, or other JSON web service. - The data returned is stored in the context with the name for the context entry. - properties: - data: - description: |- - The data object specifies the POST data sent to the server. - Only applicable when the method field is set to POST. - items: - description: RequestData contains the - HTTP POST data - properties: - key: - description: Key is a unique identifier - for the data value - type: string - value: - description: Value is the data value - x-kubernetes-preserve-unknown-fields: true - required: - - key - - value - type: object - type: array - default: - description: |- - Default is an optional arbitrary JSON object that the context - value is set to, if the apiCall returns error. - x-kubernetes-preserve-unknown-fields: true - jmesPath: - description: |- - JMESPath is an optional JSON Match Expression that can be used to - transform the JSON response returned from the server. For example - a JMESPath of "items | length(@)" applied to the API server response - for the URLPath "/apis/apps/v1/deployments" will return the total count - of deployments across all namespaces. - type: string - method: - default: GET - description: Method is the HTTP request - type (GET or POST). Defaults to GET. - enum: - - GET - - POST - type: string - service: - description: |- - Service is an API call to a JSON web service. - This is used for non-Kubernetes API server calls. - It's mutually exclusive with the URLPath field. - properties: - caBundle: - description: |- - CABundle is a PEM encoded CA bundle which will be used to validate - the server certificate. - type: string - headers: - description: Headers is a list of optional - HTTP headers to be included in the - request. - items: - properties: - key: - description: Key is the header - key - type: string - value: - description: Value is the header - value - type: string - required: - - key - - value - type: object - type: array - url: - description: |- - URL is the JSON web service URL. A typical form is - `https://{service}.{namespace}:{port}/{path}`. - type: string - required: - - url - type: object - urlPath: - description: |- - URLPath is the URL path to be used in the HTTP GET or POST request to the - Kubernetes API server (e.g. "/api/v1/namespaces" or "/apis/apps/v1/deployments"). - The format required is the same format used by the `kubectl get --raw` command. - See https://kyverno.io/docs/writing-policies/external-data-sources/#variables-from-kubernetes-api-server-calls - for details. - It's mutually exclusive with the Service field. - type: string - type: object - configMap: - description: ConfigMap is the ConfigMap reference. - properties: - name: - description: Name is the ConfigMap name. - type: string - namespace: - description: Namespace is the ConfigMap - namespace. - type: string - required: - - name - type: object - globalReference: - description: GlobalContextEntryReference is - a reference to a cached global context entry. - properties: - jmesPath: - description: |- - JMESPath is an optional JSON Match Expression that can be used to - transform the JSON response returned from the server. For example - a JMESPath of "items | length(@)" applied to the API server response - for the URLPath "/apis/apps/v1/deployments" will return the total count - of deployments across all namespaces. - type: string - name: - description: Name of the global context - entry - type: string - required: - - name - type: object - imageRegistry: - description: |- - ImageRegistry defines requests to an OCI/Docker V2 registry to fetch image - details. - properties: - imageRegistryCredentials: - description: ImageRegistryCredentials provides - credentials that will be used for authentication - with registry - properties: - allowInsecureRegistry: - description: AllowInsecureRegistry allows - insecure access to a registry. - type: boolean - providers: - description: |- - Providers specifies a list of OCI Registry names, whose authentication providers are provided. - It can be of one of these values: default,google,azure,amazon,github. - items: - description: ImageRegistryCredentialsProvidersType - provides the list of credential - providers required. - enum: - - default - - amazon - - azure - - google - - github - type: string - type: array - secrets: - description: |- - Secrets specifies a list of secrets that are provided for credentials. - Secrets must live in the Kyverno namespace. - items: - type: string - type: array - type: object - jmesPath: - description: |- - JMESPath is an optional JSON Match Expression that can be used to - transform the ImageData struct returned as a result of processing - the image reference. - type: string - reference: - description: |- - Reference is image reference to a container image in the registry. - Example: ghcr.io/kyverno/kyverno:latest - type: string - required: - - reference - type: object - name: - description: Name is the variable name. - type: string - variable: - description: Variable defines an arbitrary JMESPath - context variable that can be defined inline. - properties: - default: - description: |- - Default is an optional arbitrary JSON object that the variable may take if the JMESPath - expression evaluates to nil - x-kubernetes-preserve-unknown-fields: true - jmesPath: - description: |- - JMESPath is an optional JMESPath Expression that can be used to - transform the variable. - type: string - value: - description: Value is any arbitrary JSON - object representable in YAML or JSON form. - x-kubernetes-preserve-unknown-fields: true - type: object - required: - - name - type: object - type: array - data: - description: |- - Data provides the resource declaration used to populate each generated resource. - At most one of Data or Clone must be specified. If neither are provided, the generated - resource will be created with default data only. - x-kubernetes-preserve-unknown-fields: true - kind: - description: Kind specifies resource kind. - type: string - list: - description: |- - List specifies a JMESPath expression that results in one or more elements - to which the validation logic is applied. - type: string - name: - description: Name specifies the resource name. - type: string - namespace: - description: Namespace specifies resource namespace. - type: string - preconditions: - description: |- - AnyAllConditions are used to determine if a policy rule should be applied by evaluating a - set of conditions. The declaration can contain nested `any` or `all` statements. - See: https://kyverno.io/docs/writing-policies/preconditions/ - properties: - all: - description: |- - AllConditions enable variable-based conditional rule execution. This is useful for - finer control of when an rule is applied. A condition can reference object data - using JMESPath notation. - Here, all of the conditions need to pass - items: - description: Condition defines variable-based - conditional criteria for rule execution. - properties: - key: - description: Key is the context entry (using - JMESPath) for conditional rule evaluation. - x-kubernetes-preserve-unknown-fields: true - message: - description: Message is an optional display - message - type: string - operator: - description: |- - Operator is the conditional operation to perform. Valid operators are: - Equals, NotEquals, In, AnyIn, AllIn, NotIn, AnyNotIn, AllNotIn, GreaterThanOrEquals, - GreaterThan, LessThanOrEquals, LessThan, DurationGreaterThanOrEquals, DurationGreaterThan, - DurationLessThanOrEquals, DurationLessThan - enum: - - Equals - - NotEquals - - In - - AnyIn - - AllIn - - NotIn - - AnyNotIn - - AllNotIn - - GreaterThanOrEquals - - GreaterThan - - LessThanOrEquals - - LessThan - - DurationGreaterThanOrEquals - - DurationGreaterThan - - DurationLessThanOrEquals - - DurationLessThan - type: string - value: - description: |- - Value is the conditional value, or set of values. The values can be fixed set - or can be variables declared using JMESPath. - x-kubernetes-preserve-unknown-fields: true - type: object - type: array - any: - description: |- - AnyConditions enable variable-based conditional rule execution. This is useful for - finer control of when an rule is applied. A condition can reference object data - using JMESPath notation. - Here, at least one of the conditions need to pass - items: - description: Condition defines variable-based - conditional criteria for rule execution. - properties: - key: - description: Key is the context entry (using - JMESPath) for conditional rule evaluation. - x-kubernetes-preserve-unknown-fields: true - message: - description: Message is an optional display - message - type: string - operator: - description: |- - Operator is the conditional operation to perform. Valid operators are: - Equals, NotEquals, In, AnyIn, AllIn, NotIn, AnyNotIn, AllNotIn, GreaterThanOrEquals, - GreaterThan, LessThanOrEquals, LessThan, DurationGreaterThanOrEquals, DurationGreaterThan, - DurationLessThanOrEquals, DurationLessThan - enum: - - Equals - - NotEquals - - In - - AnyIn - - AllIn - - NotIn - - AnyNotIn - - AllNotIn - - GreaterThanOrEquals - - GreaterThan - - LessThanOrEquals - - LessThan - - DurationGreaterThanOrEquals - - DurationGreaterThan - - DurationLessThanOrEquals - - DurationLessThan - type: string - value: - description: |- - Value is the conditional value, or set of values. The values can be fixed set - or can be variables declared using JMESPath. - x-kubernetes-preserve-unknown-fields: true - type: object - type: array - type: object - x-kubernetes-preserve-unknown-fields: true - uid: - description: UID specifies the resource uid. - type: string - type: object - type: array - generateExisting: - description: |- - GenerateExisting controls whether to trigger the rule in existing resources - If is set to "true" the rule will be triggered and applied to existing matched resources. - type: boolean - kind: - description: Kind specifies resource kind. - type: string - name: - description: Name specifies the resource name. - type: string - namespace: - description: Namespace specifies resource namespace. - type: string - orphanDownstreamOnPolicyDelete: - description: |- - OrphanDownstreamOnPolicyDelete controls whether generated resources should be deleted when the rule that generated - them is deleted with synchronization enabled. This option is only applicable to generate rules of the data type. - See https://kyverno.io/docs/writing-policies/generate/#data-examples. - Defaults to "false" if not specified. - type: boolean - synchronize: - description: |- - Synchronize controls if generated resources should be kept in-sync with their source resource. - If Synchronize is set to "true" changes to generated resources will be overwritten with resource - data from Data or the resource specified in the Clone declaration. - Optional. Defaults to "false" if not specified. - type: boolean - uid: - description: UID specifies the resource uid. - type: string - type: object - imageExtractors: - additionalProperties: - items: - properties: - jmesPath: - description: |- - JMESPath is an optional JMESPath expression to apply to the image value. - This is useful when the extracted image begins with a prefix like 'docker://'. - The 'trim_prefix' function may be used to trim the prefix: trim_prefix(@, 'docker://'). - Note - Image digest mutation may not be used when applying a JMESPAth to an image. - type: string - key: - description: |- - Key is an optional name of the field within 'path' that will be used to uniquely identify an image. - Note - this field MUST be unique. - type: string - name: - description: |- - Name is the entry the image will be available under 'images.' in the context. - If this field is not defined, image entries will appear under 'images.custom'. - type: string - path: - description: |- - Path is the path to the object containing the image field in a custom resource. - It should be slash-separated. Each slash-separated key must be a valid YAML key or a wildcard '*'. - Wildcard keys are expanded in case of arrays or objects. - type: string - value: - description: |- - Value is an optional name of the field within 'path' that points to the image URI. - This is useful when a custom 'key' is also defined. - type: string - required: - - path - type: object - type: array - description: |- - ImageExtractors defines a mapping from kinds to ImageExtractorConfigs. - This config is only valid for verifyImages rules. - type: object - match: - description: |- - MatchResources defines when this policy rule should be applied. The match - criteria can include resource information (e.g. kind, name, namespace, labels) - and admission review request information like the user name or role. - At least one kind is required. - not: - required: - - any - - all - properties: - all: - description: All allows specifying resources which will - be ANDed - items: - description: ResourceFilter allow users to "AND" or "OR" - between resources - properties: - clusterRoles: - description: ClusterRoles is the list of cluster-wide - role names for the user. - items: - type: string - type: array - resources: - description: ResourceDescription contains information - about the resource being created or modified. - not: - required: - - name - - names - properties: - annotations: - additionalProperties: - type: string - description: |- - Annotations is a map of annotations (key-value pairs of type string). Annotation keys - and values support the wildcard characters "*" (matches zero or many characters) and - "?" (matches at least one character). - type: object - kinds: - description: Kinds is a list of resource kinds. - items: - type: string - type: array - name: - description: |- - Name is the name of the resource. The name supports wildcard characters - "*" (matches zero or many characters) and "?" (at least one character). - NOTE: "Name" is being deprecated in favor of "Names". - type: string - names: - description: |- - Names are the names of the resources. Each name supports wildcard characters - "*" (matches zero or many characters) and "?" (at least one character). - items: - type: string - type: array - namespaceSelector: - description: |- - NamespaceSelector is a label selector for the resource namespace. Label keys and values - in `matchLabels` support the wildcard characters `*` (matches zero or many characters) - and `?` (matches one character).Wildcards allows writing label selectors like - ["storage.k8s.io/*": "*"]. Note that using ["*" : "*"] matches any key and value but - does not match an empty label set. - properties: - matchExpressions: - description: matchExpressions is a list of - label selector requirements. The requirements - are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key that - the selector applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - namespaces: - description: |- - Namespaces is a list of namespaces names. Each name supports wildcard characters - "*" (matches zero or many characters) and "?" (at least one character). - items: - type: string - type: array - operations: - description: Operations can contain values ["CREATE, - "UPDATE", "CONNECT", "DELETE"], which are used - to match a specific action. - items: - description: AdmissionOperation can have one - of the values CREATE, UPDATE, CONNECT, DELETE, - which are used to match a specific action. - enum: - - CREATE - - CONNECT - - UPDATE - - DELETE - type: string - type: array - selector: - description: |- - Selector is a label selector. Label keys and values in `matchLabels` support the wildcard - characters `*` (matches zero or many characters) and `?` (matches one character). - Wildcards allows writing label selectors like ["storage.k8s.io/*": "*"]. Note that - using ["*" : "*"] matches any key and value but does not match an empty label set. - properties: - matchExpressions: - description: matchExpressions is a list of - label selector requirements. The requirements - are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key that - the selector applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - type: object - roles: - description: Roles is the list of namespaced role - names for the user. - items: - type: string - type: array - subjects: - description: Subjects is the list of subject names - like users, user groups, and service accounts. - items: - description: |- - Subject contains a reference to the object or user identities a role binding applies to. This can either hold a direct API object reference, - or a value for non-objects such as user and group names. - properties: - apiGroup: - description: |- - APIGroup holds the API group of the referenced subject. - Defaults to "" for ServiceAccount subjects. - Defaults to "rbac.authorization.k8s.io" for User and Group subjects. - type: string - kind: - description: |- - Kind of object being referenced. Values defined by this API group are "User", "Group", and "ServiceAccount". - If the Authorizer does not recognized the kind value, the Authorizer should report an error. - type: string - name: - description: Name of the object being referenced. - type: string - namespace: - description: |- - Namespace of the referenced object. If the object kind is non-namespace, such as "User" or "Group", and this value is not empty - the Authorizer should report an error. - type: string - required: - - kind - - name - type: object - x-kubernetes-map-type: atomic - type: array - type: object - type: array - any: - description: Any allows specifying resources which will - be ORed - items: - description: ResourceFilter allow users to "AND" or "OR" - between resources - properties: - clusterRoles: - description: ClusterRoles is the list of cluster-wide - role names for the user. - items: - type: string - type: array - resources: - description: ResourceDescription contains information - about the resource being created or modified. - not: - required: - - name - - names - properties: - annotations: - additionalProperties: - type: string - description: |- - Annotations is a map of annotations (key-value pairs of type string). Annotation keys - and values support the wildcard characters "*" (matches zero or many characters) and - "?" (matches at least one character). - type: object - kinds: - description: Kinds is a list of resource kinds. - items: - type: string - type: array - name: - description: |- - Name is the name of the resource. The name supports wildcard characters - "*" (matches zero or many characters) and "?" (at least one character). - NOTE: "Name" is being deprecated in favor of "Names". - type: string - names: - description: |- - Names are the names of the resources. Each name supports wildcard characters - "*" (matches zero or many characters) and "?" (at least one character). - items: - type: string - type: array - namespaceSelector: - description: |- - NamespaceSelector is a label selector for the resource namespace. Label keys and values - in `matchLabels` support the wildcard characters `*` (matches zero or many characters) - and `?` (matches one character).Wildcards allows writing label selectors like - ["storage.k8s.io/*": "*"]. Note that using ["*" : "*"] matches any key and value but - does not match an empty label set. - properties: - matchExpressions: - description: matchExpressions is a list of - label selector requirements. The requirements - are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key that - the selector applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - namespaces: - description: |- - Namespaces is a list of namespaces names. Each name supports wildcard characters - "*" (matches zero or many characters) and "?" (at least one character). - items: - type: string - type: array - operations: - description: Operations can contain values ["CREATE, - "UPDATE", "CONNECT", "DELETE"], which are used - to match a specific action. - items: - description: AdmissionOperation can have one - of the values CREATE, UPDATE, CONNECT, DELETE, - which are used to match a specific action. - enum: - - CREATE - - CONNECT - - UPDATE - - DELETE - type: string - type: array - selector: - description: |- - Selector is a label selector. Label keys and values in `matchLabels` support the wildcard - characters `*` (matches zero or many characters) and `?` (matches one character). - Wildcards allows writing label selectors like ["storage.k8s.io/*": "*"]. Note that - using ["*" : "*"] matches any key and value but does not match an empty label set. - properties: - matchExpressions: - description: matchExpressions is a list of - label selector requirements. The requirements - are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key that - the selector applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - type: object - roles: - description: Roles is the list of namespaced role - names for the user. - items: - type: string - type: array - subjects: - description: Subjects is the list of subject names - like users, user groups, and service accounts. - items: - description: |- - Subject contains a reference to the object or user identities a role binding applies to. This can either hold a direct API object reference, - or a value for non-objects such as user and group names. - properties: - apiGroup: - description: |- - APIGroup holds the API group of the referenced subject. - Defaults to "" for ServiceAccount subjects. - Defaults to "rbac.authorization.k8s.io" for User and Group subjects. - type: string - kind: - description: |- - Kind of object being referenced. Values defined by this API group are "User", "Group", and "ServiceAccount". - If the Authorizer does not recognized the kind value, the Authorizer should report an error. - type: string - name: - description: Name of the object being referenced. - type: string - namespace: - description: |- - Namespace of the referenced object. If the object kind is non-namespace, such as "User" or "Group", and this value is not empty - the Authorizer should report an error. - type: string - required: - - kind - - name - type: object - x-kubernetes-map-type: atomic - type: array - type: object - type: array - type: object - mutate: - description: Mutation is used to modify matching resources. - properties: - foreach: - description: ForEach applies mutation rules to a list of - sub-elements by creating a context for each entry in the - list and looping over it to apply the specified logic. - items: - description: ForEachMutation applies mutation rules to - a list of sub-elements by creating a context for each - entry in the list and looping over it to apply the specified - logic. - properties: - context: - description: Context defines variables and data sources - that can be used during rule execution. - items: - description: |- - ContextEntry adds variables and data sources to a rule Context. Either a - ConfigMap reference or a APILookup must be provided. - oneOf: - - required: - - configMap - - required: - - apiCall - - required: - - imageRegistry - - required: - - variable - - required: - - globalReference - properties: - apiCall: - description: |- - APICall is an HTTP request to the Kubernetes API server, or other JSON web service. - The data returned is stored in the context with the name for the context entry. - properties: - data: - description: |- - The data object specifies the POST data sent to the server. - Only applicable when the method field is set to POST. - items: - description: RequestData contains the - HTTP POST data - properties: - key: - description: Key is a unique identifier - for the data value - type: string - value: - description: Value is the data value - x-kubernetes-preserve-unknown-fields: true - required: - - key - - value - type: object - type: array - default: - description: |- - Default is an optional arbitrary JSON object that the context - value is set to, if the apiCall returns error. - x-kubernetes-preserve-unknown-fields: true - jmesPath: - description: |- - JMESPath is an optional JSON Match Expression that can be used to - transform the JSON response returned from the server. For example - a JMESPath of "items | length(@)" applied to the API server response - for the URLPath "/apis/apps/v1/deployments" will return the total count - of deployments across all namespaces. - type: string - method: - default: GET - description: Method is the HTTP request - type (GET or POST). Defaults to GET. - enum: - - GET - - POST - type: string - service: - description: |- - Service is an API call to a JSON web service. - This is used for non-Kubernetes API server calls. - It's mutually exclusive with the URLPath field. - properties: - caBundle: - description: |- - CABundle is a PEM encoded CA bundle which will be used to validate - the server certificate. - type: string - headers: - description: Headers is a list of optional - HTTP headers to be included in the - request. - items: - properties: - key: - description: Key is the header - key - type: string - value: - description: Value is the header - value - type: string - required: - - key - - value - type: object - type: array - url: - description: |- - URL is the JSON web service URL. A typical form is - `https://{service}.{namespace}:{port}/{path}`. - type: string - required: - - url - type: object - urlPath: - description: |- - URLPath is the URL path to be used in the HTTP GET or POST request to the - Kubernetes API server (e.g. "/api/v1/namespaces" or "/apis/apps/v1/deployments"). - The format required is the same format used by the `kubectl get --raw` command. - See https://kyverno.io/docs/writing-policies/external-data-sources/#variables-from-kubernetes-api-server-calls - for details. - It's mutually exclusive with the Service field. - type: string - type: object - configMap: - description: ConfigMap is the ConfigMap reference. - properties: - name: - description: Name is the ConfigMap name. - type: string - namespace: - description: Namespace is the ConfigMap - namespace. - type: string - required: - - name - type: object - globalReference: - description: GlobalContextEntryReference is - a reference to a cached global context entry. - properties: - jmesPath: - description: |- - JMESPath is an optional JSON Match Expression that can be used to - transform the JSON response returned from the server. For example - a JMESPath of "items | length(@)" applied to the API server response - for the URLPath "/apis/apps/v1/deployments" will return the total count - of deployments across all namespaces. - type: string - name: - description: Name of the global context - entry - type: string - required: - - name - type: object - imageRegistry: - description: |- - ImageRegistry defines requests to an OCI/Docker V2 registry to fetch image - details. - properties: - imageRegistryCredentials: - description: ImageRegistryCredentials provides - credentials that will be used for authentication - with registry - properties: - allowInsecureRegistry: - description: AllowInsecureRegistry allows - insecure access to a registry. - type: boolean - providers: - description: |- - Providers specifies a list of OCI Registry names, whose authentication providers are provided. - It can be of one of these values: default,google,azure,amazon,github. - items: - description: ImageRegistryCredentialsProvidersType - provides the list of credential - providers required. - enum: - - default - - amazon - - azure - - google - - github - type: string - type: array - secrets: - description: |- - Secrets specifies a list of secrets that are provided for credentials. - Secrets must live in the Kyverno namespace. - items: - type: string - type: array - type: object - jmesPath: - description: |- - JMESPath is an optional JSON Match Expression that can be used to - transform the ImageData struct returned as a result of processing - the image reference. - type: string - reference: - description: |- - Reference is image reference to a container image in the registry. - Example: ghcr.io/kyverno/kyverno:latest - type: string - required: - - reference - type: object - name: - description: Name is the variable name. - type: string - variable: - description: Variable defines an arbitrary JMESPath - context variable that can be defined inline. - properties: - default: - description: |- - Default is an optional arbitrary JSON object that the variable may take if the JMESPath - expression evaluates to nil - x-kubernetes-preserve-unknown-fields: true - jmesPath: - description: |- - JMESPath is an optional JMESPath Expression that can be used to - transform the variable. - type: string - value: - description: Value is any arbitrary JSON - object representable in YAML or JSON form. - x-kubernetes-preserve-unknown-fields: true - type: object - required: - - name - type: object - type: array - foreach: - description: Foreach declares a nested foreach iterator - x-kubernetes-preserve-unknown-fields: true - list: - description: |- - List specifies a JMESPath expression that results in one or more elements - to which the validation logic is applied. - type: string - order: - description: |- - Order defines the iteration order on the list. - Can be Ascending to iterate from first to last element or Descending to iterate in from last to first element. - enum: - - Ascending - - Descending - type: string - patchStrategicMerge: - description: |- - PatchStrategicMerge is a strategic merge patch used to modify resources. - See https://kubernetes.io/docs/tasks/manage-kubernetes-objects/update-api-object-kubectl-patch/ - and https://kubectl.docs.kubernetes.io/references/kustomize/kustomization/patchesstrategicmerge/. - x-kubernetes-preserve-unknown-fields: true - patchesJson6902: - description: |- - PatchesJSON6902 is a list of RFC 6902 JSON Patch declarations used to modify resources. - See https://tools.ietf.org/html/rfc6902 and https://kubectl.docs.kubernetes.io/references/kustomize/kustomization/patchesjson6902/. - type: string - preconditions: - description: |- - AnyAllConditions are used to determine if a policy rule should be applied by evaluating a - set of conditions. The declaration can contain nested `any` or `all` statements. - See: https://kyverno.io/docs/writing-policies/preconditions/ - properties: - all: - description: |- - AllConditions enable variable-based conditional rule execution. This is useful for - finer control of when an rule is applied. A condition can reference object data - using JMESPath notation. - Here, all of the conditions need to pass - items: - description: Condition defines variable-based - conditional criteria for rule execution. - properties: - key: - description: Key is the context entry (using - JMESPath) for conditional rule evaluation. - x-kubernetes-preserve-unknown-fields: true - message: - description: Message is an optional display - message - type: string - operator: - description: |- - Operator is the conditional operation to perform. Valid operators are: - Equals, NotEquals, In, AnyIn, AllIn, NotIn, AnyNotIn, AllNotIn, GreaterThanOrEquals, - GreaterThan, LessThanOrEquals, LessThan, DurationGreaterThanOrEquals, DurationGreaterThan, - DurationLessThanOrEquals, DurationLessThan - enum: - - Equals - - NotEquals - - In - - AnyIn - - AllIn - - NotIn - - AnyNotIn - - AllNotIn - - GreaterThanOrEquals - - GreaterThan - - LessThanOrEquals - - LessThan - - DurationGreaterThanOrEquals - - DurationGreaterThan - - DurationLessThanOrEquals - - DurationLessThan - type: string - value: - description: |- - Value is the conditional value, or set of values. The values can be fixed set - or can be variables declared using JMESPath. - x-kubernetes-preserve-unknown-fields: true - type: object - type: array - any: - description: |- - AnyConditions enable variable-based conditional rule execution. This is useful for - finer control of when an rule is applied. A condition can reference object data - using JMESPath notation. - Here, at least one of the conditions need to pass - items: - description: Condition defines variable-based - conditional criteria for rule execution. - properties: - key: - description: Key is the context entry (using - JMESPath) for conditional rule evaluation. - x-kubernetes-preserve-unknown-fields: true - message: - description: Message is an optional display - message - type: string - operator: - description: |- - Operator is the conditional operation to perform. Valid operators are: - Equals, NotEquals, In, AnyIn, AllIn, NotIn, AnyNotIn, AllNotIn, GreaterThanOrEquals, - GreaterThan, LessThanOrEquals, LessThan, DurationGreaterThanOrEquals, DurationGreaterThan, - DurationLessThanOrEquals, DurationLessThan - enum: - - Equals - - NotEquals - - In - - AnyIn - - AllIn - - NotIn - - AnyNotIn - - AllNotIn - - GreaterThanOrEquals - - GreaterThan - - LessThanOrEquals - - LessThan - - DurationGreaterThanOrEquals - - DurationGreaterThan - - DurationLessThanOrEquals - - DurationLessThan - type: string - value: - description: |- - Value is the conditional value, or set of values. The values can be fixed set - or can be variables declared using JMESPath. - x-kubernetes-preserve-unknown-fields: true - type: object - type: array - type: object - x-kubernetes-preserve-unknown-fields: true - type: object - type: array - mutateExistingOnPolicyUpdate: - description: MutateExistingOnPolicyUpdate controls if the - mutateExisting rule will be applied on policy events. - type: boolean - patchStrategicMerge: - description: |- - PatchStrategicMerge is a strategic merge patch used to modify resources. - See https://kubernetes.io/docs/tasks/manage-kubernetes-objects/update-api-object-kubectl-patch/ - and https://kubectl.docs.kubernetes.io/references/kustomize/kustomization/patchesstrategicmerge/. - x-kubernetes-preserve-unknown-fields: true - patchesJson6902: - description: |- - PatchesJSON6902 is a list of RFC 6902 JSON Patch declarations used to modify resources. - See https://tools.ietf.org/html/rfc6902 and https://kubectl.docs.kubernetes.io/references/kustomize/kustomization/patchesjson6902/. - type: string - targets: - description: Targets defines the target resources to be - mutated. - items: - description: TargetResourceSpec defines targets for mutating - existing resources. - properties: - apiVersion: - description: APIVersion specifies resource apiVersion. - type: string - context: - description: Context defines variables and data sources - that can be used during rule execution. - items: - description: |- - ContextEntry adds variables and data sources to a rule Context. Either a - ConfigMap reference or a APILookup must be provided. - oneOf: - - required: - - configMap - - required: - - apiCall - - required: - - imageRegistry - - required: - - variable - - required: - - globalReference - properties: - apiCall: - description: |- - APICall is an HTTP request to the Kubernetes API server, or other JSON web service. - The data returned is stored in the context with the name for the context entry. - properties: - data: - description: |- - The data object specifies the POST data sent to the server. - Only applicable when the method field is set to POST. - items: - description: RequestData contains the - HTTP POST data - properties: - key: - description: Key is a unique identifier - for the data value - type: string - value: - description: Value is the data value - x-kubernetes-preserve-unknown-fields: true - required: - - key - - value - type: object - type: array - default: - description: |- - Default is an optional arbitrary JSON object that the context - value is set to, if the apiCall returns error. - x-kubernetes-preserve-unknown-fields: true - jmesPath: - description: |- - JMESPath is an optional JSON Match Expression that can be used to - transform the JSON response returned from the server. For example - a JMESPath of "items | length(@)" applied to the API server response - for the URLPath "/apis/apps/v1/deployments" will return the total count - of deployments across all namespaces. - type: string - method: - default: GET - description: Method is the HTTP request - type (GET or POST). Defaults to GET. - enum: - - GET - - POST - type: string - service: - description: |- - Service is an API call to a JSON web service. - This is used for non-Kubernetes API server calls. - It's mutually exclusive with the URLPath field. - properties: - caBundle: - description: |- - CABundle is a PEM encoded CA bundle which will be used to validate - the server certificate. - type: string - headers: - description: Headers is a list of optional - HTTP headers to be included in the - request. - items: - properties: - key: - description: Key is the header - key - type: string - value: - description: Value is the header - value - type: string - required: - - key - - value - type: object - type: array - url: - description: |- - URL is the JSON web service URL. A typical form is - `https://{service}.{namespace}:{port}/{path}`. - type: string - required: - - url - type: object - urlPath: - description: |- - URLPath is the URL path to be used in the HTTP GET or POST request to the - Kubernetes API server (e.g. "/api/v1/namespaces" or "/apis/apps/v1/deployments"). - The format required is the same format used by the `kubectl get --raw` command. - See https://kyverno.io/docs/writing-policies/external-data-sources/#variables-from-kubernetes-api-server-calls - for details. - It's mutually exclusive with the Service field. - type: string - type: object - configMap: - description: ConfigMap is the ConfigMap reference. - properties: - name: - description: Name is the ConfigMap name. - type: string - namespace: - description: Namespace is the ConfigMap - namespace. - type: string - required: - - name - type: object - globalReference: - description: GlobalContextEntryReference is - a reference to a cached global context entry. - properties: - jmesPath: - description: |- - JMESPath is an optional JSON Match Expression that can be used to - transform the JSON response returned from the server. For example - a JMESPath of "items | length(@)" applied to the API server response - for the URLPath "/apis/apps/v1/deployments" will return the total count - of deployments across all namespaces. - type: string - name: - description: Name of the global context - entry - type: string - required: - - name - type: object - imageRegistry: - description: |- - ImageRegistry defines requests to an OCI/Docker V2 registry to fetch image - details. - properties: - imageRegistryCredentials: - description: ImageRegistryCredentials provides - credentials that will be used for authentication - with registry - properties: - allowInsecureRegistry: - description: AllowInsecureRegistry allows - insecure access to a registry. - type: boolean - providers: - description: |- - Providers specifies a list of OCI Registry names, whose authentication providers are provided. - It can be of one of these values: default,google,azure,amazon,github. - items: - description: ImageRegistryCredentialsProvidersType - provides the list of credential - providers required. - enum: - - default - - amazon - - azure - - google - - github - type: string - type: array - secrets: - description: |- - Secrets specifies a list of secrets that are provided for credentials. - Secrets must live in the Kyverno namespace. - items: - type: string - type: array - type: object - jmesPath: - description: |- - JMESPath is an optional JSON Match Expression that can be used to - transform the ImageData struct returned as a result of processing - the image reference. - type: string - reference: - description: |- - Reference is image reference to a container image in the registry. - Example: ghcr.io/kyverno/kyverno:latest - type: string - required: - - reference - type: object - name: - description: Name is the variable name. - type: string - variable: - description: Variable defines an arbitrary JMESPath - context variable that can be defined inline. - properties: - default: - description: |- - Default is an optional arbitrary JSON object that the variable may take if the JMESPath - expression evaluates to nil - x-kubernetes-preserve-unknown-fields: true - jmesPath: - description: |- - JMESPath is an optional JMESPath Expression that can be used to - transform the variable. - type: string - value: - description: Value is any arbitrary JSON - object representable in YAML or JSON form. - x-kubernetes-preserve-unknown-fields: true - type: object - required: - - name - type: object - type: array - kind: - description: Kind specifies resource kind. - type: string - name: - description: Name specifies the resource name. - type: string - namespace: - description: Namespace specifies resource namespace. - type: string - preconditions: - description: |- - Preconditions are used to determine if a policy rule should be applied by evaluating a - set of conditions. The declaration can contain nested `any` or `all` statements. A direct list - of conditions (without `any` or `all` statements is supported for backwards compatibility but - will be deprecated in the next major release. - See: https://kyverno.io/docs/writing-policies/preconditions/ - x-kubernetes-preserve-unknown-fields: true - selector: - description: Selector allows you to select target - resources with their labels. - properties: - matchExpressions: - description: matchExpressions is a list of label - selector requirements. The requirements are - ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key that the - selector applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - uid: - description: UID specifies the resource uid. - type: string - type: object - type: array - type: object - name: - description: Name is a label to identify the rule, It must be - unique within the policy. - maxLength: 63 - type: string - preconditions: - description: |- - Preconditions are used to determine if a policy rule should be applied by evaluating a - set of conditions. The declaration can contain nested `any` or `all` statements. - See: https://kyverno.io/docs/writing-policies/preconditions/ - properties: - all: - description: |- - AllConditions enable variable-based conditional rule execution. This is useful for - finer control of when an rule is applied. A condition can reference object data - using JMESPath notation. - Here, all of the conditions need to pass. - items: - properties: - key: - description: Key is the context entry (using JMESPath) - for conditional rule evaluation. - x-kubernetes-preserve-unknown-fields: true - message: - description: Message is an optional display message - type: string - operator: - description: |- - Operator is the conditional operation to perform. Valid operators are: - Equals, NotEquals, In, AnyIn, AllIn, NotIn, AnyNotIn, AllNotIn, GreaterThanOrEquals, - GreaterThan, LessThanOrEquals, LessThan, DurationGreaterThanOrEquals, DurationGreaterThan, - DurationLessThanOrEquals, DurationLessThan - enum: - - Equals - - NotEquals - - AnyIn - - AllIn - - AnyNotIn - - AllNotIn - - GreaterThanOrEquals - - GreaterThan - - LessThanOrEquals - - LessThan - - DurationGreaterThanOrEquals - - DurationGreaterThan - - DurationLessThanOrEquals - - DurationLessThan - type: string - value: - description: |- - Value is the conditional value, or set of values. The values can be fixed set - or can be variables declared using JMESPath. - x-kubernetes-preserve-unknown-fields: true - type: object - type: array - any: - description: |- - AnyConditions enable variable-based conditional rule execution. This is useful for - finer control of when an rule is applied. A condition can reference object data - using JMESPath notation. - Here, at least one of the conditions need to pass. - items: - properties: - key: - description: Key is the context entry (using JMESPath) - for conditional rule evaluation. - x-kubernetes-preserve-unknown-fields: true - message: - description: Message is an optional display message - type: string - operator: - description: |- - Operator is the conditional operation to perform. Valid operators are: - Equals, NotEquals, In, AnyIn, AllIn, NotIn, AnyNotIn, AllNotIn, GreaterThanOrEquals, - GreaterThan, LessThanOrEquals, LessThan, DurationGreaterThanOrEquals, DurationGreaterThan, - DurationLessThanOrEquals, DurationLessThan - enum: - - Equals - - NotEquals - - AnyIn - - AllIn - - AnyNotIn - - AllNotIn - - GreaterThanOrEquals - - GreaterThan - - LessThanOrEquals - - LessThan - - DurationGreaterThanOrEquals - - DurationGreaterThan - - DurationLessThanOrEquals - - DurationLessThan - type: string - value: - description: |- - Value is the conditional value, or set of values. The values can be fixed set - or can be variables declared using JMESPath. - x-kubernetes-preserve-unknown-fields: true - type: object - type: array - type: object - skipBackgroundRequests: - default: true - description: |- - SkipBackgroundRequests bypasses admission requests that are sent by the background controller. - The default value is set to "true", it must be set to "false" to apply - generate and mutateExisting rules to those requests. - type: boolean - validate: - description: Validation is used to validate matching resources. - properties: - anyPattern: - description: |- - AnyPattern specifies list of validation patterns. At least one of the patterns - must be satisfied for the validation rule to succeed. - x-kubernetes-preserve-unknown-fields: true - assert: - description: Assert defines a kyverno-json assertion tree. - type: object - x-kubernetes-preserve-unknown-fields: true - cel: - description: CEL allows validation checks using the Common - Expression Language (https://kubernetes.io/docs/reference/using-api/cel/). - properties: - auditAnnotations: - description: AuditAnnotations contains CEL expressions - which are used to produce audit annotations for the - audit event of the API request. - items: - description: AuditAnnotation describes how to produce - an audit annotation for an API request. - properties: - key: - description: |- - key specifies the audit annotation key. The audit annotation keys of - a ValidatingAdmissionPolicy must be unique. The key must be a qualified - name ([A-Za-z0-9][-A-Za-z0-9_.]*) no more than 63 bytes in length. - - The key is combined with the resource name of the - ValidatingAdmissionPolicy to construct an audit annotation key: - "{ValidatingAdmissionPolicy name}/{key}". - - If an admission webhook uses the same resource name as this ValidatingAdmissionPolicy - and the same audit annotation key, the annotation key will be identical. - In this case, the first annotation written with the key will be included - in the audit event and all subsequent annotations with the same key - will be discarded. - - Required. - type: string - valueExpression: - description: |- - valueExpression represents the expression which is evaluated by CEL to - produce an audit annotation value. The expression must evaluate to either - a string or null value. If the expression evaluates to a string, the - audit annotation is included with the string value. If the expression - evaluates to null or empty string the audit annotation will be omitted. - The valueExpression may be no longer than 5kb in length. - If the result of the valueExpression is more than 10kb in length, it - will be truncated to 10kb. - - If multiple ValidatingAdmissionPolicyBinding resources match an - API request, then the valueExpression will be evaluated for - each binding. All unique values produced by the valueExpressions - will be joined together in a comma-separated list. - - Required. - type: string - required: - - key - - valueExpression - type: object - type: array - expressions: - description: Expressions is a list of CELExpression - types. - items: - description: Validation specifies the CEL expression - which is used to apply the validation. - properties: - expression: - description: "Expression represents the expression - which will be evaluated by CEL.\nref: https://github.com/google/cel-spec\nCEL - expressions have access to the contents of the - API request/response, organized into CEL variables - as well as some other useful variables:\n\n- - 'object' - The object from the incoming request. - The value is null for DELETE requests.\n- 'oldObject' - - The existing object. The value is null for - CREATE requests.\n- 'request' - Attributes of - the API request([ref](/pkg/apis/admission/types.go#AdmissionRequest)).\n- - 'params' - Parameter resource referred to by - the policy binding being evaluated. Only populated - if the policy has a ParamKind.\n- 'namespaceObject' - - The namespace object that the incoming object - belongs to. The value is null for cluster-scoped - resources.\n- 'variables' - Map of composited - variables, from its name to its lazily evaluated - value.\n For example, a variable named 'foo' - can be accessed as 'variables.foo'.\n- 'authorizer' - - A CEL Authorizer. May be used to perform authorization - checks for the principal (user or service account) - of the request.\n See https://pkg.go.dev/k8s.io/apiserver/pkg/cel/library#Authz\n- - 'authorizer.requestResource' - A CEL ResourceCheck - constructed from the 'authorizer' and configured - with the\n request resource.\n\nThe `apiVersion`, - `kind`, `metadata.name` and `metadata.generateName` - are always accessible from the root of the\nobject. - No other metadata properties are accessible.\n\nOnly - property names of the form `[a-zA-Z_.-/][a-zA-Z0-9_.-/]*` - are accessible.\nAccessible property names are - escaped according to the following rules when - accessed in the expression:\n- '__' escapes - to '__underscores__'\n- '.' escapes to '__dot__'\n- - '-' escapes to '__dash__'\n- '/' escapes to - '__slash__'\n- Property names that exactly match - a CEL RESERVED keyword escape to '__{keyword}__'. - The keywords are:\n\t \"true\", \"false\", - \"null\", \"in\", \"as\", \"break\", \"const\", - \"continue\", \"else\", \"for\", \"function\", - \"if\",\n\t \"import\", \"let\", \"loop\", - \"package\", \"namespace\", \"return\".\nExamples:\n - \ - Expression accessing a property named \"namespace\": - {\"Expression\": \"object.__namespace__ > 0\"}\n - \ - Expression accessing a property named \"x-prop\": - {\"Expression\": \"object.x__dash__prop > 0\"}\n - \ - Expression accessing a property named \"redact__d\": - {\"Expression\": \"object.redact__underscores__d - > 0\"}\n\nEquality on arrays with list type - of 'set' or 'map' ignores element order, i.e. - [1, 2] == [2, 1].\nConcatenation on arrays with - x-kubernetes-list-type use the semantics of - the list type:\n - 'set': `X + Y` performs - a union where the array positions of all elements - in `X` are preserved and\n non-intersecting - elements in `Y` are appended, retaining their - partial order.\n - 'map': `X + Y` performs - a merge where the array positions of all keys - in `X` are preserved but the values\n are - overwritten by values in `Y` when the key sets - of `X` and `Y` intersect. Elements in `Y` with\n - \ non-intersecting keys are appended, retaining - their partial order.\nRequired." - type: string - message: - description: |- - Message represents the message displayed when validation fails. The message is required if the Expression contains - line breaks. The message must not contain line breaks. - If unset, the message is "failed rule: {Rule}". - e.g. "must be a URL with the host matching spec.host" - If the Expression contains line breaks. Message is required. - The message must not contain line breaks. - If unset, the message is "failed Expression: {Expression}". - type: string - messageExpression: - description: |- - messageExpression declares a CEL expression that evaluates to the validation failure message that is returned when this rule fails. - Since messageExpression is used as a failure message, it must evaluate to a string. - If both message and messageExpression are present on a validation, then messageExpression will be used if validation fails. - If messageExpression results in a runtime error, the runtime error is logged, and the validation failure message is produced - as if the messageExpression field were unset. If messageExpression evaluates to an empty string, a string with only spaces, or a string - that contains line breaks, then the validation failure message will also be produced as if the messageExpression field were unset, and - the fact that messageExpression produced an empty string/string with only spaces/string with line breaks will be logged. - messageExpression has access to all the same variables as the `expression` except for 'authorizer' and 'authorizer.requestResource'. - Example: - "object.x must be less than max ("+string(params.max)+")" - type: string - reason: - description: |- - Reason represents a machine-readable description of why this validation failed. - If this is the first validation in the list to fail, this reason, as well as the - corresponding HTTP response code, are used in the - HTTP response to the client. - The currently supported reasons are: "Unauthorized", "Forbidden", "Invalid", "RequestEntityTooLarge". - If not set, StatusReasonInvalid is used in the response to the client. - type: string - required: - - expression - type: object - type: array - generate: - default: false - description: |- - Generate specifies whether to generate a Kubernetes ValidatingAdmissionPolicy from the rule. - Optional. Defaults to "false" if not specified. - type: boolean - paramKind: - description: ParamKind is a tuple of Group Kind and - Version. - properties: - apiVersion: - description: |- - APIVersion is the API group version the resources belong to. - In format of "group/version". - Required. - type: string - kind: - description: |- - Kind is the API kind the resources belong to. - Required. - type: string - type: object - x-kubernetes-map-type: atomic - paramRef: - description: ParamRef references a parameter resource. - properties: - name: - description: |- - name is the name of the resource being referenced. - - One of `name` or `selector` must be set, but `name` and `selector` are - mutually exclusive properties. If one is set, the other must be unset. - - A single parameter used for all admission requests can be configured - by setting the `name` field, leaving `selector` blank, and setting namespace - if `paramKind` is namespace-scoped. - type: string - namespace: - description: |- - namespace is the namespace of the referenced resource. Allows limiting - the search for params to a specific namespace. Applies to both `name` and - `selector` fields. - - A per-namespace parameter may be used by specifying a namespace-scoped - `paramKind` in the policy and leaving this field empty. - - - If `paramKind` is cluster-scoped, this field MUST be unset. Setting this - field results in a configuration error. - - - If `paramKind` is namespace-scoped, the namespace of the object being - evaluated for admission will be used when this field is left unset. Take - care that if this is left empty the binding must not match any cluster-scoped - resources, which will result in an error. - type: string - parameterNotFoundAction: - description: |- - `parameterNotFoundAction` controls the behavior of the binding when the resource - exists, and name or selector is valid, but there are no parameters - matched by the binding. If the value is set to `Allow`, then no - matched parameters will be treated as successful validation by the binding. - If set to `Deny`, then no matched parameters will be subject to the - `failurePolicy` of the policy. - - Allowed values are `Allow` or `Deny` - - Required - type: string - selector: - description: |- - selector can be used to match multiple param objects based on their labels. - Supply selector: {} to match all resources of the ParamKind. - - If multiple params are found, they are all evaluated with the policy expressions - and the results are ANDed together. - - One of `name` or `selector` must be set, but `name` and `selector` are - mutually exclusive properties. If one is set, the other must be unset. - properties: - matchExpressions: - description: matchExpressions is a list of label - selector requirements. The requirements are - ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key that - the selector applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - type: object - x-kubernetes-map-type: atomic - variables: - description: |- - Variables contain definitions of variables that can be used in composition of other expressions. - Each variable is defined as a named CEL expression. - The variables defined here will be available under `variables` in other expressions of the policy. - items: - description: Variable is the definition of a variable - that is used for composition. A variable is defined - as a named expression. - properties: - expression: - description: |- - Expression is the expression that will be evaluated as the value of the variable. - The CEL expression has access to the same identifiers as the CEL expressions in Validation. - type: string - name: - description: |- - Name is the name of the variable. The name must be a valid CEL identifier and unique among all variables. - The variable can be accessed in other expressions through `variables` - For example, if name is "foo", the variable will be available as `variables.foo` - type: string - required: - - expression - - name - type: object - x-kubernetes-map-type: atomic - type: array - type: object - deny: - description: Deny defines conditions used to pass or fail - a validation rule. - properties: - conditions: - description: |- - Multiple conditions can be declared under an `any` or `all` statement. - See: https://kyverno.io/docs/writing-policies/validate/#deny-rules - properties: - all: - description: |- - AllConditions enable variable-based conditional rule execution. This is useful for - finer control of when an rule is applied. A condition can reference object data - using JMESPath notation. - Here, all of the conditions need to pass. - items: - properties: - key: - description: Key is the context entry (using - JMESPath) for conditional rule evaluation. - x-kubernetes-preserve-unknown-fields: true - message: - description: Message is an optional display - message - type: string - operator: - description: |- - Operator is the conditional operation to perform. Valid operators are: - Equals, NotEquals, In, AnyIn, AllIn, NotIn, AnyNotIn, AllNotIn, GreaterThanOrEquals, - GreaterThan, LessThanOrEquals, LessThan, DurationGreaterThanOrEquals, DurationGreaterThan, - DurationLessThanOrEquals, DurationLessThan - enum: - - Equals - - NotEquals - - AnyIn - - AllIn - - AnyNotIn - - AllNotIn - - GreaterThanOrEquals - - GreaterThan - - LessThanOrEquals - - LessThan - - DurationGreaterThanOrEquals - - DurationGreaterThan - - DurationLessThanOrEquals - - DurationLessThan - type: string - value: - description: |- - Value is the conditional value, or set of values. The values can be fixed set - or can be variables declared using JMESPath. - x-kubernetes-preserve-unknown-fields: true - type: object - type: array - any: - description: |- - AnyConditions enable variable-based conditional rule execution. This is useful for - finer control of when an rule is applied. A condition can reference object data - using JMESPath notation. - Here, at least one of the conditions need to pass. - items: - properties: - key: - description: Key is the context entry (using - JMESPath) for conditional rule evaluation. - x-kubernetes-preserve-unknown-fields: true - message: - description: Message is an optional display - message - type: string - operator: - description: |- - Operator is the conditional operation to perform. Valid operators are: - Equals, NotEquals, In, AnyIn, AllIn, NotIn, AnyNotIn, AllNotIn, GreaterThanOrEquals, - GreaterThan, LessThanOrEquals, LessThan, DurationGreaterThanOrEquals, DurationGreaterThan, - DurationLessThanOrEquals, DurationLessThan - enum: - - Equals - - NotEquals - - AnyIn - - AllIn - - AnyNotIn - - AllNotIn - - GreaterThanOrEquals - - GreaterThan - - LessThanOrEquals - - LessThan - - DurationGreaterThanOrEquals - - DurationGreaterThan - - DurationLessThanOrEquals - - DurationLessThan - type: string - value: - description: |- - Value is the conditional value, or set of values. The values can be fixed set - or can be variables declared using JMESPath. - x-kubernetes-preserve-unknown-fields: true - type: object - type: array - type: object - type: object - failureAction: - description: |- - FailureAction defines if a validation policy rule violation should block - the admission review request (Enforce), or allow (Audit) the admission review request - and report an error in a policy report. Optional. - Allowed values are Audit or Enforce. - enum: - - Audit - - Enforce - type: string - failureActionOverrides: - description: |- - FailureActionOverrides is a Cluster Policy attribute that specifies FailureAction - namespace-wise. It overrides FailureAction for the specified namespaces. - items: - properties: - action: - description: ValidationFailureAction defines the policy - validation failure action - enum: - - audit - - enforce - - Audit - - Enforce - type: string - namespaceSelector: - description: |- - A label selector is a label query over a set of resources. The result of matchLabels and - matchExpressions are ANDed. An empty label selector matches all objects. A null - label selector matches no objects. - properties: - matchExpressions: - description: matchExpressions is a list of label - selector requirements. The requirements are - ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key that the - selector applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - namespaces: - items: - type: string - type: array - type: object - type: array - foreach: - description: ForEach applies validate rules to a list of - sub-elements by creating a context for each entry in the - list and looping over it to apply the specified logic. - items: - description: ForEachValidation applies validate rules - to a list of sub-elements by creating a context for - each entry in the list and looping over it to apply - the specified logic. - properties: - anyPattern: - description: |- - AnyPattern specifies list of validation patterns. At least one of the patterns - must be satisfied for the validation rule to succeed. - x-kubernetes-preserve-unknown-fields: true - context: - description: Context defines variables and data sources - that can be used during rule execution. - items: - description: |- - ContextEntry adds variables and data sources to a rule Context. Either a - ConfigMap reference or a APILookup must be provided. - oneOf: - - required: - - configMap - - required: - - apiCall - - required: - - imageRegistry - - required: - - variable - - required: - - globalReference - properties: - apiCall: - description: |- - APICall is an HTTP request to the Kubernetes API server, or other JSON web service. - The data returned is stored in the context with the name for the context entry. - properties: - data: - description: |- - The data object specifies the POST data sent to the server. - Only applicable when the method field is set to POST. - items: - description: RequestData contains the - HTTP POST data - properties: - key: - description: Key is a unique identifier - for the data value - type: string - value: - description: Value is the data value - x-kubernetes-preserve-unknown-fields: true - required: - - key - - value - type: object - type: array - default: - description: |- - Default is an optional arbitrary JSON object that the context - value is set to, if the apiCall returns error. - x-kubernetes-preserve-unknown-fields: true - jmesPath: - description: |- - JMESPath is an optional JSON Match Expression that can be used to - transform the JSON response returned from the server. For example - a JMESPath of "items | length(@)" applied to the API server response - for the URLPath "/apis/apps/v1/deployments" will return the total count - of deployments across all namespaces. - type: string - method: - default: GET - description: Method is the HTTP request - type (GET or POST). Defaults to GET. - enum: - - GET - - POST - type: string - service: - description: |- - Service is an API call to a JSON web service. - This is used for non-Kubernetes API server calls. - It's mutually exclusive with the URLPath field. - properties: - caBundle: - description: |- - CABundle is a PEM encoded CA bundle which will be used to validate - the server certificate. - type: string - headers: - description: Headers is a list of optional - HTTP headers to be included in the - request. - items: - properties: - key: - description: Key is the header - key - type: string - value: - description: Value is the header - value - type: string - required: - - key - - value - type: object - type: array - url: - description: |- - URL is the JSON web service URL. A typical form is - `https://{service}.{namespace}:{port}/{path}`. - type: string - required: - - url - type: object - urlPath: - description: |- - URLPath is the URL path to be used in the HTTP GET or POST request to the - Kubernetes API server (e.g. "/api/v1/namespaces" or "/apis/apps/v1/deployments"). - The format required is the same format used by the `kubectl get --raw` command. - See https://kyverno.io/docs/writing-policies/external-data-sources/#variables-from-kubernetes-api-server-calls - for details. - It's mutually exclusive with the Service field. - type: string - type: object - configMap: - description: ConfigMap is the ConfigMap reference. - properties: - name: - description: Name is the ConfigMap name. - type: string - namespace: - description: Namespace is the ConfigMap - namespace. - type: string - required: - - name - type: object - globalReference: - description: GlobalContextEntryReference is - a reference to a cached global context entry. - properties: - jmesPath: - description: |- - JMESPath is an optional JSON Match Expression that can be used to - transform the JSON response returned from the server. For example - a JMESPath of "items | length(@)" applied to the API server response - for the URLPath "/apis/apps/v1/deployments" will return the total count - of deployments across all namespaces. - type: string - name: - description: Name of the global context - entry - type: string - required: - - name - type: object - imageRegistry: - description: |- - ImageRegistry defines requests to an OCI/Docker V2 registry to fetch image - details. - properties: - imageRegistryCredentials: - description: ImageRegistryCredentials provides - credentials that will be used for authentication - with registry - properties: - allowInsecureRegistry: - description: AllowInsecureRegistry allows - insecure access to a registry. - type: boolean - providers: - description: |- - Providers specifies a list of OCI Registry names, whose authentication providers are provided. - It can be of one of these values: default,google,azure,amazon,github. - items: - description: ImageRegistryCredentialsProvidersType - provides the list of credential - providers required. - enum: - - default - - amazon - - azure - - google - - github - type: string - type: array - secrets: - description: |- - Secrets specifies a list of secrets that are provided for credentials. - Secrets must live in the Kyverno namespace. - items: - type: string - type: array - type: object - jmesPath: - description: |- - JMESPath is an optional JSON Match Expression that can be used to - transform the ImageData struct returned as a result of processing - the image reference. - type: string - reference: - description: |- - Reference is image reference to a container image in the registry. - Example: ghcr.io/kyverno/kyverno:latest - type: string - required: - - reference - type: object - name: - description: Name is the variable name. - type: string - variable: - description: Variable defines an arbitrary JMESPath - context variable that can be defined inline. - properties: - default: - description: |- - Default is an optional arbitrary JSON object that the variable may take if the JMESPath - expression evaluates to nil - x-kubernetes-preserve-unknown-fields: true - jmesPath: - description: |- - JMESPath is an optional JMESPath Expression that can be used to - transform the variable. - type: string - value: - description: Value is any arbitrary JSON - object representable in YAML or JSON form. - x-kubernetes-preserve-unknown-fields: true - type: object - required: - - name - type: object - type: array - deny: - description: Deny defines conditions used to pass - or fail a validation rule. - properties: - conditions: - description: |- - Multiple conditions can be declared under an `any` or `all` statement. A direct list - of conditions (without `any` or `all` statements) is also supported for backwards compatibility - but will be deprecated in the next major release. - See: https://kyverno.io/docs/writing-policies/validate/#deny-rules - x-kubernetes-preserve-unknown-fields: true - type: object - elementScope: - description: |- - ElementScope specifies whether to use the current list element as the scope for validation. Defaults to "true" if not specified. - When set to "false", "request.object" is used as the validation scope within the foreach - block to allow referencing other elements in the subtree. - type: boolean - foreach: - description: Foreach declares a nested foreach iterator - x-kubernetes-preserve-unknown-fields: true - list: - description: |- - List specifies a JMESPath expression that results in one or more elements - to which the validation logic is applied. - type: string - pattern: - description: Pattern specifies an overlay-style pattern - used to check resources. - x-kubernetes-preserve-unknown-fields: true - preconditions: - description: |- - AnyAllConditions are used to determine if a policy rule should be applied by evaluating a - set of conditions. The declaration can contain nested `any` or `all` statements. - See: https://kyverno.io/docs/writing-policies/preconditions/ - properties: - all: - description: |- - AllConditions enable variable-based conditional rule execution. This is useful for - finer control of when an rule is applied. A condition can reference object data - using JMESPath notation. - Here, all of the conditions need to pass - items: - description: Condition defines variable-based - conditional criteria for rule execution. - properties: - key: - description: Key is the context entry (using - JMESPath) for conditional rule evaluation. - x-kubernetes-preserve-unknown-fields: true - message: - description: Message is an optional display - message - type: string - operator: - description: |- - Operator is the conditional operation to perform. Valid operators are: - Equals, NotEquals, In, AnyIn, AllIn, NotIn, AnyNotIn, AllNotIn, GreaterThanOrEquals, - GreaterThan, LessThanOrEquals, LessThan, DurationGreaterThanOrEquals, DurationGreaterThan, - DurationLessThanOrEquals, DurationLessThan - enum: - - Equals - - NotEquals - - In - - AnyIn - - AllIn - - NotIn - - AnyNotIn - - AllNotIn - - GreaterThanOrEquals - - GreaterThan - - LessThanOrEquals - - LessThan - - DurationGreaterThanOrEquals - - DurationGreaterThan - - DurationLessThanOrEquals - - DurationLessThan - type: string - value: - description: |- - Value is the conditional value, or set of values. The values can be fixed set - or can be variables declared using JMESPath. - x-kubernetes-preserve-unknown-fields: true - type: object - type: array - any: - description: |- - AnyConditions enable variable-based conditional rule execution. This is useful for - finer control of when an rule is applied. A condition can reference object data - using JMESPath notation. - Here, at least one of the conditions need to pass - items: - description: Condition defines variable-based - conditional criteria for rule execution. - properties: - key: - description: Key is the context entry (using - JMESPath) for conditional rule evaluation. - x-kubernetes-preserve-unknown-fields: true - message: - description: Message is an optional display - message - type: string - operator: - description: |- - Operator is the conditional operation to perform. Valid operators are: - Equals, NotEquals, In, AnyIn, AllIn, NotIn, AnyNotIn, AllNotIn, GreaterThanOrEquals, - GreaterThan, LessThanOrEquals, LessThan, DurationGreaterThanOrEquals, DurationGreaterThan, - DurationLessThanOrEquals, DurationLessThan - enum: - - Equals - - NotEquals - - In - - AnyIn - - AllIn - - NotIn - - AnyNotIn - - AllNotIn - - GreaterThanOrEquals - - GreaterThan - - LessThanOrEquals - - LessThan - - DurationGreaterThanOrEquals - - DurationGreaterThan - - DurationLessThanOrEquals - - DurationLessThan - type: string - value: - description: |- - Value is the conditional value, or set of values. The values can be fixed set - or can be variables declared using JMESPath. - x-kubernetes-preserve-unknown-fields: true - type: object - type: array - type: object - x-kubernetes-preserve-unknown-fields: true - type: object - type: array - manifests: - description: Manifest specifies conditions for manifest - verification - properties: - annotationDomain: - description: AnnotationDomain is custom domain of annotation - for message and signature. Default is "cosign.sigstore.dev". - type: string - attestors: - description: Attestors specified the required attestors - (i.e. authorities) - items: - properties: - count: - description: |- - Count specifies the required number of entries that must match. If the count is null, all entries must match - (a logical AND). If the count is 1, at least one entry must match (a logical OR). If the count contains a - value N, then N must be less than or equal to the size of entries, and at least N entries must match. - minimum: 1 - type: integer - entries: - description: |- - Entries contains the available attestors. An attestor can be a static key, - attributes for keyless verification, or a nested attestor declaration. - items: - properties: - annotations: - additionalProperties: - type: string - description: |- - Annotations are used for image verification. - Every specified key-value pair must exist and match in the verified payload. - The payload may contain other key-value pairs. - type: object - attestor: - description: Attestor is a nested set of - Attestor used to specify a more complex - set of match authorities. - x-kubernetes-preserve-unknown-fields: true - certificates: - description: Certificates specifies one - or more certificates. - properties: - cert: - description: Cert is an optional PEM-encoded - public certificate. - type: string - certChain: - description: CertChain is an optional - PEM encoded set of certificates used - to verify. - type: string - ctlog: - description: |- - CTLog (certificate timestamp log) provides a configuration for validation of Signed Certificate - Timestamps (SCTs). If the value is unset, the default behavior by Cosign is used. - properties: - ignoreSCT: - description: |- - IgnoreSCT defines whether to use the Signed Certificate Timestamp (SCT) log to check for a certificate - timestamp. Default is false. Set to true if this was opted out during signing. - type: boolean - pubkey: - description: PubKey, if set, is - used to validate SCTs against - a custom source. - type: string - tsaCertChain: - description: |- - TSACertChain, if set, is the PEM-encoded certificate chain file for the RFC3161 timestamp authority. Must - contain the root CA certificate. Optionally may contain intermediate CA certificates, and - may contain the leaf TSA certificate if not present in the timestamurce. - type: string - type: object - rekor: - description: |- - Rekor provides configuration for the Rekor transparency log service. If an empty object - is provided the public instance of Rekor (https://rekor.sigstore.dev) is used. - properties: - ignoreTlog: - description: IgnoreTlog skips transparency - log verification. - type: boolean - pubkey: - description: |- - RekorPubKey is an optional PEM-encoded public key to use for a custom Rekor. - If set, this will be used to validate transparency log signatures from a custom Rekor. - type: string - url: - description: URL is the address - of the transparency log. Defaults - to the public Rekor log instance - https://rekor.sigstore.dev. - type: string - type: object - type: object - keyless: - description: |- - Keyless is a set of attribute used to verify a Sigstore keyless attestor. - See https://github.com/sigstore/cosign/blob/main/KEYLESS.md. - properties: - additionalExtensions: - additionalProperties: - type: string - description: AdditionalExtensions are - certificate-extensions used for keyless - signing. - type: object - ctlog: - description: |- - CTLog (certificate timestamp log) provides a configuration for validation of Signed Certificate - Timestamps (SCTs). If the value is unset, the default behavior by Cosign is used. - properties: - ignoreSCT: - description: |- - IgnoreSCT defines whether to use the Signed Certificate Timestamp (SCT) log to check for a certificate - timestamp. Default is false. Set to true if this was opted out during signing. - type: boolean - pubkey: - description: PubKey, if set, is - used to validate SCTs against - a custom source. - type: string - tsaCertChain: - description: |- - TSACertChain, if set, is the PEM-encoded certificate chain file for the RFC3161 timestamp authority. Must - contain the root CA certificate. Optionally may contain intermediate CA certificates, and - may contain the leaf TSA certificate if not present in the timestamurce. - type: string - type: object - issuer: - description: Issuer is the certificate - issuer used for keyless signing. - type: string - issuerRegExp: - description: IssuerRegExp is the regular - expression to match certificate issuer - used for keyless signing. - type: string - rekor: - description: |- - Rekor provides configuration for the Rekor transparency log service. If an empty object - is provided the public instance of Rekor (https://rekor.sigstore.dev) is used. - properties: - ignoreTlog: - description: IgnoreTlog skips transparency - log verification. - type: boolean - pubkey: - description: |- - RekorPubKey is an optional PEM-encoded public key to use for a custom Rekor. - If set, this will be used to validate transparency log signatures from a custom Rekor. - type: string - url: - description: URL is the address - of the transparency log. Defaults - to the public Rekor log instance - https://rekor.sigstore.dev. - type: string - type: object - roots: - description: |- - Roots is an optional set of PEM encoded trusted root certificates. - If not provided, the system roots are used. - type: string - subject: - description: Subject is the verified - identity used for keyless signing, - for example the email address. - type: string - subjectRegExp: - description: SubjectRegExp is the regular - expression to match identity used - for keyless signing, for example the - email address. - type: string - type: object - keys: - description: Keys specifies one or more - public keys. - properties: - ctlog: - description: |- - CTLog (certificate timestamp log) provides a configuration for validation of Signed Certificate - Timestamps (SCTs). If the value is unset, the default behavior by Cosign is used. - properties: - ignoreSCT: - description: |- - IgnoreSCT defines whether to use the Signed Certificate Timestamp (SCT) log to check for a certificate - timestamp. Default is false. Set to true if this was opted out during signing. - type: boolean - pubkey: - description: PubKey, if set, is - used to validate SCTs against - a custom source. - type: string - tsaCertChain: - description: |- - TSACertChain, if set, is the PEM-encoded certificate chain file for the RFC3161 timestamp authority. Must - contain the root CA certificate. Optionally may contain intermediate CA certificates, and - may contain the leaf TSA certificate if not present in the timestamurce. - type: string - type: object - kms: - description: |- - KMS provides the URI to the public key stored in a Key Management System. See: - https://github.com/sigstore/cosign/blob/main/KMS.md - type: string - publicKeys: - description: |- - Keys is a set of X.509 public keys used to verify image signatures. The keys can be directly - specified or can be a variable reference to a key specified in a ConfigMap (see - https://kyverno.io/docs/writing-policies/variables/), or reference a standard Kubernetes Secret - elsewhere in the cluster by specifying it in the format "k8s:///". - The named Secret must specify a key `cosign.pub` containing the public key used for - verification, (see https://github.com/sigstore/cosign/blob/main/KMS.md#kubernetes-secret). - When multiple keys are specified each key is processed as a separate staticKey entry - (.attestors[*].entries.keys) within the set of attestors and the count is applied across the keys. - type: string - rekor: - description: |- - Rekor provides configuration for the Rekor transparency log service. If an empty object - is provided the public instance of Rekor (https://rekor.sigstore.dev) is used. - properties: - ignoreTlog: - description: IgnoreTlog skips transparency - log verification. - type: boolean - pubkey: - description: |- - RekorPubKey is an optional PEM-encoded public key to use for a custom Rekor. - If set, this will be used to validate transparency log signatures from a custom Rekor. - type: string - url: - description: URL is the address - of the transparency log. Defaults - to the public Rekor log instance - https://rekor.sigstore.dev. - type: string - type: object - secret: - description: Reference to a Secret resource - that contains a public key - properties: - name: - description: Name of the secret. - The provided secret must contain - a key named cosign.pub. - type: string - namespace: - description: Namespace name where - the Secret exists. - type: string - required: - - name - - namespace - type: object - signatureAlgorithm: - default: sha256 - description: Deprecated. Use attestor.signatureAlgorithm - instead. - type: string - type: object - repository: - description: |- - Repository is an optional alternate OCI repository to use for signatures and attestations that match this rule. - If specified Repository will override other OCI image repository locations for this Attestor. - type: string - signatureAlgorithm: - default: sha256 - description: Specify signature algorithm - for public keys. Supported values are - sha224, sha256, sha384 and sha512. - type: string - type: object - type: array - type: object - type: array - dryRun: - description: DryRun configuration - properties: - enable: - type: boolean - namespace: - type: string - type: object - ignoreFields: - description: Fields which will be ignored while comparing - manifests. - items: - properties: - fields: - items: - type: string - type: array - objects: - items: - properties: - group: - type: string - kind: - type: string - name: - type: string - namespace: - type: string - version: - type: string - type: object - type: array - type: object - type: array - repository: - description: |- - Repository is an optional alternate OCI repository to use for resource bundle reference. - The repository can be overridden per Attestor or Attestation. - type: string - type: object - message: - description: Message specifies a custom message to be displayed - on failure. - type: string - pattern: - description: Pattern specifies an overlay-style pattern - used to check resources. - x-kubernetes-preserve-unknown-fields: true - podSecurity: - description: |- - PodSecurity applies exemptions for Kubernetes Pod Security admission - by specifying exclusions for Pod Security Standards controls. - properties: - exclude: - description: Exclude specifies the Pod Security Standard - controls to be excluded. - items: - description: PodSecurityStandard specifies the Pod - Security Standard controls to be excluded. - properties: - controlName: - description: |- - ControlName specifies the name of the Pod Security Standard control. - See: https://kubernetes.io/docs/concepts/security/pod-security-standards/ - enum: - - HostProcess - - Host Namespaces - - Privileged Containers - - Capabilities - - HostPath Volumes - - Host Ports - - AppArmor - - SELinux - - /proc Mount Type - - Seccomp - - Sysctls - - Volume Types - - Privilege Escalation - - Running as Non-root - - Running as Non-root user - type: string - images: - description: |- - Images selects matching containers and applies the container level PSS. - Each image is the image name consisting of the registry address, repository, image, and tag. - Empty list matches no containers, PSS checks are applied at the pod level only. - Wildcards ('*' and '?') are allowed. See: https://kubernetes.io/docs/concepts/containers/images. - items: - type: string - type: array - restrictedField: - description: |- - RestrictedField selects the field for the given Pod Security Standard control. - When not set, all restricted fields for the control are selected. - type: string - values: - description: Values defines the allowed values - that can be excluded. - items: - type: string - type: array - required: - - controlName - type: object - type: array - level: - description: |- - Level defines the Pod Security Standard level to be applied to workloads. - Allowed values are privileged, baseline, and restricted. - enum: - - privileged - - baseline - - restricted - type: string - version: - description: |- - Version defines the Pod Security Standard versions that Kubernetes supports. - Allowed values are v1.19, v1.20, v1.21, v1.22, v1.23, v1.24, v1.25, v1.26, v1.27, v1.28, v1.29, latest. Defaults to latest. - enum: - - v1.19 - - v1.20 - - v1.21 - - v1.22 - - v1.23 - - v1.24 - - v1.25 - - v1.26 - - v1.27 - - v1.28 - - v1.29 - - latest - type: string - type: object - type: object - verifyImages: - description: VerifyImages is used to verify image signatures - and mutate them to add a digest - items: - description: |- - ImageVerification validates that images that match the specified pattern - are signed with the supplied public key. Once the image is verified it is - mutated to include the SHA digest retrieved during the registration. - properties: - attestations: - description: |- - Attestations are optional checks for signed in-toto Statements used to verify the image. - See https://github.com/in-toto/attestation. Kyverno fetches signed attestations from the - OCI registry and decodes them into a list of Statement declarations. - items: - description: |- - Attestation are checks for signed in-toto Statements that are used to verify the image. - See https://github.com/in-toto/attestation. Kyverno fetches signed attestations from the - OCI registry and decodes them into a list of Statements. - properties: - attestors: - description: Attestors specify the required attestors - (i.e. authorities). - items: - properties: - count: - description: |- - Count specifies the required number of entries that must match. If the count is null, all entries must match - (a logical AND). If the count is 1, at least one entry must match (a logical OR). If the count contains a - value N, then N must be less than or equal to the size of entries, and at least N entries must match. - minimum: 1 - type: integer - entries: - description: |- - Entries contains the available attestors. An attestor can be a static key, - attributes for keyless verification, or a nested attestor declaration. - items: - properties: - annotations: - additionalProperties: - type: string - description: |- - Annotations are used for image verification. - Every specified key-value pair must exist and match in the verified payload. - The payload may contain other key-value pairs. - type: object - attestor: - description: Attestor is a nested set - of Attestor used to specify a more - complex set of match authorities. - x-kubernetes-preserve-unknown-fields: true - certificates: - description: Certificates specifies - one or more certificates. - properties: - cert: - description: Cert is an optional - PEM-encoded public certificate. - type: string - certChain: - description: CertChain is an optional - PEM encoded set of certificates - used to verify. - type: string - ctlog: - description: |- - CTLog (certificate timestamp log) provides a configuration for validation of Signed Certificate - Timestamps (SCTs). If the value is unset, the default behavior by Cosign is used. - properties: - ignoreSCT: - description: |- - IgnoreSCT defines whether to use the Signed Certificate Timestamp (SCT) log to check for a certificate - timestamp. Default is false. Set to true if this was opted out during signing. - type: boolean - pubkey: - description: PubKey, if set, - is used to validate SCTs against - a custom source. - type: string - tsaCertChain: - description: |- - TSACertChain, if set, is the PEM-encoded certificate chain file for the RFC3161 timestamp authority. Must - contain the root CA certificate. Optionally may contain intermediate CA certificates, and - may contain the leaf TSA certificate if not present in the timestamurce. - type: string - type: object - rekor: - description: |- - Rekor provides configuration for the Rekor transparency log service. If an empty object - is provided the public instance of Rekor (https://rekor.sigstore.dev) is used. - properties: - ignoreTlog: - description: IgnoreTlog skips - transparency log verification. - type: boolean - pubkey: - description: |- - RekorPubKey is an optional PEM-encoded public key to use for a custom Rekor. - If set, this will be used to validate transparency log signatures from a custom Rekor. - type: string - url: - description: URL is the address - of the transparency log. Defaults - to the public Rekor log instance - https://rekor.sigstore.dev. - type: string - type: object - type: object - keyless: - description: |- - Keyless is a set of attribute used to verify a Sigstore keyless attestor. - See https://github.com/sigstore/cosign/blob/main/KEYLESS.md. - properties: - additionalExtensions: - additionalProperties: - type: string - description: AdditionalExtensions - are certificate-extensions used - for keyless signing. - type: object - ctlog: - description: |- - CTLog (certificate timestamp log) provides a configuration for validation of Signed Certificate - Timestamps (SCTs). If the value is unset, the default behavior by Cosign is used. - properties: - ignoreSCT: - description: |- - IgnoreSCT defines whether to use the Signed Certificate Timestamp (SCT) log to check for a certificate - timestamp. Default is false. Set to true if this was opted out during signing. - type: boolean - pubkey: - description: PubKey, if set, - is used to validate SCTs against - a custom source. - type: string - tsaCertChain: - description: |- - TSACertChain, if set, is the PEM-encoded certificate chain file for the RFC3161 timestamp authority. Must - contain the root CA certificate. Optionally may contain intermediate CA certificates, and - may contain the leaf TSA certificate if not present in the timestamurce. - type: string - type: object - issuer: - description: Issuer is the certificate - issuer used for keyless signing. - type: string - issuerRegExp: - description: IssuerRegExp is the - regular expression to match certificate - issuer used for keyless signing. - type: string - rekor: - description: |- - Rekor provides configuration for the Rekor transparency log service. If an empty object - is provided the public instance of Rekor (https://rekor.sigstore.dev) is used. - properties: - ignoreTlog: - description: IgnoreTlog skips - transparency log verification. - type: boolean - pubkey: - description: |- - RekorPubKey is an optional PEM-encoded public key to use for a custom Rekor. - If set, this will be used to validate transparency log signatures from a custom Rekor. - type: string - url: - description: URL is the address - of the transparency log. Defaults - to the public Rekor log instance - https://rekor.sigstore.dev. - type: string - type: object - roots: - description: |- - Roots is an optional set of PEM encoded trusted root certificates. - If not provided, the system roots are used. - type: string - subject: - description: Subject is the verified - identity used for keyless signing, - for example the email address. - type: string - subjectRegExp: - description: SubjectRegExp is the - regular expression to match identity - used for keyless signing, for - example the email address. - type: string - type: object - keys: - description: Keys specifies one or more - public keys. - properties: - ctlog: - description: |- - CTLog (certificate timestamp log) provides a configuration for validation of Signed Certificate - Timestamps (SCTs). If the value is unset, the default behavior by Cosign is used. - properties: - ignoreSCT: - description: |- - IgnoreSCT defines whether to use the Signed Certificate Timestamp (SCT) log to check for a certificate - timestamp. Default is false. Set to true if this was opted out during signing. - type: boolean - pubkey: - description: PubKey, if set, - is used to validate SCTs against - a custom source. - type: string - tsaCertChain: - description: |- - TSACertChain, if set, is the PEM-encoded certificate chain file for the RFC3161 timestamp authority. Must - contain the root CA certificate. Optionally may contain intermediate CA certificates, and - may contain the leaf TSA certificate if not present in the timestamurce. - type: string - type: object - kms: - description: |- - KMS provides the URI to the public key stored in a Key Management System. See: - https://github.com/sigstore/cosign/blob/main/KMS.md - type: string - publicKeys: - description: |- - Keys is a set of X.509 public keys used to verify image signatures. The keys can be directly - specified or can be a variable reference to a key specified in a ConfigMap (see - https://kyverno.io/docs/writing-policies/variables/), or reference a standard Kubernetes Secret - elsewhere in the cluster by specifying it in the format "k8s:///". - The named Secret must specify a key `cosign.pub` containing the public key used for - verification, (see https://github.com/sigstore/cosign/blob/main/KMS.md#kubernetes-secret). - When multiple keys are specified each key is processed as a separate staticKey entry - (.attestors[*].entries.keys) within the set of attestors and the count is applied across the keys. - type: string - rekor: - description: |- - Rekor provides configuration for the Rekor transparency log service. If an empty object - is provided the public instance of Rekor (https://rekor.sigstore.dev) is used. - properties: - ignoreTlog: - description: IgnoreTlog skips - transparency log verification. - type: boolean - pubkey: - description: |- - RekorPubKey is an optional PEM-encoded public key to use for a custom Rekor. - If set, this will be used to validate transparency log signatures from a custom Rekor. - type: string - url: - description: URL is the address - of the transparency log. Defaults - to the public Rekor log instance - https://rekor.sigstore.dev. - type: string - type: object - secret: - description: Reference to a Secret - resource that contains a public - key - properties: - name: - description: Name of the secret. - The provided secret must contain - a key named cosign.pub. - type: string - namespace: - description: Namespace name - where the Secret exists. - type: string - required: - - name - - namespace - type: object - signatureAlgorithm: - default: sha256 - description: Deprecated. Use attestor.signatureAlgorithm - instead. - type: string - type: object - repository: - description: |- - Repository is an optional alternate OCI repository to use for signatures and attestations that match this rule. - If specified Repository will override other OCI image repository locations for this Attestor. - type: string - signatureAlgorithm: - default: sha256 - description: Specify signature algorithm - for public keys. Supported values - are sha224, sha256, sha384 and sha512. - type: string - type: object - type: array - type: object - type: array - conditions: - description: |- - Conditions are used to verify attributes within a Predicate. If no Conditions are specified - the attestation check is satisfied as long there are predicates that match the predicate type. - items: - description: |- - AnyAllConditions consists of conditions wrapped denoting a logical criteria to be fulfilled. - AnyConditions get fulfilled when at least one of its sub-conditions passes. - AllConditions get fulfilled only when all of its sub-conditions pass. - properties: - all: - description: |- - AllConditions enable variable-based conditional rule execution. This is useful for - finer control of when an rule is applied. A condition can reference object data - using JMESPath notation. - Here, all of the conditions need to pass - items: - description: Condition defines variable-based - conditional criteria for rule execution. - properties: - key: - description: Key is the context entry - (using JMESPath) for conditional rule - evaluation. - x-kubernetes-preserve-unknown-fields: true - message: - description: Message is an optional - display message - type: string - operator: - description: |- - Operator is the conditional operation to perform. Valid operators are: - Equals, NotEquals, In, AnyIn, AllIn, NotIn, AnyNotIn, AllNotIn, GreaterThanOrEquals, - GreaterThan, LessThanOrEquals, LessThan, DurationGreaterThanOrEquals, DurationGreaterThan, - DurationLessThanOrEquals, DurationLessThan - enum: - - Equals - - NotEquals - - In - - AnyIn - - AllIn - - NotIn - - AnyNotIn - - AllNotIn - - GreaterThanOrEquals - - GreaterThan - - LessThanOrEquals - - LessThan - - DurationGreaterThanOrEquals - - DurationGreaterThan - - DurationLessThanOrEquals - - DurationLessThan - type: string - value: - description: |- - Value is the conditional value, or set of values. The values can be fixed set - or can be variables declared using JMESPath. - x-kubernetes-preserve-unknown-fields: true - type: object - type: array - any: - description: |- - AnyConditions enable variable-based conditional rule execution. This is useful for - finer control of when an rule is applied. A condition can reference object data - using JMESPath notation. - Here, at least one of the conditions need to pass - items: - description: Condition defines variable-based - conditional criteria for rule execution. - properties: - key: - description: Key is the context entry - (using JMESPath) for conditional rule - evaluation. - x-kubernetes-preserve-unknown-fields: true - message: - description: Message is an optional - display message - type: string - operator: - description: |- - Operator is the conditional operation to perform. Valid operators are: - Equals, NotEquals, In, AnyIn, AllIn, NotIn, AnyNotIn, AllNotIn, GreaterThanOrEquals, - GreaterThan, LessThanOrEquals, LessThan, DurationGreaterThanOrEquals, DurationGreaterThan, - DurationLessThanOrEquals, DurationLessThan - enum: - - Equals - - NotEquals - - In - - AnyIn - - AllIn - - NotIn - - AnyNotIn - - AllNotIn - - GreaterThanOrEquals - - GreaterThan - - LessThanOrEquals - - LessThan - - DurationGreaterThanOrEquals - - DurationGreaterThan - - DurationLessThanOrEquals - - DurationLessThan - type: string - value: - description: |- - Value is the conditional value, or set of values. The values can be fixed set - or can be variables declared using JMESPath. - x-kubernetes-preserve-unknown-fields: true - type: object - type: array - type: object - type: array - name: - description: Name is the variable name. - type: string - predicateType: - description: Deprecated in favour of 'Type', to - be removed soon - type: string - type: - description: Type defines the type of attestation - contained within the Statement. - type: string - type: object - type: array - attestors: - description: Attestors specified the required attestors - (i.e. authorities) - items: - properties: - count: - description: |- - Count specifies the required number of entries that must match. If the count is null, all entries must match - (a logical AND). If the count is 1, at least one entry must match (a logical OR). If the count contains a - value N, then N must be less than or equal to the size of entries, and at least N entries must match. - minimum: 1 - type: integer - entries: - description: |- - Entries contains the available attestors. An attestor can be a static key, - attributes for keyless verification, or a nested attestor declaration. - items: - properties: - annotations: - additionalProperties: - type: string - description: |- - Annotations are used for image verification. - Every specified key-value pair must exist and match in the verified payload. - The payload may contain other key-value pairs. - type: object - attestor: - description: Attestor is a nested set of Attestor - used to specify a more complex set of match - authorities. - x-kubernetes-preserve-unknown-fields: true - certificates: - description: Certificates specifies one or - more certificates. - properties: - cert: - description: Cert is an optional PEM-encoded - public certificate. - type: string - certChain: - description: CertChain is an optional - PEM encoded set of certificates used - to verify. - type: string - ctlog: - description: |- - CTLog (certificate timestamp log) provides a configuration for validation of Signed Certificate - Timestamps (SCTs). If the value is unset, the default behavior by Cosign is used. - properties: - ignoreSCT: - description: |- - IgnoreSCT defines whether to use the Signed Certificate Timestamp (SCT) log to check for a certificate - timestamp. Default is false. Set to true if this was opted out during signing. - type: boolean - pubkey: - description: PubKey, if set, is used - to validate SCTs against a custom - source. - type: string - tsaCertChain: - description: |- - TSACertChain, if set, is the PEM-encoded certificate chain file for the RFC3161 timestamp authority. Must - contain the root CA certificate. Optionally may contain intermediate CA certificates, and - may contain the leaf TSA certificate if not present in the timestamurce. - type: string - type: object - rekor: - description: |- - Rekor provides configuration for the Rekor transparency log service. If an empty object - is provided the public instance of Rekor (https://rekor.sigstore.dev) is used. - properties: - ignoreTlog: - description: IgnoreTlog skips transparency - log verification. - type: boolean - pubkey: - description: |- - RekorPubKey is an optional PEM-encoded public key to use for a custom Rekor. - If set, this will be used to validate transparency log signatures from a custom Rekor. - type: string - url: - description: URL is the address of - the transparency log. Defaults to - the public Rekor log instance https://rekor.sigstore.dev. - type: string - type: object - type: object - keyless: - description: |- - Keyless is a set of attribute used to verify a Sigstore keyless attestor. - See https://github.com/sigstore/cosign/blob/main/KEYLESS.md. - properties: - additionalExtensions: - additionalProperties: - type: string - description: AdditionalExtensions are - certificate-extensions used for keyless - signing. - type: object - ctlog: - description: |- - CTLog (certificate timestamp log) provides a configuration for validation of Signed Certificate - Timestamps (SCTs). If the value is unset, the default behavior by Cosign is used. - properties: - ignoreSCT: - description: |- - IgnoreSCT defines whether to use the Signed Certificate Timestamp (SCT) log to check for a certificate - timestamp. Default is false. Set to true if this was opted out during signing. - type: boolean - pubkey: - description: PubKey, if set, is used - to validate SCTs against a custom - source. - type: string - tsaCertChain: - description: |- - TSACertChain, if set, is the PEM-encoded certificate chain file for the RFC3161 timestamp authority. Must - contain the root CA certificate. Optionally may contain intermediate CA certificates, and - may contain the leaf TSA certificate if not present in the timestamurce. - type: string - type: object - issuer: - description: Issuer is the certificate - issuer used for keyless signing. - type: string - issuerRegExp: - description: IssuerRegExp is the regular - expression to match certificate issuer - used for keyless signing. - type: string - rekor: - description: |- - Rekor provides configuration for the Rekor transparency log service. If an empty object - is provided the public instance of Rekor (https://rekor.sigstore.dev) is used. - properties: - ignoreTlog: - description: IgnoreTlog skips transparency - log verification. - type: boolean - pubkey: - description: |- - RekorPubKey is an optional PEM-encoded public key to use for a custom Rekor. - If set, this will be used to validate transparency log signatures from a custom Rekor. - type: string - url: - description: URL is the address of - the transparency log. Defaults to - the public Rekor log instance https://rekor.sigstore.dev. - type: string - type: object - roots: - description: |- - Roots is an optional set of PEM encoded trusted root certificates. - If not provided, the system roots are used. - type: string - subject: - description: Subject is the verified identity - used for keyless signing, for example - the email address. - type: string - subjectRegExp: - description: SubjectRegExp is the regular - expression to match identity used for - keyless signing, for example the email - address. - type: string - type: object - keys: - description: Keys specifies one or more public - keys. - properties: - ctlog: - description: |- - CTLog (certificate timestamp log) provides a configuration for validation of Signed Certificate - Timestamps (SCTs). If the value is unset, the default behavior by Cosign is used. - properties: - ignoreSCT: - description: |- - IgnoreSCT defines whether to use the Signed Certificate Timestamp (SCT) log to check for a certificate - timestamp. Default is false. Set to true if this was opted out during signing. - type: boolean - pubkey: - description: PubKey, if set, is used - to validate SCTs against a custom - source. - type: string - tsaCertChain: - description: |- - TSACertChain, if set, is the PEM-encoded certificate chain file for the RFC3161 timestamp authority. Must - contain the root CA certificate. Optionally may contain intermediate CA certificates, and - may contain the leaf TSA certificate if not present in the timestamurce. - type: string - type: object - kms: - description: |- - KMS provides the URI to the public key stored in a Key Management System. See: - https://github.com/sigstore/cosign/blob/main/KMS.md - type: string - publicKeys: - description: |- - Keys is a set of X.509 public keys used to verify image signatures. The keys can be directly - specified or can be a variable reference to a key specified in a ConfigMap (see - https://kyverno.io/docs/writing-policies/variables/), or reference a standard Kubernetes Secret - elsewhere in the cluster by specifying it in the format "k8s:///". - The named Secret must specify a key `cosign.pub` containing the public key used for - verification, (see https://github.com/sigstore/cosign/blob/main/KMS.md#kubernetes-secret). - When multiple keys are specified each key is processed as a separate staticKey entry - (.attestors[*].entries.keys) within the set of attestors and the count is applied across the keys. - type: string - rekor: - description: |- - Rekor provides configuration for the Rekor transparency log service. If an empty object - is provided the public instance of Rekor (https://rekor.sigstore.dev) is used. - properties: - ignoreTlog: - description: IgnoreTlog skips transparency - log verification. - type: boolean - pubkey: - description: |- - RekorPubKey is an optional PEM-encoded public key to use for a custom Rekor. - If set, this will be used to validate transparency log signatures from a custom Rekor. - type: string - url: - description: URL is the address of - the transparency log. Defaults to - the public Rekor log instance https://rekor.sigstore.dev. - type: string - type: object - secret: - description: Reference to a Secret resource - that contains a public key - properties: - name: - description: Name of the secret. The - provided secret must contain a key - named cosign.pub. - type: string - namespace: - description: Namespace name where - the Secret exists. - type: string - required: - - name - - namespace - type: object - signatureAlgorithm: - default: sha256 - description: Deprecated. Use attestor.signatureAlgorithm - instead. - type: string - type: object - repository: - description: |- - Repository is an optional alternate OCI repository to use for signatures and attestations that match this rule. - If specified Repository will override other OCI image repository locations for this Attestor. - type: string - signatureAlgorithm: - default: sha256 - description: Specify signature algorithm for - public keys. Supported values are sha224, - sha256, sha384 and sha512. - type: string - type: object - type: array - type: object - type: array - failureAction: - description: Allowed values are Audit or Enforce. - enum: - - Audit - - Enforce - type: string - imageReferences: - description: |- - ImageReferences is a list of matching image reference patterns. At least one pattern in the - list must match the image for the rule to apply. Each image reference consists of a registry - address (defaults to docker.io), repository, image, and tag (defaults to latest). - Wildcards ('*' and '?') are allowed. See: https://kubernetes.io/docs/concepts/containers/images. - items: - type: string - type: array - imageRegistryCredentials: - description: ImageRegistryCredentials provides credentials - that will be used for authentication with registry - properties: - allowInsecureRegistry: - description: AllowInsecureRegistry allows insecure - access to a registry. - type: boolean - providers: - description: |- - Providers specifies a list of OCI Registry names, whose authentication providers are provided. - It can be of one of these values: default,google,azure,amazon,github. - items: - description: ImageRegistryCredentialsProvidersType - provides the list of credential providers required. - enum: - - default - - amazon - - azure - - google - - github - type: string - type: array - secrets: - description: |- - Secrets specifies a list of secrets that are provided for credentials. - Secrets must live in the Kyverno namespace. - items: - type: string - type: array - type: object - mutateDigest: - default: true - description: |- - MutateDigest enables replacement of image tags with digests. - Defaults to true. - type: boolean - repository: - description: |- - Repository is an optional alternate OCI repository to use for image signatures and attestations that match this rule. - If specified Repository will override the default OCI image repository configured for the installation. - The repository can also be overridden per Attestor or Attestation. - type: string - required: - default: true - description: Required validates that images are verified - i.e. have matched passed a signature or attestation - check. - type: boolean - skipImageReferences: - description: |- - SkipImageReferences is a list of matching image reference patterns that should be skipped. - At least one pattern in the list must match the image for the rule to be skipped. Each image reference - consists of a registry address (defaults to docker.io), repository, image, and tag (defaults to latest). - Wildcards ('*' and '?') are allowed. See: https://kubernetes.io/docs/concepts/containers/images. - items: - type: string - type: array - type: - description: |- - Type specifies the method of signature validation. The allowed options - are Cosign and Notary. By default Cosign is used if a type is not specified. - enum: - - Cosign - - SigstoreBundle - - Notary - type: string - useCache: - default: true - description: UseCache enables caching of image verify - responses for this rule - type: boolean - validate: - description: |- - Validation checks conditions across multiple image - verification attestations or context entries - properties: - deny: - description: Deny defines conditions used to pass - or fail a validation rule. - properties: - conditions: - description: |- - Multiple conditions can be declared under an `any` or `all` statement. A direct list - of conditions (without `any` or `all` statements) is also supported for backwards compatibility - but will be deprecated in the next major release. - See: https://kyverno.io/docs/writing-policies/validate/#deny-rules - x-kubernetes-preserve-unknown-fields: true - type: object - message: - description: Message specifies a custom message to - be displayed on failure. - type: string - type: object - verifyDigest: - default: true - description: VerifyDigest validates that images have a - digest. - type: boolean - type: object - type: array - required: - - match - - name - type: object - type: array - schemaValidation: - description: Deprecated. - type: boolean - useServerSideApply: - description: |- - UseServerSideApply controls whether to use server-side apply for generate rules - If is set to "true" create & update for generate rules will use apply instead of create/update. - Defaults to "false" if not specified. - type: boolean - validationFailureAction: - default: Audit - description: Deprecated, use validationFailureAction under the validate - rule instead. - enum: - - audit - - enforce - - Audit - - Enforce - type: string - validationFailureActionOverrides: - description: Deprecated, use validationFailureActionOverrides under - the validate rule instead. - items: - properties: - action: - description: ValidationFailureAction defines the policy validation - failure action - enum: - - audit - - enforce - - Audit - - Enforce - type: string - namespaceSelector: - description: |- - A label selector is a label query over a set of resources. The result of matchLabels and - matchExpressions are ANDed. An empty label selector matches all objects. A null - label selector matches no objects. - properties: - matchExpressions: - description: matchExpressions is a list of label selector - requirements. The requirements are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key that the selector - applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - namespaces: - items: - type: string - type: array - type: object - type: array - webhookConfiguration: - description: WebhookConfiguration specifies the custom configuration - for Kubernetes admission webhookconfiguration. - properties: - failurePolicy: - description: |- - FailurePolicy defines how unexpected policy errors and webhook response timeout errors are handled. - Rules within the same policy share the same failure behavior. - This field should not be accessed directly, instead `GetFailurePolicy()` should be used. - Allowed values are Ignore or Fail. Defaults to Fail. - enum: - - Ignore - - Fail - type: string - matchConditions: - description: |- - MatchCondition configures admission webhook matchConditions. - Requires Kubernetes 1.27 or later. - items: - description: MatchCondition represents a condition which must - by fulfilled for a request to be sent to a webhook. - properties: - expression: - description: |- - Expression represents the expression which will be evaluated by CEL. Must evaluate to bool. - CEL expressions have access to the contents of the AdmissionRequest and Authorizer, organized into CEL variables: - - 'object' - The object from the incoming request. The value is null for DELETE requests. - 'oldObject' - The existing object. The value is null for CREATE requests. - 'request' - Attributes of the admission request(/pkg/apis/admission/types.go#AdmissionRequest). - 'authorizer' - A CEL Authorizer. May be used to perform authorization checks for the principal (user or service account) of the request. - See https://pkg.go.dev/k8s.io/apiserver/pkg/cel/library#Authz - 'authorizer.requestResource' - A CEL ResourceCheck constructed from the 'authorizer' and configured with the - request resource. - Documentation on CEL: https://kubernetes.io/docs/reference/using-api/cel/ - - Required. - type: string - name: - description: |- - Name is an identifier for this match condition, used for strategic merging of MatchConditions, - as well as providing an identifier for logging purposes. A good name should be descriptive of - the associated expression. - Name must be a qualified name consisting of alphanumeric characters, '-', '_' or '.', and - must start and end with an alphanumeric character (e.g. 'MyName', or 'my.name', or - '123-abc', regex used for validation is '([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9]') with an - optional DNS subdomain prefix and '/' (e.g. 'example.com/MyName') - - Required. - type: string - required: - - expression - - name - type: object - type: array - timeoutSeconds: - description: |- - TimeoutSeconds specifies the maximum time in seconds allowed to apply this policy. - After the configured time expires, the admission request may fail, or may simply ignore the policy results, - based on the failure policy. The default timeout is 10s, the value must be between 1 and 30 seconds. - format: int32 - type: integer - type: object - webhookTimeoutSeconds: - description: Deprecated, use webhookTimeoutSeconds under webhookConfiguration - instead. - format: int32 - type: integer - type: object - status: - description: Status contains policy runtime data. - properties: - autogen: - description: AutogenStatus contains autogen status information. - properties: - rules: - description: Rules is a list of Rule instances. It contains auto - generated rules added for pod controllers - items: - description: |- - Rule defines a validation, mutation, or generation control for matching resources. - Each rules contains a match declaration to select resources, and an optional exclude - declaration to specify which resources to exclude. - properties: - celPreconditions: - description: |- - CELPreconditions are used to determine if a policy rule should be applied by evaluating a - set of CEL conditions. It can only be used with the validate.cel subrule - items: - description: MatchCondition represents a condition which - must by fulfilled for a request to be sent to a webhook. - properties: - expression: - description: |- - Expression represents the expression which will be evaluated by CEL. Must evaluate to bool. - CEL expressions have access to the contents of the AdmissionRequest and Authorizer, organized into CEL variables: - - 'object' - The object from the incoming request. The value is null for DELETE requests. - 'oldObject' - The existing object. The value is null for CREATE requests. - 'request' - Attributes of the admission request(/pkg/apis/admission/types.go#AdmissionRequest). - 'authorizer' - A CEL Authorizer. May be used to perform authorization checks for the principal (user or service account) of the request. - See https://pkg.go.dev/k8s.io/apiserver/pkg/cel/library#Authz - 'authorizer.requestResource' - A CEL ResourceCheck constructed from the 'authorizer' and configured with the - request resource. - Documentation on CEL: https://kubernetes.io/docs/reference/using-api/cel/ - - Required. - type: string - name: - description: |- - Name is an identifier for this match condition, used for strategic merging of MatchConditions, - as well as providing an identifier for logging purposes. A good name should be descriptive of - the associated expression. - Name must be a qualified name consisting of alphanumeric characters, '-', '_' or '.', and - must start and end with an alphanumeric character (e.g. 'MyName', or 'my.name', or - '123-abc', regex used for validation is '([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9]') with an - optional DNS subdomain prefix and '/' (e.g. 'example.com/MyName') - - Required. - type: string - required: - - expression - - name - type: object - type: array - context: - description: Context defines variables and data sources - that can be used during rule execution. - items: - description: |- - ContextEntry adds variables and data sources to a rule Context. Either a - ConfigMap reference or a APILookup must be provided. - oneOf: - - required: - - configMap - - required: - - apiCall - - required: - - imageRegistry - - required: - - variable - - required: - - globalReference - properties: - apiCall: - description: |- - APICall is an HTTP request to the Kubernetes API server, or other JSON web service. - The data returned is stored in the context with the name for the context entry. - properties: - data: - description: |- - The data object specifies the POST data sent to the server. - Only applicable when the method field is set to POST. - items: - description: RequestData contains the HTTP POST - data - properties: - key: - description: Key is a unique identifier - for the data value - type: string - value: - description: Value is the data value - x-kubernetes-preserve-unknown-fields: true - required: - - key - - value - type: object - type: array - default: - description: |- - Default is an optional arbitrary JSON object that the context - value is set to, if the apiCall returns error. - x-kubernetes-preserve-unknown-fields: true - jmesPath: - description: |- - JMESPath is an optional JSON Match Expression that can be used to - transform the JSON response returned from the server. For example - a JMESPath of "items | length(@)" applied to the API server response - for the URLPath "/apis/apps/v1/deployments" will return the total count - of deployments across all namespaces. - type: string - method: - default: GET - description: Method is the HTTP request type (GET - or POST). Defaults to GET. - enum: - - GET - - POST - type: string - service: - description: |- - Service is an API call to a JSON web service. - This is used for non-Kubernetes API server calls. - It's mutually exclusive with the URLPath field. - properties: - caBundle: - description: |- - CABundle is a PEM encoded CA bundle which will be used to validate - the server certificate. - type: string - headers: - description: Headers is a list of optional - HTTP headers to be included in the request. - items: - properties: - key: - description: Key is the header key - type: string - value: - description: Value is the header value - type: string - required: - - key - - value - type: object - type: array - url: - description: |- - URL is the JSON web service URL. A typical form is - `https://{service}.{namespace}:{port}/{path}`. - type: string - required: - - url - type: object - urlPath: - description: |- - URLPath is the URL path to be used in the HTTP GET or POST request to the - Kubernetes API server (e.g. "/api/v1/namespaces" or "/apis/apps/v1/deployments"). - The format required is the same format used by the `kubectl get --raw` command. - See https://kyverno.io/docs/writing-policies/external-data-sources/#variables-from-kubernetes-api-server-calls - for details. - It's mutually exclusive with the Service field. - type: string - type: object - configMap: - description: ConfigMap is the ConfigMap reference. - properties: - name: - description: Name is the ConfigMap name. - type: string - namespace: - description: Namespace is the ConfigMap namespace. - type: string - required: - - name - type: object - globalReference: - description: GlobalContextEntryReference is a reference - to a cached global context entry. - properties: - jmesPath: - description: |- - JMESPath is an optional JSON Match Expression that can be used to - transform the JSON response returned from the server. For example - a JMESPath of "items | length(@)" applied to the API server response - for the URLPath "/apis/apps/v1/deployments" will return the total count - of deployments across all namespaces. - type: string - name: - description: Name of the global context entry - type: string - required: - - name - type: object - imageRegistry: - description: |- - ImageRegistry defines requests to an OCI/Docker V2 registry to fetch image - details. - properties: - imageRegistryCredentials: - description: ImageRegistryCredentials provides - credentials that will be used for authentication - with registry - properties: - allowInsecureRegistry: - description: AllowInsecureRegistry allows - insecure access to a registry. - type: boolean - providers: - description: |- - Providers specifies a list of OCI Registry names, whose authentication providers are provided. - It can be of one of these values: default,google,azure,amazon,github. - items: - description: ImageRegistryCredentialsProvidersType - provides the list of credential providers - required. - enum: - - default - - amazon - - azure - - google - - github - type: string - type: array - secrets: - description: |- - Secrets specifies a list of secrets that are provided for credentials. - Secrets must live in the Kyverno namespace. - items: - type: string - type: array - type: object - jmesPath: - description: |- - JMESPath is an optional JSON Match Expression that can be used to - transform the ImageData struct returned as a result of processing - the image reference. - type: string - reference: - description: |- - Reference is image reference to a container image in the registry. - Example: ghcr.io/kyverno/kyverno:latest - type: string - required: - - reference - type: object - name: - description: Name is the variable name. - type: string - variable: - description: Variable defines an arbitrary JMESPath - context variable that can be defined inline. - properties: - default: - description: |- - Default is an optional arbitrary JSON object that the variable may take if the JMESPath - expression evaluates to nil - x-kubernetes-preserve-unknown-fields: true - jmesPath: - description: |- - JMESPath is an optional JMESPath Expression that can be used to - transform the variable. - type: string - value: - description: Value is any arbitrary JSON object - representable in YAML or JSON form. - x-kubernetes-preserve-unknown-fields: true - type: object - required: - - name - type: object - type: array - exclude: - description: |- - ExcludeResources defines when this policy rule should not be applied. The exclude - criteria can include resource information (e.g. kind, name, namespace, labels) - and admission review request information like the name or role. - not: - required: - - any - - all - properties: - all: - description: All allows specifying resources which will - be ANDed - items: - description: ResourceFilter allow users to "AND" or - "OR" between resources - properties: - clusterRoles: - description: ClusterRoles is the list of cluster-wide - role names for the user. - items: - type: string - type: array - resources: - description: ResourceDescription contains information - about the resource being created or modified. - not: - required: - - name - - names - properties: - annotations: - additionalProperties: - type: string - description: |- - Annotations is a map of annotations (key-value pairs of type string). Annotation keys - and values support the wildcard characters "*" (matches zero or many characters) and - "?" (matches at least one character). - type: object - kinds: - description: Kinds is a list of resource kinds. - items: - type: string - type: array - name: - description: |- - Name is the name of the resource. The name supports wildcard characters - "*" (matches zero or many characters) and "?" (at least one character). - NOTE: "Name" is being deprecated in favor of "Names". - type: string - names: - description: |- - Names are the names of the resources. Each name supports wildcard characters - "*" (matches zero or many characters) and "?" (at least one character). - items: - type: string - type: array - namespaceSelector: - description: |- - NamespaceSelector is a label selector for the resource namespace. Label keys and values - in `matchLabels` support the wildcard characters `*` (matches zero or many characters) - and `?` (matches one character).Wildcards allows writing label selectors like - ["storage.k8s.io/*": "*"]. Note that using ["*" : "*"] matches any key and value but - does not match an empty label set. - properties: - matchExpressions: - description: matchExpressions is a list - of label selector requirements. The - requirements are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key - that the selector applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - namespaces: - description: |- - Namespaces is a list of namespaces names. Each name supports wildcard characters - "*" (matches zero or many characters) and "?" (at least one character). - items: - type: string - type: array - operations: - description: Operations can contain values - ["CREATE, "UPDATE", "CONNECT", "DELETE"], - which are used to match a specific action. - items: - description: AdmissionOperation can have - one of the values CREATE, UPDATE, CONNECT, - DELETE, which are used to match a specific - action. - enum: - - CREATE - - CONNECT - - UPDATE - - DELETE - type: string - type: array - selector: - description: |- - Selector is a label selector. Label keys and values in `matchLabels` support the wildcard - characters `*` (matches zero or many characters) and `?` (matches one character). - Wildcards allows writing label selectors like ["storage.k8s.io/*": "*"]. Note that - using ["*" : "*"] matches any key and value but does not match an empty label set. - properties: - matchExpressions: - description: matchExpressions is a list - of label selector requirements. The - requirements are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key - that the selector applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - type: object - roles: - description: Roles is the list of namespaced role - names for the user. - items: - type: string - type: array - subjects: - description: Subjects is the list of subject names - like users, user groups, and service accounts. - items: - description: |- - Subject contains a reference to the object or user identities a role binding applies to. This can either hold a direct API object reference, - or a value for non-objects such as user and group names. - properties: - apiGroup: - description: |- - APIGroup holds the API group of the referenced subject. - Defaults to "" for ServiceAccount subjects. - Defaults to "rbac.authorization.k8s.io" for User and Group subjects. - type: string - kind: - description: |- - Kind of object being referenced. Values defined by this API group are "User", "Group", and "ServiceAccount". - If the Authorizer does not recognized the kind value, the Authorizer should report an error. - type: string - name: - description: Name of the object being referenced. - type: string - namespace: - description: |- - Namespace of the referenced object. If the object kind is non-namespace, such as "User" or "Group", and this value is not empty - the Authorizer should report an error. - type: string - required: - - kind - - name - type: object - x-kubernetes-map-type: atomic - type: array - type: object - type: array - any: - description: Any allows specifying resources which will - be ORed - items: - description: ResourceFilter allow users to "AND" or - "OR" between resources - properties: - clusterRoles: - description: ClusterRoles is the list of cluster-wide - role names for the user. - items: - type: string - type: array - resources: - description: ResourceDescription contains information - about the resource being created or modified. - not: - required: - - name - - names - properties: - annotations: - additionalProperties: - type: string - description: |- - Annotations is a map of annotations (key-value pairs of type string). Annotation keys - and values support the wildcard characters "*" (matches zero or many characters) and - "?" (matches at least one character). - type: object - kinds: - description: Kinds is a list of resource kinds. - items: - type: string - type: array - name: - description: |- - Name is the name of the resource. The name supports wildcard characters - "*" (matches zero or many characters) and "?" (at least one character). - NOTE: "Name" is being deprecated in favor of "Names". - type: string - names: - description: |- - Names are the names of the resources. Each name supports wildcard characters - "*" (matches zero or many characters) and "?" (at least one character). - items: - type: string - type: array - namespaceSelector: - description: |- - NamespaceSelector is a label selector for the resource namespace. Label keys and values - in `matchLabels` support the wildcard characters `*` (matches zero or many characters) - and `?` (matches one character).Wildcards allows writing label selectors like - ["storage.k8s.io/*": "*"]. Note that using ["*" : "*"] matches any key and value but - does not match an empty label set. - properties: - matchExpressions: - description: matchExpressions is a list - of label selector requirements. The - requirements are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key - that the selector applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - namespaces: - description: |- - Namespaces is a list of namespaces names. Each name supports wildcard characters - "*" (matches zero or many characters) and "?" (at least one character). - items: - type: string - type: array - operations: - description: Operations can contain values - ["CREATE, "UPDATE", "CONNECT", "DELETE"], - which are used to match a specific action. - items: - description: AdmissionOperation can have - one of the values CREATE, UPDATE, CONNECT, - DELETE, which are used to match a specific - action. - enum: - - CREATE - - CONNECT - - UPDATE - - DELETE - type: string - type: array - selector: - description: |- - Selector is a label selector. Label keys and values in `matchLabels` support the wildcard - characters `*` (matches zero or many characters) and `?` (matches one character). - Wildcards allows writing label selectors like ["storage.k8s.io/*": "*"]. Note that - using ["*" : "*"] matches any key and value but does not match an empty label set. - properties: - matchExpressions: - description: matchExpressions is a list - of label selector requirements. The - requirements are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key - that the selector applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - type: object - roles: - description: Roles is the list of namespaced role - names for the user. - items: - type: string - type: array - subjects: - description: Subjects is the list of subject names - like users, user groups, and service accounts. - items: - description: |- - Subject contains a reference to the object or user identities a role binding applies to. This can either hold a direct API object reference, - or a value for non-objects such as user and group names. - properties: - apiGroup: - description: |- - APIGroup holds the API group of the referenced subject. - Defaults to "" for ServiceAccount subjects. - Defaults to "rbac.authorization.k8s.io" for User and Group subjects. - type: string - kind: - description: |- - Kind of object being referenced. Values defined by this API group are "User", "Group", and "ServiceAccount". - If the Authorizer does not recognized the kind value, the Authorizer should report an error. - type: string - name: - description: Name of the object being referenced. - type: string - namespace: - description: |- - Namespace of the referenced object. If the object kind is non-namespace, such as "User" or "Group", and this value is not empty - the Authorizer should report an error. - type: string - required: - - kind - - name - type: object - x-kubernetes-map-type: atomic - type: array - type: object - type: array - clusterRoles: - description: ClusterRoles is the list of cluster-wide - role names for the user. - items: - type: string - type: array - resources: - description: |- - ResourceDescription contains information about the resource being created or modified. - Requires at least one tag to be specified when under MatchResources. - Specifying ResourceDescription directly under match is being deprecated. - Please specify under "any" or "all" instead. - not: - required: - - name - - names - properties: - annotations: - additionalProperties: - type: string - description: |- - Annotations is a map of annotations (key-value pairs of type string). Annotation keys - and values support the wildcard characters "*" (matches zero or many characters) and - "?" (matches at least one character). - type: object - kinds: - description: Kinds is a list of resource kinds. - items: - type: string - type: array - name: - description: |- - Name is the name of the resource. The name supports wildcard characters - "*" (matches zero or many characters) and "?" (at least one character). - NOTE: "Name" is being deprecated in favor of "Names". - type: string - names: - description: |- - Names are the names of the resources. Each name supports wildcard characters - "*" (matches zero or many characters) and "?" (at least one character). - items: - type: string - type: array - namespaceSelector: - description: |- - NamespaceSelector is a label selector for the resource namespace. Label keys and values - in `matchLabels` support the wildcard characters `*` (matches zero or many characters) - and `?` (matches one character).Wildcards allows writing label selectors like - ["storage.k8s.io/*": "*"]. Note that using ["*" : "*"] matches any key and value but - does not match an empty label set. - properties: - matchExpressions: - description: matchExpressions is a list of label - selector requirements. The requirements are - ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key that - the selector applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - namespaces: - description: |- - Namespaces is a list of namespaces names. Each name supports wildcard characters - "*" (matches zero or many characters) and "?" (at least one character). - items: - type: string - type: array - operations: - description: Operations can contain values ["CREATE, - "UPDATE", "CONNECT", "DELETE"], which are used - to match a specific action. - items: - description: AdmissionOperation can have one of - the values CREATE, UPDATE, CONNECT, DELETE, - which are used to match a specific action. - enum: - - CREATE - - CONNECT - - UPDATE - - DELETE - type: string - type: array - selector: - description: |- - Selector is a label selector. Label keys and values in `matchLabels` support the wildcard - characters `*` (matches zero or many characters) and `?` (matches one character). - Wildcards allows writing label selectors like ["storage.k8s.io/*": "*"]. Note that - using ["*" : "*"] matches any key and value but does not match an empty label set. - properties: - matchExpressions: - description: matchExpressions is a list of label - selector requirements. The requirements are - ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key that - the selector applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - type: object - roles: - description: Roles is the list of namespaced role names - for the user. - items: - type: string - type: array - subjects: - description: Subjects is the list of subject names like - users, user groups, and service accounts. - items: - description: |- - Subject contains a reference to the object or user identities a role binding applies to. This can either hold a direct API object reference, - or a value for non-objects such as user and group names. - properties: - apiGroup: - description: |- - APIGroup holds the API group of the referenced subject. - Defaults to "" for ServiceAccount subjects. - Defaults to "rbac.authorization.k8s.io" for User and Group subjects. - type: string - kind: - description: |- - Kind of object being referenced. Values defined by this API group are "User", "Group", and "ServiceAccount". - If the Authorizer does not recognized the kind value, the Authorizer should report an error. - type: string - name: - description: Name of the object being referenced. - type: string - namespace: - description: |- - Namespace of the referenced object. If the object kind is non-namespace, such as "User" or "Group", and this value is not empty - the Authorizer should report an error. - type: string - required: - - kind - - name - type: object - x-kubernetes-map-type: atomic - type: array - type: object - generate: - description: Generation is used to create new resources. - properties: - apiVersion: - description: APIVersion specifies resource apiVersion. - type: string - clone: - description: |- - Clone specifies the source resource used to populate each generated resource. - At most one of Data or Clone can be specified. If neither are provided, the generated - resource will be created with default data only. - properties: - name: - description: Name specifies name of the resource. - type: string - namespace: - description: Namespace specifies source resource - namespace. - type: string - type: object - cloneList: - description: CloneList specifies the list of source - resource used to populate each generated resource. - properties: - kinds: - description: Kinds is a list of resource kinds. - items: - type: string - type: array - namespace: - description: Namespace specifies source resource - namespace. - type: string - selector: - description: |- - Selector is a label selector. Label keys and values in `matchLabels`. - wildcard characters are not supported. - properties: - matchExpressions: - description: matchExpressions is a list of label - selector requirements. The requirements are - ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key that - the selector applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - type: object - data: - description: |- - Data provides the resource declaration used to populate each generated resource. - At most one of Data or Clone must be specified. If neither are provided, the generated - resource will be created with default data only. - x-kubernetes-preserve-unknown-fields: true - foreach: - description: ForEach applies generate rules to a list - of sub-elements by creating a context for each entry - in the list and looping over it to apply the specified - logic. - items: - properties: - apiVersion: - description: APIVersion specifies resource apiVersion. - type: string - clone: - description: |- - Clone specifies the source resource used to populate each generated resource. - At most one of Data or Clone can be specified. If neither are provided, the generated - resource will be created with default data only. - properties: - name: - description: Name specifies name of the resource. - type: string - namespace: - description: Namespace specifies source resource - namespace. - type: string - type: object - cloneList: - description: CloneList specifies the list of source - resource used to populate each generated resource. - properties: - kinds: - description: Kinds is a list of resource kinds. - items: - type: string - type: array - namespace: - description: Namespace specifies source resource - namespace. - type: string - selector: - description: |- - Selector is a label selector. Label keys and values in `matchLabels`. - wildcard characters are not supported. - properties: - matchExpressions: - description: matchExpressions is a list - of label selector requirements. The - requirements are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key - that the selector applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - type: object - context: - description: Context defines variables and data - sources that can be used during rule execution. - items: - description: |- - ContextEntry adds variables and data sources to a rule Context. Either a - ConfigMap reference or a APILookup must be provided. - oneOf: - - required: - - configMap - - required: - - apiCall - - required: - - imageRegistry - - required: - - variable - - required: - - globalReference - properties: - apiCall: - description: |- - APICall is an HTTP request to the Kubernetes API server, or other JSON web service. - The data returned is stored in the context with the name for the context entry. - properties: - data: - description: |- - The data object specifies the POST data sent to the server. - Only applicable when the method field is set to POST. - items: - description: RequestData contains - the HTTP POST data - properties: - key: - description: Key is a unique identifier - for the data value - type: string - value: - description: Value is the data - value - x-kubernetes-preserve-unknown-fields: true - required: - - key - - value - type: object - type: array - default: - description: |- - Default is an optional arbitrary JSON object that the context - value is set to, if the apiCall returns error. - x-kubernetes-preserve-unknown-fields: true - jmesPath: - description: |- - JMESPath is an optional JSON Match Expression that can be used to - transform the JSON response returned from the server. For example - a JMESPath of "items | length(@)" applied to the API server response - for the URLPath "/apis/apps/v1/deployments" will return the total count - of deployments across all namespaces. - type: string - method: - default: GET - description: Method is the HTTP request - type (GET or POST). Defaults to GET. - enum: - - GET - - POST - type: string - service: - description: |- - Service is an API call to a JSON web service. - This is used for non-Kubernetes API server calls. - It's mutually exclusive with the URLPath field. - properties: - caBundle: - description: |- - CABundle is a PEM encoded CA bundle which will be used to validate - the server certificate. - type: string - headers: - description: Headers is a list of - optional HTTP headers to be included - in the request. - items: - properties: - key: - description: Key is the header - key - type: string - value: - description: Value is the - header value - type: string - required: - - key - - value - type: object - type: array - url: - description: |- - URL is the JSON web service URL. A typical form is - `https://{service}.{namespace}:{port}/{path}`. - type: string - required: - - url - type: object - urlPath: - description: |- - URLPath is the URL path to be used in the HTTP GET or POST request to the - Kubernetes API server (e.g. "/api/v1/namespaces" or "/apis/apps/v1/deployments"). - The format required is the same format used by the `kubectl get --raw` command. - See https://kyverno.io/docs/writing-policies/external-data-sources/#variables-from-kubernetes-api-server-calls - for details. - It's mutually exclusive with the Service field. - type: string - type: object - configMap: - description: ConfigMap is the ConfigMap - reference. - properties: - name: - description: Name is the ConfigMap name. - type: string - namespace: - description: Namespace is the ConfigMap - namespace. - type: string - required: - - name - type: object - globalReference: - description: GlobalContextEntryReference - is a reference to a cached global context - entry. - properties: - jmesPath: - description: |- - JMESPath is an optional JSON Match Expression that can be used to - transform the JSON response returned from the server. For example - a JMESPath of "items | length(@)" applied to the API server response - for the URLPath "/apis/apps/v1/deployments" will return the total count - of deployments across all namespaces. - type: string - name: - description: Name of the global context - entry - type: string - required: - - name - type: object - imageRegistry: - description: |- - ImageRegistry defines requests to an OCI/Docker V2 registry to fetch image - details. - properties: - imageRegistryCredentials: - description: ImageRegistryCredentials - provides credentials that will be - used for authentication with registry - properties: - allowInsecureRegistry: - description: AllowInsecureRegistry - allows insecure access to a registry. - type: boolean - providers: - description: |- - Providers specifies a list of OCI Registry names, whose authentication providers are provided. - It can be of one of these values: default,google,azure,amazon,github. - items: - description: ImageRegistryCredentialsProvidersType - provides the list of credential - providers required. - enum: - - default - - amazon - - azure - - google - - github - type: string - type: array - secrets: - description: |- - Secrets specifies a list of secrets that are provided for credentials. - Secrets must live in the Kyverno namespace. - items: - type: string - type: array - type: object - jmesPath: - description: |- - JMESPath is an optional JSON Match Expression that can be used to - transform the ImageData struct returned as a result of processing - the image reference. - type: string - reference: - description: |- - Reference is image reference to a container image in the registry. - Example: ghcr.io/kyverno/kyverno:latest - type: string - required: - - reference - type: object - name: - description: Name is the variable name. - type: string - variable: - description: Variable defines an arbitrary - JMESPath context variable that can be - defined inline. - properties: - default: - description: |- - Default is an optional arbitrary JSON object that the variable may take if the JMESPath - expression evaluates to nil - x-kubernetes-preserve-unknown-fields: true - jmesPath: - description: |- - JMESPath is an optional JMESPath Expression that can be used to - transform the variable. - type: string - value: - description: Value is any arbitrary - JSON object representable in YAML - or JSON form. - x-kubernetes-preserve-unknown-fields: true - type: object - required: - - name - type: object - type: array - data: - description: |- - Data provides the resource declaration used to populate each generated resource. - At most one of Data or Clone must be specified. If neither are provided, the generated - resource will be created with default data only. - x-kubernetes-preserve-unknown-fields: true - kind: - description: Kind specifies resource kind. - type: string - list: - description: |- - List specifies a JMESPath expression that results in one or more elements - to which the validation logic is applied. - type: string - name: - description: Name specifies the resource name. - type: string - namespace: - description: Namespace specifies resource namespace. - type: string - preconditions: - description: |- - AnyAllConditions are used to determine if a policy rule should be applied by evaluating a - set of conditions. The declaration can contain nested `any` or `all` statements. - See: https://kyverno.io/docs/writing-policies/preconditions/ - properties: - all: - description: |- - AllConditions enable variable-based conditional rule execution. This is useful for - finer control of when an rule is applied. A condition can reference object data - using JMESPath notation. - Here, all of the conditions need to pass - items: - description: Condition defines variable-based - conditional criteria for rule execution. - properties: - key: - description: Key is the context entry - (using JMESPath) for conditional rule - evaluation. - x-kubernetes-preserve-unknown-fields: true - message: - description: Message is an optional - display message - type: string - operator: - description: |- - Operator is the conditional operation to perform. Valid operators are: - Equals, NotEquals, In, AnyIn, AllIn, NotIn, AnyNotIn, AllNotIn, GreaterThanOrEquals, - GreaterThan, LessThanOrEquals, LessThan, DurationGreaterThanOrEquals, DurationGreaterThan, - DurationLessThanOrEquals, DurationLessThan - enum: - - Equals - - NotEquals - - In - - AnyIn - - AllIn - - NotIn - - AnyNotIn - - AllNotIn - - GreaterThanOrEquals - - GreaterThan - - LessThanOrEquals - - LessThan - - DurationGreaterThanOrEquals - - DurationGreaterThan - - DurationLessThanOrEquals - - DurationLessThan - type: string - value: - description: |- - Value is the conditional value, or set of values. The values can be fixed set - or can be variables declared using JMESPath. - x-kubernetes-preserve-unknown-fields: true - type: object - type: array - any: - description: |- - AnyConditions enable variable-based conditional rule execution. This is useful for - finer control of when an rule is applied. A condition can reference object data - using JMESPath notation. - Here, at least one of the conditions need to pass - items: - description: Condition defines variable-based - conditional criteria for rule execution. - properties: - key: - description: Key is the context entry - (using JMESPath) for conditional rule - evaluation. - x-kubernetes-preserve-unknown-fields: true - message: - description: Message is an optional - display message - type: string - operator: - description: |- - Operator is the conditional operation to perform. Valid operators are: - Equals, NotEquals, In, AnyIn, AllIn, NotIn, AnyNotIn, AllNotIn, GreaterThanOrEquals, - GreaterThan, LessThanOrEquals, LessThan, DurationGreaterThanOrEquals, DurationGreaterThan, - DurationLessThanOrEquals, DurationLessThan - enum: - - Equals - - NotEquals - - In - - AnyIn - - AllIn - - NotIn - - AnyNotIn - - AllNotIn - - GreaterThanOrEquals - - GreaterThan - - LessThanOrEquals - - LessThan - - DurationGreaterThanOrEquals - - DurationGreaterThan - - DurationLessThanOrEquals - - DurationLessThan - type: string - value: - description: |- - Value is the conditional value, or set of values. The values can be fixed set - or can be variables declared using JMESPath. - x-kubernetes-preserve-unknown-fields: true - type: object - type: array - type: object - x-kubernetes-preserve-unknown-fields: true - uid: - description: UID specifies the resource uid. - type: string - type: object - type: array - generateExisting: - description: |- - GenerateExisting controls whether to trigger the rule in existing resources - If is set to "true" the rule will be triggered and applied to existing matched resources. - type: boolean - kind: - description: Kind specifies resource kind. - type: string - name: - description: Name specifies the resource name. - type: string - namespace: - description: Namespace specifies resource namespace. - type: string - orphanDownstreamOnPolicyDelete: - description: |- - OrphanDownstreamOnPolicyDelete controls whether generated resources should be deleted when the rule that generated - them is deleted with synchronization enabled. This option is only applicable to generate rules of the data type. - See https://kyverno.io/docs/writing-policies/generate/#data-examples. - Defaults to "false" if not specified. - type: boolean - synchronize: - description: |- - Synchronize controls if generated resources should be kept in-sync with their source resource. - If Synchronize is set to "true" changes to generated resources will be overwritten with resource - data from Data or the resource specified in the Clone declaration. - Optional. Defaults to "false" if not specified. - type: boolean - uid: - description: UID specifies the resource uid. - type: string - type: object - imageExtractors: - additionalProperties: - items: - properties: - jmesPath: - description: |- - JMESPath is an optional JMESPath expression to apply to the image value. - This is useful when the extracted image begins with a prefix like 'docker://'. - The 'trim_prefix' function may be used to trim the prefix: trim_prefix(@, 'docker://'). - Note - Image digest mutation may not be used when applying a JMESPAth to an image. - type: string - key: - description: |- - Key is an optional name of the field within 'path' that will be used to uniquely identify an image. - Note - this field MUST be unique. - type: string - name: - description: |- - Name is the entry the image will be available under 'images.' in the context. - If this field is not defined, image entries will appear under 'images.custom'. - type: string - path: - description: |- - Path is the path to the object containing the image field in a custom resource. - It should be slash-separated. Each slash-separated key must be a valid YAML key or a wildcard '*'. - Wildcard keys are expanded in case of arrays or objects. - type: string - value: - description: |- - Value is an optional name of the field within 'path' that points to the image URI. - This is useful when a custom 'key' is also defined. - type: string - required: - - path - type: object - type: array - description: |- - ImageExtractors defines a mapping from kinds to ImageExtractorConfigs. - This config is only valid for verifyImages rules. - type: object - match: - description: |- - MatchResources defines when this policy rule should be applied. The match - criteria can include resource information (e.g. kind, name, namespace, labels) - and admission review request information like the user name or role. - At least one kind is required. - not: - required: - - any - - all - properties: - all: - description: All allows specifying resources which will - be ANDed - items: - description: ResourceFilter allow users to "AND" or - "OR" between resources - properties: - clusterRoles: - description: ClusterRoles is the list of cluster-wide - role names for the user. - items: - type: string - type: array - resources: - description: ResourceDescription contains information - about the resource being created or modified. - not: - required: - - name - - names - properties: - annotations: - additionalProperties: - type: string - description: |- - Annotations is a map of annotations (key-value pairs of type string). Annotation keys - and values support the wildcard characters "*" (matches zero or many characters) and - "?" (matches at least one character). - type: object - kinds: - description: Kinds is a list of resource kinds. - items: - type: string - type: array - name: - description: |- - Name is the name of the resource. The name supports wildcard characters - "*" (matches zero or many characters) and "?" (at least one character). - NOTE: "Name" is being deprecated in favor of "Names". - type: string - names: - description: |- - Names are the names of the resources. Each name supports wildcard characters - "*" (matches zero or many characters) and "?" (at least one character). - items: - type: string - type: array - namespaceSelector: - description: |- - NamespaceSelector is a label selector for the resource namespace. Label keys and values - in `matchLabels` support the wildcard characters `*` (matches zero or many characters) - and `?` (matches one character).Wildcards allows writing label selectors like - ["storage.k8s.io/*": "*"]. Note that using ["*" : "*"] matches any key and value but - does not match an empty label set. - properties: - matchExpressions: - description: matchExpressions is a list - of label selector requirements. The - requirements are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key - that the selector applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - namespaces: - description: |- - Namespaces is a list of namespaces names. Each name supports wildcard characters - "*" (matches zero or many characters) and "?" (at least one character). - items: - type: string - type: array - operations: - description: Operations can contain values - ["CREATE, "UPDATE", "CONNECT", "DELETE"], - which are used to match a specific action. - items: - description: AdmissionOperation can have - one of the values CREATE, UPDATE, CONNECT, - DELETE, which are used to match a specific - action. - enum: - - CREATE - - CONNECT - - UPDATE - - DELETE - type: string - type: array - selector: - description: |- - Selector is a label selector. Label keys and values in `matchLabels` support the wildcard - characters `*` (matches zero or many characters) and `?` (matches one character). - Wildcards allows writing label selectors like ["storage.k8s.io/*": "*"]. Note that - using ["*" : "*"] matches any key and value but does not match an empty label set. - properties: - matchExpressions: - description: matchExpressions is a list - of label selector requirements. The - requirements are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key - that the selector applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - type: object - roles: - description: Roles is the list of namespaced role - names for the user. - items: - type: string - type: array - subjects: - description: Subjects is the list of subject names - like users, user groups, and service accounts. - items: - description: |- - Subject contains a reference to the object or user identities a role binding applies to. This can either hold a direct API object reference, - or a value for non-objects such as user and group names. - properties: - apiGroup: - description: |- - APIGroup holds the API group of the referenced subject. - Defaults to "" for ServiceAccount subjects. - Defaults to "rbac.authorization.k8s.io" for User and Group subjects. - type: string - kind: - description: |- - Kind of object being referenced. Values defined by this API group are "User", "Group", and "ServiceAccount". - If the Authorizer does not recognized the kind value, the Authorizer should report an error. - type: string - name: - description: Name of the object being referenced. - type: string - namespace: - description: |- - Namespace of the referenced object. If the object kind is non-namespace, such as "User" or "Group", and this value is not empty - the Authorizer should report an error. - type: string - required: - - kind - - name - type: object - x-kubernetes-map-type: atomic - type: array - type: object - type: array - any: - description: Any allows specifying resources which will - be ORed - items: - description: ResourceFilter allow users to "AND" or - "OR" between resources - properties: - clusterRoles: - description: ClusterRoles is the list of cluster-wide - role names for the user. - items: - type: string - type: array - resources: - description: ResourceDescription contains information - about the resource being created or modified. - not: - required: - - name - - names - properties: - annotations: - additionalProperties: - type: string - description: |- - Annotations is a map of annotations (key-value pairs of type string). Annotation keys - and values support the wildcard characters "*" (matches zero or many characters) and - "?" (matches at least one character). - type: object - kinds: - description: Kinds is a list of resource kinds. - items: - type: string - type: array - name: - description: |- - Name is the name of the resource. The name supports wildcard characters - "*" (matches zero or many characters) and "?" (at least one character). - NOTE: "Name" is being deprecated in favor of "Names". - type: string - names: - description: |- - Names are the names of the resources. Each name supports wildcard characters - "*" (matches zero or many characters) and "?" (at least one character). - items: - type: string - type: array - namespaceSelector: - description: |- - NamespaceSelector is a label selector for the resource namespace. Label keys and values - in `matchLabels` support the wildcard characters `*` (matches zero or many characters) - and `?` (matches one character).Wildcards allows writing label selectors like - ["storage.k8s.io/*": "*"]. Note that using ["*" : "*"] matches any key and value but - does not match an empty label set. - properties: - matchExpressions: - description: matchExpressions is a list - of label selector requirements. The - requirements are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key - that the selector applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - namespaces: - description: |- - Namespaces is a list of namespaces names. Each name supports wildcard characters - "*" (matches zero or many characters) and "?" (at least one character). - items: - type: string - type: array - operations: - description: Operations can contain values - ["CREATE, "UPDATE", "CONNECT", "DELETE"], - which are used to match a specific action. - items: - description: AdmissionOperation can have - one of the values CREATE, UPDATE, CONNECT, - DELETE, which are used to match a specific - action. - enum: - - CREATE - - CONNECT - - UPDATE - - DELETE - type: string - type: array - selector: - description: |- - Selector is a label selector. Label keys and values in `matchLabels` support the wildcard - characters `*` (matches zero or many characters) and `?` (matches one character). - Wildcards allows writing label selectors like ["storage.k8s.io/*": "*"]. Note that - using ["*" : "*"] matches any key and value but does not match an empty label set. - properties: - matchExpressions: - description: matchExpressions is a list - of label selector requirements. The - requirements are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key - that the selector applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - type: object - roles: - description: Roles is the list of namespaced role - names for the user. - items: - type: string - type: array - subjects: - description: Subjects is the list of subject names - like users, user groups, and service accounts. - items: - description: |- - Subject contains a reference to the object or user identities a role binding applies to. This can either hold a direct API object reference, - or a value for non-objects such as user and group names. - properties: - apiGroup: - description: |- - APIGroup holds the API group of the referenced subject. - Defaults to "" for ServiceAccount subjects. - Defaults to "rbac.authorization.k8s.io" for User and Group subjects. - type: string - kind: - description: |- - Kind of object being referenced. Values defined by this API group are "User", "Group", and "ServiceAccount". - If the Authorizer does not recognized the kind value, the Authorizer should report an error. - type: string - name: - description: Name of the object being referenced. - type: string - namespace: - description: |- - Namespace of the referenced object. If the object kind is non-namespace, such as "User" or "Group", and this value is not empty - the Authorizer should report an error. - type: string - required: - - kind - - name - type: object - x-kubernetes-map-type: atomic - type: array - type: object - type: array - clusterRoles: - description: ClusterRoles is the list of cluster-wide - role names for the user. - items: - type: string - type: array - resources: - description: |- - ResourceDescription contains information about the resource being created or modified. - Requires at least one tag to be specified when under MatchResources. - Specifying ResourceDescription directly under match is being deprecated. - Please specify under "any" or "all" instead. - not: - required: - - name - - names - properties: - annotations: - additionalProperties: - type: string - description: |- - Annotations is a map of annotations (key-value pairs of type string). Annotation keys - and values support the wildcard characters "*" (matches zero or many characters) and - "?" (matches at least one character). - type: object - kinds: - description: Kinds is a list of resource kinds. - items: - type: string - type: array - name: - description: |- - Name is the name of the resource. The name supports wildcard characters - "*" (matches zero or many characters) and "?" (at least one character). - NOTE: "Name" is being deprecated in favor of "Names". - type: string - names: - description: |- - Names are the names of the resources. Each name supports wildcard characters - "*" (matches zero or many characters) and "?" (at least one character). - items: - type: string - type: array - namespaceSelector: - description: |- - NamespaceSelector is a label selector for the resource namespace. Label keys and values - in `matchLabels` support the wildcard characters `*` (matches zero or many characters) - and `?` (matches one character).Wildcards allows writing label selectors like - ["storage.k8s.io/*": "*"]. Note that using ["*" : "*"] matches any key and value but - does not match an empty label set. - properties: - matchExpressions: - description: matchExpressions is a list of label - selector requirements. The requirements are - ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key that - the selector applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - namespaces: - description: |- - Namespaces is a list of namespaces names. Each name supports wildcard characters - "*" (matches zero or many characters) and "?" (at least one character). - items: - type: string - type: array - operations: - description: Operations can contain values ["CREATE, - "UPDATE", "CONNECT", "DELETE"], which are used - to match a specific action. - items: - description: AdmissionOperation can have one of - the values CREATE, UPDATE, CONNECT, DELETE, - which are used to match a specific action. - enum: - - CREATE - - CONNECT - - UPDATE - - DELETE - type: string - type: array - selector: - description: |- - Selector is a label selector. Label keys and values in `matchLabels` support the wildcard - characters `*` (matches zero or many characters) and `?` (matches one character). - Wildcards allows writing label selectors like ["storage.k8s.io/*": "*"]. Note that - using ["*" : "*"] matches any key and value but does not match an empty label set. - properties: - matchExpressions: - description: matchExpressions is a list of label - selector requirements. The requirements are - ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key that - the selector applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - type: object - roles: - description: Roles is the list of namespaced role names - for the user. - items: - type: string - type: array - subjects: - description: Subjects is the list of subject names like - users, user groups, and service accounts. - items: - description: |- - Subject contains a reference to the object or user identities a role binding applies to. This can either hold a direct API object reference, - or a value for non-objects such as user and group names. - properties: - apiGroup: - description: |- - APIGroup holds the API group of the referenced subject. - Defaults to "" for ServiceAccount subjects. - Defaults to "rbac.authorization.k8s.io" for User and Group subjects. - type: string - kind: - description: |- - Kind of object being referenced. Values defined by this API group are "User", "Group", and "ServiceAccount". - If the Authorizer does not recognized the kind value, the Authorizer should report an error. - type: string - name: - description: Name of the object being referenced. - type: string - namespace: - description: |- - Namespace of the referenced object. If the object kind is non-namespace, such as "User" or "Group", and this value is not empty - the Authorizer should report an error. - type: string - required: - - kind - - name - type: object - x-kubernetes-map-type: atomic - type: array - type: object - mutate: - description: Mutation is used to modify matching resources. - properties: - foreach: - description: ForEach applies mutation rules to a list - of sub-elements by creating a context for each entry - in the list and looping over it to apply the specified - logic. - items: - description: ForEachMutation applies mutation rules - to a list of sub-elements by creating a context - for each entry in the list and looping over it to - apply the specified logic. - properties: - context: - description: Context defines variables and data - sources that can be used during rule execution. - items: - description: |- - ContextEntry adds variables and data sources to a rule Context. Either a - ConfigMap reference or a APILookup must be provided. - oneOf: - - required: - - configMap - - required: - - apiCall - - required: - - imageRegistry - - required: - - variable - - required: - - globalReference - properties: - apiCall: - description: |- - APICall is an HTTP request to the Kubernetes API server, or other JSON web service. - The data returned is stored in the context with the name for the context entry. - properties: - data: - description: |- - The data object specifies the POST data sent to the server. - Only applicable when the method field is set to POST. - items: - description: RequestData contains - the HTTP POST data - properties: - key: - description: Key is a unique identifier - for the data value - type: string - value: - description: Value is the data - value - x-kubernetes-preserve-unknown-fields: true - required: - - key - - value - type: object - type: array - default: - description: |- - Default is an optional arbitrary JSON object that the context - value is set to, if the apiCall returns error. - x-kubernetes-preserve-unknown-fields: true - jmesPath: - description: |- - JMESPath is an optional JSON Match Expression that can be used to - transform the JSON response returned from the server. For example - a JMESPath of "items | length(@)" applied to the API server response - for the URLPath "/apis/apps/v1/deployments" will return the total count - of deployments across all namespaces. - type: string - method: - default: GET - description: Method is the HTTP request - type (GET or POST). Defaults to GET. - enum: - - GET - - POST - type: string - service: - description: |- - Service is an API call to a JSON web service. - This is used for non-Kubernetes API server calls. - It's mutually exclusive with the URLPath field. - properties: - caBundle: - description: |- - CABundle is a PEM encoded CA bundle which will be used to validate - the server certificate. - type: string - headers: - description: Headers is a list of - optional HTTP headers to be included - in the request. - items: - properties: - key: - description: Key is the header - key - type: string - value: - description: Value is the - header value - type: string - required: - - key - - value - type: object - type: array - url: - description: |- - URL is the JSON web service URL. A typical form is - `https://{service}.{namespace}:{port}/{path}`. - type: string - required: - - url - type: object - urlPath: - description: |- - URLPath is the URL path to be used in the HTTP GET or POST request to the - Kubernetes API server (e.g. "/api/v1/namespaces" or "/apis/apps/v1/deployments"). - The format required is the same format used by the `kubectl get --raw` command. - See https://kyverno.io/docs/writing-policies/external-data-sources/#variables-from-kubernetes-api-server-calls - for details. - It's mutually exclusive with the Service field. - type: string - type: object - configMap: - description: ConfigMap is the ConfigMap - reference. - properties: - name: - description: Name is the ConfigMap name. - type: string - namespace: - description: Namespace is the ConfigMap - namespace. - type: string - required: - - name - type: object - globalReference: - description: GlobalContextEntryReference - is a reference to a cached global context - entry. - properties: - jmesPath: - description: |- - JMESPath is an optional JSON Match Expression that can be used to - transform the JSON response returned from the server. For example - a JMESPath of "items | length(@)" applied to the API server response - for the URLPath "/apis/apps/v1/deployments" will return the total count - of deployments across all namespaces. - type: string - name: - description: Name of the global context - entry - type: string - required: - - name - type: object - imageRegistry: - description: |- - ImageRegistry defines requests to an OCI/Docker V2 registry to fetch image - details. - properties: - imageRegistryCredentials: - description: ImageRegistryCredentials - provides credentials that will be - used for authentication with registry - properties: - allowInsecureRegistry: - description: AllowInsecureRegistry - allows insecure access to a registry. - type: boolean - providers: - description: |- - Providers specifies a list of OCI Registry names, whose authentication providers are provided. - It can be of one of these values: default,google,azure,amazon,github. - items: - description: ImageRegistryCredentialsProvidersType - provides the list of credential - providers required. - enum: - - default - - amazon - - azure - - google - - github - type: string - type: array - secrets: - description: |- - Secrets specifies a list of secrets that are provided for credentials. - Secrets must live in the Kyverno namespace. - items: - type: string - type: array - type: object - jmesPath: - description: |- - JMESPath is an optional JSON Match Expression that can be used to - transform the ImageData struct returned as a result of processing - the image reference. - type: string - reference: - description: |- - Reference is image reference to a container image in the registry. - Example: ghcr.io/kyverno/kyverno:latest - type: string - required: - - reference - type: object - name: - description: Name is the variable name. - type: string - variable: - description: Variable defines an arbitrary - JMESPath context variable that can be - defined inline. - properties: - default: - description: |- - Default is an optional arbitrary JSON object that the variable may take if the JMESPath - expression evaluates to nil - x-kubernetes-preserve-unknown-fields: true - jmesPath: - description: |- - JMESPath is an optional JMESPath Expression that can be used to - transform the variable. - type: string - value: - description: Value is any arbitrary - JSON object representable in YAML - or JSON form. - x-kubernetes-preserve-unknown-fields: true - type: object - required: - - name - type: object - type: array - foreach: - description: Foreach declares a nested foreach - iterator - x-kubernetes-preserve-unknown-fields: true - list: - description: |- - List specifies a JMESPath expression that results in one or more elements - to which the validation logic is applied. - type: string - order: - description: |- - Order defines the iteration order on the list. - Can be Ascending to iterate from first to last element or Descending to iterate in from last to first element. - enum: - - Ascending - - Descending - type: string - patchStrategicMerge: - description: |- - PatchStrategicMerge is a strategic merge patch used to modify resources. - See https://kubernetes.io/docs/tasks/manage-kubernetes-objects/update-api-object-kubectl-patch/ - and https://kubectl.docs.kubernetes.io/references/kustomize/kustomization/patchesstrategicmerge/. - x-kubernetes-preserve-unknown-fields: true - patchesJson6902: - description: |- - PatchesJSON6902 is a list of RFC 6902 JSON Patch declarations used to modify resources. - See https://tools.ietf.org/html/rfc6902 and https://kubectl.docs.kubernetes.io/references/kustomize/kustomization/patchesjson6902/. - type: string - preconditions: - description: |- - AnyAllConditions are used to determine if a policy rule should be applied by evaluating a - set of conditions. The declaration can contain nested `any` or `all` statements. - See: https://kyverno.io/docs/writing-policies/preconditions/ - properties: - all: - description: |- - AllConditions enable variable-based conditional rule execution. This is useful for - finer control of when an rule is applied. A condition can reference object data - using JMESPath notation. - Here, all of the conditions need to pass - items: - description: Condition defines variable-based - conditional criteria for rule execution. - properties: - key: - description: Key is the context entry - (using JMESPath) for conditional rule - evaluation. - x-kubernetes-preserve-unknown-fields: true - message: - description: Message is an optional - display message - type: string - operator: - description: |- - Operator is the conditional operation to perform. Valid operators are: - Equals, NotEquals, In, AnyIn, AllIn, NotIn, AnyNotIn, AllNotIn, GreaterThanOrEquals, - GreaterThan, LessThanOrEquals, LessThan, DurationGreaterThanOrEquals, DurationGreaterThan, - DurationLessThanOrEquals, DurationLessThan - enum: - - Equals - - NotEquals - - In - - AnyIn - - AllIn - - NotIn - - AnyNotIn - - AllNotIn - - GreaterThanOrEquals - - GreaterThan - - LessThanOrEquals - - LessThan - - DurationGreaterThanOrEquals - - DurationGreaterThan - - DurationLessThanOrEquals - - DurationLessThan - type: string - value: - description: |- - Value is the conditional value, or set of values. The values can be fixed set - or can be variables declared using JMESPath. - x-kubernetes-preserve-unknown-fields: true - type: object - type: array - any: - description: |- - AnyConditions enable variable-based conditional rule execution. This is useful for - finer control of when an rule is applied. A condition can reference object data - using JMESPath notation. - Here, at least one of the conditions need to pass - items: - description: Condition defines variable-based - conditional criteria for rule execution. - properties: - key: - description: Key is the context entry - (using JMESPath) for conditional rule - evaluation. - x-kubernetes-preserve-unknown-fields: true - message: - description: Message is an optional - display message - type: string - operator: - description: |- - Operator is the conditional operation to perform. Valid operators are: - Equals, NotEquals, In, AnyIn, AllIn, NotIn, AnyNotIn, AllNotIn, GreaterThanOrEquals, - GreaterThan, LessThanOrEquals, LessThan, DurationGreaterThanOrEquals, DurationGreaterThan, - DurationLessThanOrEquals, DurationLessThan - enum: - - Equals - - NotEquals - - In - - AnyIn - - AllIn - - NotIn - - AnyNotIn - - AllNotIn - - GreaterThanOrEquals - - GreaterThan - - LessThanOrEquals - - LessThan - - DurationGreaterThanOrEquals - - DurationGreaterThan - - DurationLessThanOrEquals - - DurationLessThan - type: string - value: - description: |- - Value is the conditional value, or set of values. The values can be fixed set - or can be variables declared using JMESPath. - x-kubernetes-preserve-unknown-fields: true - type: object - type: array - type: object - x-kubernetes-preserve-unknown-fields: true - type: object - type: array - mutateExistingOnPolicyUpdate: - description: MutateExistingOnPolicyUpdate controls if - the mutateExisting rule will be applied on policy - events. - type: boolean - patchStrategicMerge: - description: |- - PatchStrategicMerge is a strategic merge patch used to modify resources. - See https://kubernetes.io/docs/tasks/manage-kubernetes-objects/update-api-object-kubectl-patch/ - and https://kubectl.docs.kubernetes.io/references/kustomize/kustomization/patchesstrategicmerge/. - x-kubernetes-preserve-unknown-fields: true - patchesJson6902: - description: |- - PatchesJSON6902 is a list of RFC 6902 JSON Patch declarations used to modify resources. - See https://tools.ietf.org/html/rfc6902 and https://kubectl.docs.kubernetes.io/references/kustomize/kustomization/patchesjson6902/. - type: string - targets: - description: Targets defines the target resources to - be mutated. - items: - description: TargetResourceSpec defines targets for - mutating existing resources. - properties: - apiVersion: - description: APIVersion specifies resource apiVersion. - type: string - context: - description: Context defines variables and data - sources that can be used during rule execution. - items: - description: |- - ContextEntry adds variables and data sources to a rule Context. Either a - ConfigMap reference or a APILookup must be provided. - oneOf: - - required: - - configMap - - required: - - apiCall - - required: - - imageRegistry - - required: - - variable - - required: - - globalReference - properties: - apiCall: - description: |- - APICall is an HTTP request to the Kubernetes API server, or other JSON web service. - The data returned is stored in the context with the name for the context entry. - properties: - data: - description: |- - The data object specifies the POST data sent to the server. - Only applicable when the method field is set to POST. - items: - description: RequestData contains - the HTTP POST data - properties: - key: - description: Key is a unique identifier - for the data value - type: string - value: - description: Value is the data - value - x-kubernetes-preserve-unknown-fields: true - required: - - key - - value - type: object - type: array - default: - description: |- - Default is an optional arbitrary JSON object that the context - value is set to, if the apiCall returns error. - x-kubernetes-preserve-unknown-fields: true - jmesPath: - description: |- - JMESPath is an optional JSON Match Expression that can be used to - transform the JSON response returned from the server. For example - a JMESPath of "items | length(@)" applied to the API server response - for the URLPath "/apis/apps/v1/deployments" will return the total count - of deployments across all namespaces. - type: string - method: - default: GET - description: Method is the HTTP request - type (GET or POST). Defaults to GET. - enum: - - GET - - POST - type: string - service: - description: |- - Service is an API call to a JSON web service. - This is used for non-Kubernetes API server calls. - It's mutually exclusive with the URLPath field. - properties: - caBundle: - description: |- - CABundle is a PEM encoded CA bundle which will be used to validate - the server certificate. - type: string - headers: - description: Headers is a list of - optional HTTP headers to be included - in the request. - items: - properties: - key: - description: Key is the header - key - type: string - value: - description: Value is the - header value - type: string - required: - - key - - value - type: object - type: array - url: - description: |- - URL is the JSON web service URL. A typical form is - `https://{service}.{namespace}:{port}/{path}`. - type: string - required: - - url - type: object - urlPath: - description: |- - URLPath is the URL path to be used in the HTTP GET or POST request to the - Kubernetes API server (e.g. "/api/v1/namespaces" or "/apis/apps/v1/deployments"). - The format required is the same format used by the `kubectl get --raw` command. - See https://kyverno.io/docs/writing-policies/external-data-sources/#variables-from-kubernetes-api-server-calls - for details. - It's mutually exclusive with the Service field. - type: string - type: object - configMap: - description: ConfigMap is the ConfigMap - reference. - properties: - name: - description: Name is the ConfigMap name. - type: string - namespace: - description: Namespace is the ConfigMap - namespace. - type: string - required: - - name - type: object - globalReference: - description: GlobalContextEntryReference - is a reference to a cached global context - entry. - properties: - jmesPath: - description: |- - JMESPath is an optional JSON Match Expression that can be used to - transform the JSON response returned from the server. For example - a JMESPath of "items | length(@)" applied to the API server response - for the URLPath "/apis/apps/v1/deployments" will return the total count - of deployments across all namespaces. - type: string - name: - description: Name of the global context - entry - type: string - required: - - name - type: object - imageRegistry: - description: |- - ImageRegistry defines requests to an OCI/Docker V2 registry to fetch image - details. - properties: - imageRegistryCredentials: - description: ImageRegistryCredentials - provides credentials that will be - used for authentication with registry - properties: - allowInsecureRegistry: - description: AllowInsecureRegistry - allows insecure access to a registry. - type: boolean - providers: - description: |- - Providers specifies a list of OCI Registry names, whose authentication providers are provided. - It can be of one of these values: default,google,azure,amazon,github. - items: - description: ImageRegistryCredentialsProvidersType - provides the list of credential - providers required. - enum: - - default - - amazon - - azure - - google - - github - type: string - type: array - secrets: - description: |- - Secrets specifies a list of secrets that are provided for credentials. - Secrets must live in the Kyverno namespace. - items: - type: string - type: array - type: object - jmesPath: - description: |- - JMESPath is an optional JSON Match Expression that can be used to - transform the ImageData struct returned as a result of processing - the image reference. - type: string - reference: - description: |- - Reference is image reference to a container image in the registry. - Example: ghcr.io/kyverno/kyverno:latest - type: string - required: - - reference - type: object - name: - description: Name is the variable name. - type: string - variable: - description: Variable defines an arbitrary - JMESPath context variable that can be - defined inline. - properties: - default: - description: |- - Default is an optional arbitrary JSON object that the variable may take if the JMESPath - expression evaluates to nil - x-kubernetes-preserve-unknown-fields: true - jmesPath: - description: |- - JMESPath is an optional JMESPath Expression that can be used to - transform the variable. - type: string - value: - description: Value is any arbitrary - JSON object representable in YAML - or JSON form. - x-kubernetes-preserve-unknown-fields: true - type: object - required: - - name - type: object - type: array - kind: - description: Kind specifies resource kind. - type: string - name: - description: Name specifies the resource name. - type: string - namespace: - description: Namespace specifies resource namespace. - type: string - preconditions: - description: |- - Preconditions are used to determine if a policy rule should be applied by evaluating a - set of conditions. The declaration can contain nested `any` or `all` statements. A direct list - of conditions (without `any` or `all` statements is supported for backwards compatibility but - will be deprecated in the next major release. - See: https://kyverno.io/docs/writing-policies/preconditions/ - x-kubernetes-preserve-unknown-fields: true - selector: - description: Selector allows you to select target - resources with their labels. - properties: - matchExpressions: - description: matchExpressions is a list of - label selector requirements. The requirements - are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key that - the selector applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - uid: - description: UID specifies the resource uid. - type: string - type: object - type: array - type: object - name: - description: Name is a label to identify the rule, It must - be unique within the policy. - maxLength: 63 - type: string - preconditions: - description: |- - Preconditions are used to determine if a policy rule should be applied by evaluating a - set of conditions. The declaration can contain nested `any` or `all` statements. A direct list - of conditions (without `any` or `all` statements is supported for backwards compatibility but - will be deprecated in the next major release. - See: https://kyverno.io/docs/writing-policies/preconditions/ - x-kubernetes-preserve-unknown-fields: true - reportProperties: - additionalProperties: - type: string - description: ReportProperties are the additional properties - from the rule that will be added to the policy report - result - type: object - skipBackgroundRequests: - default: true - description: |- - SkipBackgroundRequests bypasses admission requests that are sent by the background controller. - The default value is set to "true", it must be set to "false" to apply - generate and mutateExisting rules to those requests. - type: boolean - validate: - description: Validation is used to validate matching resources. - properties: - allowExistingViolations: - default: true - description: AllowExistingViolations allows prexisting - violating resources to continue violating a policy. - type: boolean - anyPattern: - description: |- - AnyPattern specifies list of validation patterns. At least one of the patterns - must be satisfied for the validation rule to succeed. - x-kubernetes-preserve-unknown-fields: true - assert: - description: Assert defines a kyverno-json assertion - tree. - type: object - x-kubernetes-preserve-unknown-fields: true - cel: - description: CEL allows validation checks using the - Common Expression Language (https://kubernetes.io/docs/reference/using-api/cel/). - properties: - auditAnnotations: - description: AuditAnnotations contains CEL expressions - which are used to produce audit annotations for - the audit event of the API request. - items: - description: AuditAnnotation describes how to - produce an audit annotation for an API request. - properties: - key: - description: |- - key specifies the audit annotation key. The audit annotation keys of - a ValidatingAdmissionPolicy must be unique. The key must be a qualified - name ([A-Za-z0-9][-A-Za-z0-9_.]*) no more than 63 bytes in length. - - The key is combined with the resource name of the - ValidatingAdmissionPolicy to construct an audit annotation key: - "{ValidatingAdmissionPolicy name}/{key}". - - If an admission webhook uses the same resource name as this ValidatingAdmissionPolicy - and the same audit annotation key, the annotation key will be identical. - In this case, the first annotation written with the key will be included - in the audit event and all subsequent annotations with the same key - will be discarded. - - Required. - type: string - valueExpression: - description: |- - valueExpression represents the expression which is evaluated by CEL to - produce an audit annotation value. The expression must evaluate to either - a string or null value. If the expression evaluates to a string, the - audit annotation is included with the string value. If the expression - evaluates to null or empty string the audit annotation will be omitted. - The valueExpression may be no longer than 5kb in length. - If the result of the valueExpression is more than 10kb in length, it - will be truncated to 10kb. - - If multiple ValidatingAdmissionPolicyBinding resources match an - API request, then the valueExpression will be evaluated for - each binding. All unique values produced by the valueExpressions - will be joined together in a comma-separated list. - - Required. - type: string - required: - - key - - valueExpression - type: object - type: array - expressions: - description: Expressions is a list of CELExpression - types. - items: - description: Validation specifies the CEL expression - which is used to apply the validation. - properties: - expression: - description: "Expression represents the expression - which will be evaluated by CEL.\nref: https://github.com/google/cel-spec\nCEL - expressions have access to the contents - of the API request/response, organized into - CEL variables as well as some other useful - variables:\n\n- 'object' - The object from - the incoming request. The value is null - for DELETE requests.\n- 'oldObject' - The - existing object. The value is null for CREATE - requests.\n- 'request' - Attributes of the - API request([ref](/pkg/apis/admission/types.go#AdmissionRequest)).\n- - 'params' - Parameter resource referred to - by the policy binding being evaluated. Only - populated if the policy has a ParamKind.\n- - 'namespaceObject' - The namespace object - that the incoming object belongs to. The - value is null for cluster-scoped resources.\n- - 'variables' - Map of composited variables, - from its name to its lazily evaluated value.\n - \ For example, a variable named 'foo' can - be accessed as 'variables.foo'.\n- 'authorizer' - - A CEL Authorizer. May be used to perform - authorization checks for the principal (user - or service account) of the request.\n See - https://pkg.go.dev/k8s.io/apiserver/pkg/cel/library#Authz\n- - 'authorizer.requestResource' - A CEL ResourceCheck - constructed from the 'authorizer' and configured - with the\n request resource.\n\nThe `apiVersion`, - `kind`, `metadata.name` and `metadata.generateName` - are always accessible from the root of the\nobject. - No other metadata properties are accessible.\n\nOnly - property names of the form `[a-zA-Z_.-/][a-zA-Z0-9_.-/]*` - are accessible.\nAccessible property names - are escaped according to the following rules - when accessed in the expression:\n- '__' - escapes to '__underscores__'\n- '.' escapes - to '__dot__'\n- '-' escapes to '__dash__'\n- - '/' escapes to '__slash__'\n- Property names - that exactly match a CEL RESERVED keyword - escape to '__{keyword}__'. The keywords - are:\n\t \"true\", \"false\", \"null\", - \"in\", \"as\", \"break\", \"const\", \"continue\", - \"else\", \"for\", \"function\", \"if\",\n\t - \ \"import\", \"let\", \"loop\", \"package\", - \"namespace\", \"return\".\nExamples:\n - \ - Expression accessing a property named - \"namespace\": {\"Expression\": \"object.__namespace__ - > 0\"}\n - Expression accessing a property - named \"x-prop\": {\"Expression\": \"object.x__dash__prop - > 0\"}\n - Expression accessing a property - named \"redact__d\": {\"Expression\": \"object.redact__underscores__d - > 0\"}\n\nEquality on arrays with list type - of 'set' or 'map' ignores element order, - i.e. [1, 2] == [2, 1].\nConcatenation on - arrays with x-kubernetes-list-type use the - semantics of the list type:\n - 'set': - `X + Y` performs a union where the array - positions of all elements in `X` are preserved - and\n non-intersecting elements in `Y` - are appended, retaining their partial order.\n - \ - 'map': `X + Y` performs a merge where - the array positions of all keys in `X` are - preserved but the values\n are overwritten - by values in `Y` when the key sets of `X` - and `Y` intersect. Elements in `Y` with\n - \ non-intersecting keys are appended, - retaining their partial order.\nRequired." - type: string - message: - description: |- - Message represents the message displayed when validation fails. The message is required if the Expression contains - line breaks. The message must not contain line breaks. - If unset, the message is "failed rule: {Rule}". - e.g. "must be a URL with the host matching spec.host" - If the Expression contains line breaks. Message is required. - The message must not contain line breaks. - If unset, the message is "failed Expression: {Expression}". - type: string - messageExpression: - description: |- - messageExpression declares a CEL expression that evaluates to the validation failure message that is returned when this rule fails. - Since messageExpression is used as a failure message, it must evaluate to a string. - If both message and messageExpression are present on a validation, then messageExpression will be used if validation fails. - If messageExpression results in a runtime error, the runtime error is logged, and the validation failure message is produced - as if the messageExpression field were unset. If messageExpression evaluates to an empty string, a string with only spaces, or a string - that contains line breaks, then the validation failure message will also be produced as if the messageExpression field were unset, and - the fact that messageExpression produced an empty string/string with only spaces/string with line breaks will be logged. - messageExpression has access to all the same variables as the `expression` except for 'authorizer' and 'authorizer.requestResource'. - Example: - "object.x must be less than max ("+string(params.max)+")" - type: string - reason: - description: |- - Reason represents a machine-readable description of why this validation failed. - If this is the first validation in the list to fail, this reason, as well as the - corresponding HTTP response code, are used in the - HTTP response to the client. - The currently supported reasons are: "Unauthorized", "Forbidden", "Invalid", "RequestEntityTooLarge". - If not set, StatusReasonInvalid is used in the response to the client. - type: string - required: - - expression - type: object - type: array - generate: - default: false - description: |- - Generate specifies whether to generate a Kubernetes ValidatingAdmissionPolicy from the rule. - Optional. Defaults to "false" if not specified. - type: boolean - paramKind: - description: ParamKind is a tuple of Group Kind - and Version. - properties: - apiVersion: - description: |- - APIVersion is the API group version the resources belong to. - In format of "group/version". - Required. - type: string - kind: - description: |- - Kind is the API kind the resources belong to. - Required. - type: string - type: object - x-kubernetes-map-type: atomic - paramRef: - description: ParamRef references a parameter resource. - properties: - name: - description: |- - name is the name of the resource being referenced. - - One of `name` or `selector` must be set, but `name` and `selector` are - mutually exclusive properties. If one is set, the other must be unset. - - A single parameter used for all admission requests can be configured - by setting the `name` field, leaving `selector` blank, and setting namespace - if `paramKind` is namespace-scoped. - type: string - namespace: - description: |- - namespace is the namespace of the referenced resource. Allows limiting - the search for params to a specific namespace. Applies to both `name` and - `selector` fields. - - A per-namespace parameter may be used by specifying a namespace-scoped - `paramKind` in the policy and leaving this field empty. - - - If `paramKind` is cluster-scoped, this field MUST be unset. Setting this - field results in a configuration error. - - - If `paramKind` is namespace-scoped, the namespace of the object being - evaluated for admission will be used when this field is left unset. Take - care that if this is left empty the binding must not match any cluster-scoped - resources, which will result in an error. - type: string - parameterNotFoundAction: - description: |- - `parameterNotFoundAction` controls the behavior of the binding when the resource - exists, and name or selector is valid, but there are no parameters - matched by the binding. If the value is set to `Allow`, then no - matched parameters will be treated as successful validation by the binding. - If set to `Deny`, then no matched parameters will be subject to the - `failurePolicy` of the policy. - - Allowed values are `Allow` or `Deny` - - Required - type: string - selector: - description: |- - selector can be used to match multiple param objects based on their labels. - Supply selector: {} to match all resources of the ParamKind. - - If multiple params are found, they are all evaluated with the policy expressions - and the results are ANDed together. - - One of `name` or `selector` must be set, but `name` and `selector` are - mutually exclusive properties. If one is set, the other must be unset. - properties: - matchExpressions: - description: matchExpressions is a list - of label selector requirements. The requirements - are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key - that the selector applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - type: object - x-kubernetes-map-type: atomic - variables: - description: |- - Variables contain definitions of variables that can be used in composition of other expressions. - Each variable is defined as a named CEL expression. - The variables defined here will be available under `variables` in other expressions of the policy. - items: - description: Variable is the definition of a variable - that is used for composition. A variable is - defined as a named expression. - properties: - expression: - description: |- - Expression is the expression that will be evaluated as the value of the variable. - The CEL expression has access to the same identifiers as the CEL expressions in Validation. - type: string - name: - description: |- - Name is the name of the variable. The name must be a valid CEL identifier and unique among all variables. - The variable can be accessed in other expressions through `variables` - For example, if name is "foo", the variable will be available as `variables.foo` - type: string - required: - - expression - - name - type: object - x-kubernetes-map-type: atomic - type: array - type: object - deny: - description: Deny defines conditions used to pass or - fail a validation rule. - properties: - conditions: - description: |- - Multiple conditions can be declared under an `any` or `all` statement. A direct list - of conditions (without `any` or `all` statements) is also supported for backwards compatibility - but will be deprecated in the next major release. - See: https://kyverno.io/docs/writing-policies/validate/#deny-rules - x-kubernetes-preserve-unknown-fields: true - type: object - failureAction: - description: |- - FailureAction defines if a validation policy rule violation should block - the admission review request (Enforce), or allow (Audit) the admission review request - and report an error in a policy report. Optional. - Allowed values are Audit or Enforce. - enum: - - Audit - - Enforce - type: string - failureActionOverrides: - description: |- - FailureActionOverrides is a Cluster Policy attribute that specifies FailureAction - namespace-wise. It overrides FailureAction for the specified namespaces. - items: - properties: - action: - description: ValidationFailureAction defines the - policy validation failure action - enum: - - audit - - enforce - - Audit - - Enforce - type: string - namespaceSelector: - description: |- - A label selector is a label query over a set of resources. The result of matchLabels and - matchExpressions are ANDed. An empty label selector matches all objects. A null - label selector matches no objects. - properties: - matchExpressions: - description: matchExpressions is a list of - label selector requirements. The requirements - are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key that - the selector applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - namespaces: - items: - type: string - type: array - type: object - type: array - foreach: - description: ForEach applies validate rules to a list - of sub-elements by creating a context for each entry - in the list and looping over it to apply the specified - logic. - items: - description: ForEachValidation applies validate rules - to a list of sub-elements by creating a context - for each entry in the list and looping over it to - apply the specified logic. - properties: - anyPattern: - description: |- - AnyPattern specifies list of validation patterns. At least one of the patterns - must be satisfied for the validation rule to succeed. - x-kubernetes-preserve-unknown-fields: true - context: - description: Context defines variables and data - sources that can be used during rule execution. - items: - description: |- - ContextEntry adds variables and data sources to a rule Context. Either a - ConfigMap reference or a APILookup must be provided. - oneOf: - - required: - - configMap - - required: - - apiCall - - required: - - imageRegistry - - required: - - variable - - required: - - globalReference - properties: - apiCall: - description: |- - APICall is an HTTP request to the Kubernetes API server, or other JSON web service. - The data returned is stored in the context with the name for the context entry. - properties: - data: - description: |- - The data object specifies the POST data sent to the server. - Only applicable when the method field is set to POST. - items: - description: RequestData contains - the HTTP POST data - properties: - key: - description: Key is a unique identifier - for the data value - type: string - value: - description: Value is the data - value - x-kubernetes-preserve-unknown-fields: true - required: - - key - - value - type: object - type: array - default: - description: |- - Default is an optional arbitrary JSON object that the context - value is set to, if the apiCall returns error. - x-kubernetes-preserve-unknown-fields: true - jmesPath: - description: |- - JMESPath is an optional JSON Match Expression that can be used to - transform the JSON response returned from the server. For example - a JMESPath of "items | length(@)" applied to the API server response - for the URLPath "/apis/apps/v1/deployments" will return the total count - of deployments across all namespaces. - type: string - method: - default: GET - description: Method is the HTTP request - type (GET or POST). Defaults to GET. - enum: - - GET - - POST - type: string - service: - description: |- - Service is an API call to a JSON web service. - This is used for non-Kubernetes API server calls. - It's mutually exclusive with the URLPath field. - properties: - caBundle: - description: |- - CABundle is a PEM encoded CA bundle which will be used to validate - the server certificate. - type: string - headers: - description: Headers is a list of - optional HTTP headers to be included - in the request. - items: - properties: - key: - description: Key is the header - key - type: string - value: - description: Value is the - header value - type: string - required: - - key - - value - type: object - type: array - url: - description: |- - URL is the JSON web service URL. A typical form is - `https://{service}.{namespace}:{port}/{path}`. - type: string - required: - - url - type: object - urlPath: - description: |- - URLPath is the URL path to be used in the HTTP GET or POST request to the - Kubernetes API server (e.g. "/api/v1/namespaces" or "/apis/apps/v1/deployments"). - The format required is the same format used by the `kubectl get --raw` command. - See https://kyverno.io/docs/writing-policies/external-data-sources/#variables-from-kubernetes-api-server-calls - for details. - It's mutually exclusive with the Service field. - type: string - type: object - configMap: - description: ConfigMap is the ConfigMap - reference. - properties: - name: - description: Name is the ConfigMap name. - type: string - namespace: - description: Namespace is the ConfigMap - namespace. - type: string - required: - - name - type: object - globalReference: - description: GlobalContextEntryReference - is a reference to a cached global context - entry. - properties: - jmesPath: - description: |- - JMESPath is an optional JSON Match Expression that can be used to - transform the JSON response returned from the server. For example - a JMESPath of "items | length(@)" applied to the API server response - for the URLPath "/apis/apps/v1/deployments" will return the total count - of deployments across all namespaces. - type: string - name: - description: Name of the global context - entry - type: string - required: - - name - type: object - imageRegistry: - description: |- - ImageRegistry defines requests to an OCI/Docker V2 registry to fetch image - details. - properties: - imageRegistryCredentials: - description: ImageRegistryCredentials - provides credentials that will be - used for authentication with registry - properties: - allowInsecureRegistry: - description: AllowInsecureRegistry - allows insecure access to a registry. - type: boolean - providers: - description: |- - Providers specifies a list of OCI Registry names, whose authentication providers are provided. - It can be of one of these values: default,google,azure,amazon,github. - items: - description: ImageRegistryCredentialsProvidersType - provides the list of credential - providers required. - enum: - - default - - amazon - - azure - - google - - github - type: string - type: array - secrets: - description: |- - Secrets specifies a list of secrets that are provided for credentials. - Secrets must live in the Kyverno namespace. - items: - type: string - type: array - type: object - jmesPath: - description: |- - JMESPath is an optional JSON Match Expression that can be used to - transform the ImageData struct returned as a result of processing - the image reference. - type: string - reference: - description: |- - Reference is image reference to a container image in the registry. - Example: ghcr.io/kyverno/kyverno:latest - type: string - required: - - reference - type: object - name: - description: Name is the variable name. - type: string - variable: - description: Variable defines an arbitrary - JMESPath context variable that can be - defined inline. - properties: - default: - description: |- - Default is an optional arbitrary JSON object that the variable may take if the JMESPath - expression evaluates to nil - x-kubernetes-preserve-unknown-fields: true - jmesPath: - description: |- - JMESPath is an optional JMESPath Expression that can be used to - transform the variable. - type: string - value: - description: Value is any arbitrary - JSON object representable in YAML - or JSON form. - x-kubernetes-preserve-unknown-fields: true - type: object - required: - - name - type: object - type: array - deny: - description: Deny defines conditions used to pass - or fail a validation rule. - properties: - conditions: - description: |- - Multiple conditions can be declared under an `any` or `all` statement. A direct list - of conditions (without `any` or `all` statements) is also supported for backwards compatibility - but will be deprecated in the next major release. - See: https://kyverno.io/docs/writing-policies/validate/#deny-rules - x-kubernetes-preserve-unknown-fields: true - type: object - elementScope: - description: |- - ElementScope specifies whether to use the current list element as the scope for validation. Defaults to "true" if not specified. - When set to "false", "request.object" is used as the validation scope within the foreach - block to allow referencing other elements in the subtree. - type: boolean - foreach: - description: Foreach declares a nested foreach - iterator - x-kubernetes-preserve-unknown-fields: true - list: - description: |- - List specifies a JMESPath expression that results in one or more elements - to which the validation logic is applied. - type: string - pattern: - description: Pattern specifies an overlay-style - pattern used to check resources. - x-kubernetes-preserve-unknown-fields: true - preconditions: - description: |- - AnyAllConditions are used to determine if a policy rule should be applied by evaluating a - set of conditions. The declaration can contain nested `any` or `all` statements. - See: https://kyverno.io/docs/writing-policies/preconditions/ - properties: - all: - description: |- - AllConditions enable variable-based conditional rule execution. This is useful for - finer control of when an rule is applied. A condition can reference object data - using JMESPath notation. - Here, all of the conditions need to pass - items: - description: Condition defines variable-based - conditional criteria for rule execution. - properties: - key: - description: Key is the context entry - (using JMESPath) for conditional rule - evaluation. - x-kubernetes-preserve-unknown-fields: true - message: - description: Message is an optional - display message - type: string - operator: - description: |- - Operator is the conditional operation to perform. Valid operators are: - Equals, NotEquals, In, AnyIn, AllIn, NotIn, AnyNotIn, AllNotIn, GreaterThanOrEquals, - GreaterThan, LessThanOrEquals, LessThan, DurationGreaterThanOrEquals, DurationGreaterThan, - DurationLessThanOrEquals, DurationLessThan - enum: - - Equals - - NotEquals - - In - - AnyIn - - AllIn - - NotIn - - AnyNotIn - - AllNotIn - - GreaterThanOrEquals - - GreaterThan - - LessThanOrEquals - - LessThan - - DurationGreaterThanOrEquals - - DurationGreaterThan - - DurationLessThanOrEquals - - DurationLessThan - type: string - value: - description: |- - Value is the conditional value, or set of values. The values can be fixed set - or can be variables declared using JMESPath. - x-kubernetes-preserve-unknown-fields: true - type: object - type: array - any: - description: |- - AnyConditions enable variable-based conditional rule execution. This is useful for - finer control of when an rule is applied. A condition can reference object data - using JMESPath notation. - Here, at least one of the conditions need to pass - items: - description: Condition defines variable-based - conditional criteria for rule execution. - properties: - key: - description: Key is the context entry - (using JMESPath) for conditional rule - evaluation. - x-kubernetes-preserve-unknown-fields: true - message: - description: Message is an optional - display message - type: string - operator: - description: |- - Operator is the conditional operation to perform. Valid operators are: - Equals, NotEquals, In, AnyIn, AllIn, NotIn, AnyNotIn, AllNotIn, GreaterThanOrEquals, - GreaterThan, LessThanOrEquals, LessThan, DurationGreaterThanOrEquals, DurationGreaterThan, - DurationLessThanOrEquals, DurationLessThan - enum: - - Equals - - NotEquals - - In - - AnyIn - - AllIn - - NotIn - - AnyNotIn - - AllNotIn - - GreaterThanOrEquals - - GreaterThan - - LessThanOrEquals - - LessThan - - DurationGreaterThanOrEquals - - DurationGreaterThan - - DurationLessThanOrEquals - - DurationLessThan - type: string - value: - description: |- - Value is the conditional value, or set of values. The values can be fixed set - or can be variables declared using JMESPath. - x-kubernetes-preserve-unknown-fields: true - type: object - type: array - type: object - x-kubernetes-preserve-unknown-fields: true - type: object - type: array - manifests: - description: Manifest specifies conditions for manifest - verification - properties: - annotationDomain: - description: AnnotationDomain is custom domain of - annotation for message and signature. Default - is "cosign.sigstore.dev". - type: string - attestors: - description: Attestors specified the required attestors - (i.e. authorities) - items: - properties: - count: - description: |- - Count specifies the required number of entries that must match. If the count is null, all entries must match - (a logical AND). If the count is 1, at least one entry must match (a logical OR). If the count contains a - value N, then N must be less than or equal to the size of entries, and at least N entries must match. - minimum: 1 - type: integer - entries: - description: |- - Entries contains the available attestors. An attestor can be a static key, - attributes for keyless verification, or a nested attestor declaration. - items: - properties: - annotations: - additionalProperties: - type: string - description: |- - Annotations are used for image verification. - Every specified key-value pair must exist and match in the verified payload. - The payload may contain other key-value pairs. - type: object - attestor: - description: Attestor is a nested set - of Attestor used to specify a more - complex set of match authorities. - x-kubernetes-preserve-unknown-fields: true - certificates: - description: Certificates specifies - one or more certificates. - properties: - cert: - description: Cert is an optional - PEM-encoded public certificate. - type: string - certChain: - description: CertChain is an optional - PEM encoded set of certificates - used to verify. - type: string - ctlog: - description: |- - CTLog (certificate timestamp log) provides a configuration for validation of Signed Certificate - Timestamps (SCTs). If the value is unset, the default behavior by Cosign is used. - properties: - ignoreSCT: - description: |- - IgnoreSCT defines whether to use the Signed Certificate Timestamp (SCT) log to check for a certificate - timestamp. Default is false. Set to true if this was opted out during signing. - type: boolean - pubkey: - description: PubKey, if set, - is used to validate SCTs against - a custom source. - type: string - tsaCertChain: - description: |- - TSACertChain, if set, is the PEM-encoded certificate chain file for the RFC3161 timestamp authority. Must - contain the root CA certificate. Optionally may contain intermediate CA certificates, and - may contain the leaf TSA certificate if not present in the timestamurce. - type: string - type: object - rekor: - description: |- - Rekor provides configuration for the Rekor transparency log service. If an empty object - is provided the public instance of Rekor (https://rekor.sigstore.dev) is used. - properties: - ignoreTlog: - description: IgnoreTlog skips - transparency log verification. - type: boolean - pubkey: - description: |- - RekorPubKey is an optional PEM-encoded public key to use for a custom Rekor. - If set, this will be used to validate transparency log signatures from a custom Rekor. - type: string - url: - description: URL is the address - of the transparency log. Defaults - to the public Rekor log instance - https://rekor.sigstore.dev. - type: string - type: object - type: object - keyless: - description: |- - Keyless is a set of attribute used to verify a Sigstore keyless attestor. - See https://github.com/sigstore/cosign/blob/main/KEYLESS.md. - properties: - additionalExtensions: - additionalProperties: - type: string - description: AdditionalExtensions - are certificate-extensions used - for keyless signing. - type: object - ctlog: - description: |- - CTLog (certificate timestamp log) provides a configuration for validation of Signed Certificate - Timestamps (SCTs). If the value is unset, the default behavior by Cosign is used. - properties: - ignoreSCT: - description: |- - IgnoreSCT defines whether to use the Signed Certificate Timestamp (SCT) log to check for a certificate - timestamp. Default is false. Set to true if this was opted out during signing. - type: boolean - pubkey: - description: PubKey, if set, - is used to validate SCTs against - a custom source. - type: string - tsaCertChain: - description: |- - TSACertChain, if set, is the PEM-encoded certificate chain file for the RFC3161 timestamp authority. Must - contain the root CA certificate. Optionally may contain intermediate CA certificates, and - may contain the leaf TSA certificate if not present in the timestamurce. - type: string - type: object - issuer: - description: Issuer is the certificate - issuer used for keyless signing. - type: string - issuerRegExp: - description: IssuerRegExp is the - regular expression to match certificate - issuer used for keyless signing. - type: string - rekor: - description: |- - Rekor provides configuration for the Rekor transparency log service. If an empty object - is provided the public instance of Rekor (https://rekor.sigstore.dev) is used. - properties: - ignoreTlog: - description: IgnoreTlog skips - transparency log verification. - type: boolean - pubkey: - description: |- - RekorPubKey is an optional PEM-encoded public key to use for a custom Rekor. - If set, this will be used to validate transparency log signatures from a custom Rekor. - type: string - url: - description: URL is the address - of the transparency log. Defaults - to the public Rekor log instance - https://rekor.sigstore.dev. - type: string - type: object - roots: - description: |- - Roots is an optional set of PEM encoded trusted root certificates. - If not provided, the system roots are used. - type: string - subject: - description: Subject is the verified - identity used for keyless signing, - for example the email address. - type: string - subjectRegExp: - description: SubjectRegExp is the - regular expression to match identity - used for keyless signing, for - example the email address. - type: string - type: object - keys: - description: Keys specifies one or more - public keys. - properties: - ctlog: - description: |- - CTLog (certificate timestamp log) provides a configuration for validation of Signed Certificate - Timestamps (SCTs). If the value is unset, the default behavior by Cosign is used. - properties: - ignoreSCT: - description: |- - IgnoreSCT defines whether to use the Signed Certificate Timestamp (SCT) log to check for a certificate - timestamp. Default is false. Set to true if this was opted out during signing. - type: boolean - pubkey: - description: PubKey, if set, - is used to validate SCTs against - a custom source. - type: string - tsaCertChain: - description: |- - TSACertChain, if set, is the PEM-encoded certificate chain file for the RFC3161 timestamp authority. Must - contain the root CA certificate. Optionally may contain intermediate CA certificates, and - may contain the leaf TSA certificate if not present in the timestamurce. - type: string - type: object - kms: - description: |- - KMS provides the URI to the public key stored in a Key Management System. See: - https://github.com/sigstore/cosign/blob/main/KMS.md - type: string - publicKeys: - description: |- - Keys is a set of X.509 public keys used to verify image signatures. The keys can be directly - specified or can be a variable reference to a key specified in a ConfigMap (see - https://kyverno.io/docs/writing-policies/variables/), or reference a standard Kubernetes Secret - elsewhere in the cluster by specifying it in the format "k8s:///". - The named Secret must specify a key `cosign.pub` containing the public key used for - verification, (see https://github.com/sigstore/cosign/blob/main/KMS.md#kubernetes-secret). - When multiple keys are specified each key is processed as a separate staticKey entry - (.attestors[*].entries.keys) within the set of attestors and the count is applied across the keys. - type: string - rekor: - description: |- - Rekor provides configuration for the Rekor transparency log service. If an empty object - is provided the public instance of Rekor (https://rekor.sigstore.dev) is used. - properties: - ignoreTlog: - description: IgnoreTlog skips - transparency log verification. - type: boolean - pubkey: - description: |- - RekorPubKey is an optional PEM-encoded public key to use for a custom Rekor. - If set, this will be used to validate transparency log signatures from a custom Rekor. - type: string - url: - description: URL is the address - of the transparency log. Defaults - to the public Rekor log instance - https://rekor.sigstore.dev. - type: string - type: object - secret: - description: Reference to a Secret - resource that contains a public - key - properties: - name: - description: Name of the secret. - The provided secret must contain - a key named cosign.pub. - type: string - namespace: - description: Namespace name - where the Secret exists. - type: string - required: - - name - - namespace - type: object - signatureAlgorithm: - default: sha256 - description: Deprecated. Use attestor.signatureAlgorithm - instead. - type: string - type: object - repository: - description: |- - Repository is an optional alternate OCI repository to use for signatures and attestations that match this rule. - If specified Repository will override other OCI image repository locations for this Attestor. - type: string - signatureAlgorithm: - default: sha256 - description: Specify signature algorithm - for public keys. Supported values - are sha224, sha256, sha384 and sha512. - type: string - type: object - type: array - type: object - type: array - dryRun: - description: DryRun configuration - properties: - enable: - type: boolean - namespace: - type: string - type: object - ignoreFields: - description: Fields which will be ignored while - comparing manifests. - items: - properties: - fields: - items: - type: string - type: array - objects: - items: - properties: - group: - type: string - kind: - type: string - name: - type: string - namespace: - type: string - version: - type: string - type: object - type: array - type: object - type: array - repository: - description: |- - Repository is an optional alternate OCI repository to use for resource bundle reference. - The repository can be overridden per Attestor or Attestation. - type: string - type: object - message: - description: Message specifies a custom message to be - displayed on failure. - type: string - pattern: - description: Pattern specifies an overlay-style pattern - used to check resources. - x-kubernetes-preserve-unknown-fields: true - podSecurity: - description: |- - PodSecurity applies exemptions for Kubernetes Pod Security admission - by specifying exclusions for Pod Security Standards controls. - properties: - exclude: - description: Exclude specifies the Pod Security - Standard controls to be excluded. - items: - description: PodSecurityStandard specifies the - Pod Security Standard controls to be excluded. - properties: - controlName: - description: |- - ControlName specifies the name of the Pod Security Standard control. - See: https://kubernetes.io/docs/concepts/security/pod-security-standards/ - enum: - - HostProcess - - Host Namespaces - - Privileged Containers - - Capabilities - - HostPath Volumes - - Host Ports - - AppArmor - - SELinux - - /proc Mount Type - - Seccomp - - Sysctls - - Volume Types - - Privilege Escalation - - Running as Non-root - - Running as Non-root user - type: string - images: - description: |- - Images selects matching containers and applies the container level PSS. - Each image is the image name consisting of the registry address, repository, image, and tag. - Empty list matches no containers, PSS checks are applied at the pod level only. - Wildcards ('*' and '?') are allowed. See: https://kubernetes.io/docs/concepts/containers/images. - items: - type: string - type: array - restrictedField: - description: |- - RestrictedField selects the field for the given Pod Security Standard control. - When not set, all restricted fields for the control are selected. - type: string - values: - description: Values defines the allowed values - that can be excluded. - items: - type: string - type: array - required: - - controlName - type: object - type: array - level: - description: |- - Level defines the Pod Security Standard level to be applied to workloads. - Allowed values are privileged, baseline, and restricted. - enum: - - privileged - - baseline - - restricted - type: string - version: - description: |- - Version defines the Pod Security Standard versions that Kubernetes supports. - Allowed values are v1.19, v1.20, v1.21, v1.22, v1.23, v1.24, v1.25, v1.26, v1.27, v1.28, v1.29, latest. Defaults to latest. - enum: - - v1.19 - - v1.20 - - v1.21 - - v1.22 - - v1.23 - - v1.24 - - v1.25 - - v1.26 - - v1.27 - - v1.28 - - v1.29 - - latest - type: string - type: object - type: object - verifyImages: - description: VerifyImages is used to verify image signatures - and mutate them to add a digest - items: - description: |- - ImageVerification validates that images that match the specified pattern - are signed with the supplied public key. Once the image is verified it is - mutated to include the SHA digest retrieved during the registration. - properties: - additionalExtensions: - additionalProperties: - type: string - description: Deprecated. - type: object - annotations: - additionalProperties: - type: string - description: Deprecated. Use annotations per Attestor - instead. - type: object - attestations: - description: |- - Attestations are optional checks for signed in-toto Statements used to verify the image. - See https://github.com/in-toto/attestation. Kyverno fetches signed attestations from the - OCI registry and decodes them into a list of Statement declarations. - items: - description: |- - Attestation are checks for signed in-toto Statements that are used to verify the image. - See https://github.com/in-toto/attestation. Kyverno fetches signed attestations from the - OCI registry and decodes them into a list of Statements. - properties: - attestors: - description: Attestors specify the required - attestors (i.e. authorities). - items: - properties: - count: - description: |- - Count specifies the required number of entries that must match. If the count is null, all entries must match - (a logical AND). If the count is 1, at least one entry must match (a logical OR). If the count contains a - value N, then N must be less than or equal to the size of entries, and at least N entries must match. - minimum: 1 - type: integer - entries: - description: |- - Entries contains the available attestors. An attestor can be a static key, - attributes for keyless verification, or a nested attestor declaration. - items: - properties: - annotations: - additionalProperties: - type: string - description: |- - Annotations are used for image verification. - Every specified key-value pair must exist and match in the verified payload. - The payload may contain other key-value pairs. - type: object - attestor: - description: Attestor is a nested - set of Attestor used to specify - a more complex set of match authorities. - x-kubernetes-preserve-unknown-fields: true - certificates: - description: Certificates specifies - one or more certificates. - properties: - cert: - description: Cert is an optional - PEM-encoded public certificate. - type: string - certChain: - description: CertChain is an - optional PEM encoded set of - certificates used to verify. - type: string - ctlog: - description: |- - CTLog (certificate timestamp log) provides a configuration for validation of Signed Certificate - Timestamps (SCTs). If the value is unset, the default behavior by Cosign is used. - properties: - ignoreSCT: - description: |- - IgnoreSCT defines whether to use the Signed Certificate Timestamp (SCT) log to check for a certificate - timestamp. Default is false. Set to true if this was opted out during signing. - type: boolean - pubkey: - description: PubKey, if - set, is used to validate - SCTs against a custom - source. - type: string - tsaCertChain: - description: |- - TSACertChain, if set, is the PEM-encoded certificate chain file for the RFC3161 timestamp authority. Must - contain the root CA certificate. Optionally may contain intermediate CA certificates, and - may contain the leaf TSA certificate if not present in the timestamurce. - type: string - type: object - rekor: - description: |- - Rekor provides configuration for the Rekor transparency log service. If an empty object - is provided the public instance of Rekor (https://rekor.sigstore.dev) is used. - properties: - ignoreTlog: - description: IgnoreTlog - skips transparency log - verification. - type: boolean - pubkey: - description: |- - RekorPubKey is an optional PEM-encoded public key to use for a custom Rekor. - If set, this will be used to validate transparency log signatures from a custom Rekor. - type: string - url: - description: URL is the - address of the transparency - log. Defaults to the public - Rekor log instance https://rekor.sigstore.dev. - type: string - type: object - type: object - keyless: - description: |- - Keyless is a set of attribute used to verify a Sigstore keyless attestor. - See https://github.com/sigstore/cosign/blob/main/KEYLESS.md. - properties: - additionalExtensions: - additionalProperties: - type: string - description: AdditionalExtensions - are certificate-extensions - used for keyless signing. - type: object - ctlog: - description: |- - CTLog (certificate timestamp log) provides a configuration for validation of Signed Certificate - Timestamps (SCTs). If the value is unset, the default behavior by Cosign is used. - properties: - ignoreSCT: - description: |- - IgnoreSCT defines whether to use the Signed Certificate Timestamp (SCT) log to check for a certificate - timestamp. Default is false. Set to true if this was opted out during signing. - type: boolean - pubkey: - description: PubKey, if - set, is used to validate - SCTs against a custom - source. - type: string - tsaCertChain: - description: |- - TSACertChain, if set, is the PEM-encoded certificate chain file for the RFC3161 timestamp authority. Must - contain the root CA certificate. Optionally may contain intermediate CA certificates, and - may contain the leaf TSA certificate if not present in the timestamurce. - type: string - type: object - issuer: - description: Issuer is the certificate - issuer used for keyless signing. - type: string - issuerRegExp: - description: IssuerRegExp is - the regular expression to - match certificate issuer used - for keyless signing. - type: string - rekor: - description: |- - Rekor provides configuration for the Rekor transparency log service. If an empty object - is provided the public instance of Rekor (https://rekor.sigstore.dev) is used. - properties: - ignoreTlog: - description: IgnoreTlog - skips transparency log - verification. - type: boolean - pubkey: - description: |- - RekorPubKey is an optional PEM-encoded public key to use for a custom Rekor. - If set, this will be used to validate transparency log signatures from a custom Rekor. - type: string - url: - description: URL is the - address of the transparency - log. Defaults to the public - Rekor log instance https://rekor.sigstore.dev. - type: string - type: object - roots: - description: |- - Roots is an optional set of PEM encoded trusted root certificates. - If not provided, the system roots are used. - type: string - subject: - description: Subject is the - verified identity used for - keyless signing, for example - the email address. - type: string - subjectRegExp: - description: SubjectRegExp is - the regular expression to - match identity used for keyless - signing, for example the email - address. - type: string - type: object - keys: - description: Keys specifies one - or more public keys. - properties: - ctlog: - description: |- - CTLog (certificate timestamp log) provides a configuration for validation of Signed Certificate - Timestamps (SCTs). If the value is unset, the default behavior by Cosign is used. - properties: - ignoreSCT: - description: |- - IgnoreSCT defines whether to use the Signed Certificate Timestamp (SCT) log to check for a certificate - timestamp. Default is false. Set to true if this was opted out during signing. - type: boolean - pubkey: - description: PubKey, if - set, is used to validate - SCTs against a custom - source. - type: string - tsaCertChain: - description: |- - TSACertChain, if set, is the PEM-encoded certificate chain file for the RFC3161 timestamp authority. Must - contain the root CA certificate. Optionally may contain intermediate CA certificates, and - may contain the leaf TSA certificate if not present in the timestamurce. - type: string - type: object - kms: - description: |- - KMS provides the URI to the public key stored in a Key Management System. See: - https://github.com/sigstore/cosign/blob/main/KMS.md - type: string - publicKeys: - description: |- - Keys is a set of X.509 public keys used to verify image signatures. The keys can be directly - specified or can be a variable reference to a key specified in a ConfigMap (see - https://kyverno.io/docs/writing-policies/variables/), or reference a standard Kubernetes Secret - elsewhere in the cluster by specifying it in the format "k8s:///". - The named Secret must specify a key `cosign.pub` containing the public key used for - verification, (see https://github.com/sigstore/cosign/blob/main/KMS.md#kubernetes-secret). - When multiple keys are specified each key is processed as a separate staticKey entry - (.attestors[*].entries.keys) within the set of attestors and the count is applied across the keys. - type: string - rekor: - description: |- - Rekor provides configuration for the Rekor transparency log service. If an empty object - is provided the public instance of Rekor (https://rekor.sigstore.dev) is used. - properties: - ignoreTlog: - description: IgnoreTlog - skips transparency log - verification. - type: boolean - pubkey: - description: |- - RekorPubKey is an optional PEM-encoded public key to use for a custom Rekor. - If set, this will be used to validate transparency log signatures from a custom Rekor. - type: string - url: - description: URL is the - address of the transparency - log. Defaults to the public - Rekor log instance https://rekor.sigstore.dev. - type: string - type: object - secret: - description: Reference to a - Secret resource that contains - a public key - properties: - name: - description: Name of the - secret. The provided secret - must contain a key named - cosign.pub. - type: string - namespace: - description: Namespace name - where the Secret exists. - type: string - required: - - name - - namespace - type: object - signatureAlgorithm: - default: sha256 - description: Deprecated. Use - attestor.signatureAlgorithm - instead. - type: string - type: object - repository: - description: |- - Repository is an optional alternate OCI repository to use for signatures and attestations that match this rule. - If specified Repository will override other OCI image repository locations for this Attestor. - type: string - signatureAlgorithm: - default: sha256 - description: Specify signature algorithm - for public keys. Supported values - are sha224, sha256, sha384 and - sha512. - type: string - type: object - type: array - type: object - type: array - conditions: - description: |- - Conditions are used to verify attributes within a Predicate. If no Conditions are specified - the attestation check is satisfied as long there are predicates that match the predicate type. - items: - description: |- - AnyAllConditions consists of conditions wrapped denoting a logical criteria to be fulfilled. - AnyConditions get fulfilled when at least one of its sub-conditions passes. - AllConditions get fulfilled only when all of its sub-conditions pass. - properties: - all: - description: |- - AllConditions enable variable-based conditional rule execution. This is useful for - finer control of when an rule is applied. A condition can reference object data - using JMESPath notation. - Here, all of the conditions need to pass - items: - description: Condition defines variable-based - conditional criteria for rule execution. - properties: - key: - description: Key is the context - entry (using JMESPath) for conditional - rule evaluation. - x-kubernetes-preserve-unknown-fields: true - message: - description: Message is an optional - display message - type: string - operator: - description: |- - Operator is the conditional operation to perform. Valid operators are: - Equals, NotEquals, In, AnyIn, AllIn, NotIn, AnyNotIn, AllNotIn, GreaterThanOrEquals, - GreaterThan, LessThanOrEquals, LessThan, DurationGreaterThanOrEquals, DurationGreaterThan, - DurationLessThanOrEquals, DurationLessThan - enum: - - Equals - - NotEquals - - In - - AnyIn - - AllIn - - NotIn - - AnyNotIn - - AllNotIn - - GreaterThanOrEquals - - GreaterThan - - LessThanOrEquals - - LessThan - - DurationGreaterThanOrEquals - - DurationGreaterThan - - DurationLessThanOrEquals - - DurationLessThan - type: string - value: - description: |- - Value is the conditional value, or set of values. The values can be fixed set - or can be variables declared using JMESPath. - x-kubernetes-preserve-unknown-fields: true - type: object - type: array - any: - description: |- - AnyConditions enable variable-based conditional rule execution. This is useful for - finer control of when an rule is applied. A condition can reference object data - using JMESPath notation. - Here, at least one of the conditions need to pass - items: - description: Condition defines variable-based - conditional criteria for rule execution. - properties: - key: - description: Key is the context - entry (using JMESPath) for conditional - rule evaluation. - x-kubernetes-preserve-unknown-fields: true - message: - description: Message is an optional - display message - type: string - operator: - description: |- - Operator is the conditional operation to perform. Valid operators are: - Equals, NotEquals, In, AnyIn, AllIn, NotIn, AnyNotIn, AllNotIn, GreaterThanOrEquals, - GreaterThan, LessThanOrEquals, LessThan, DurationGreaterThanOrEquals, DurationGreaterThan, - DurationLessThanOrEquals, DurationLessThan - enum: - - Equals - - NotEquals - - In - - AnyIn - - AllIn - - NotIn - - AnyNotIn - - AllNotIn - - GreaterThanOrEquals - - GreaterThan - - LessThanOrEquals - - LessThan - - DurationGreaterThanOrEquals - - DurationGreaterThan - - DurationLessThanOrEquals - - DurationLessThan - type: string - value: - description: |- - Value is the conditional value, or set of values. The values can be fixed set - or can be variables declared using JMESPath. - x-kubernetes-preserve-unknown-fields: true - type: object - type: array - type: object - type: array - name: - description: Name is the variable name. - type: string - predicateType: - description: Deprecated in favour of 'Type', - to be removed soon - type: string - type: - description: Type defines the type of attestation - contained within the Statement. - type: string - type: object - type: array - attestors: - description: Attestors specified the required attestors - (i.e. authorities) - items: - properties: - count: - description: |- - Count specifies the required number of entries that must match. If the count is null, all entries must match - (a logical AND). If the count is 1, at least one entry must match (a logical OR). If the count contains a - value N, then N must be less than or equal to the size of entries, and at least N entries must match. - minimum: 1 - type: integer - entries: - description: |- - Entries contains the available attestors. An attestor can be a static key, - attributes for keyless verification, or a nested attestor declaration. - items: - properties: - annotations: - additionalProperties: - type: string - description: |- - Annotations are used for image verification. - Every specified key-value pair must exist and match in the verified payload. - The payload may contain other key-value pairs. - type: object - attestor: - description: Attestor is a nested set - of Attestor used to specify a more complex - set of match authorities. - x-kubernetes-preserve-unknown-fields: true - certificates: - description: Certificates specifies one - or more certificates. - properties: - cert: - description: Cert is an optional PEM-encoded - public certificate. - type: string - certChain: - description: CertChain is an optional - PEM encoded set of certificates - used to verify. - type: string - ctlog: - description: |- - CTLog (certificate timestamp log) provides a configuration for validation of Signed Certificate - Timestamps (SCTs). If the value is unset, the default behavior by Cosign is used. - properties: - ignoreSCT: - description: |- - IgnoreSCT defines whether to use the Signed Certificate Timestamp (SCT) log to check for a certificate - timestamp. Default is false. Set to true if this was opted out during signing. - type: boolean - pubkey: - description: PubKey, if set, is - used to validate SCTs against - a custom source. - type: string - tsaCertChain: - description: |- - TSACertChain, if set, is the PEM-encoded certificate chain file for the RFC3161 timestamp authority. Must - contain the root CA certificate. Optionally may contain intermediate CA certificates, and - may contain the leaf TSA certificate if not present in the timestamurce. - type: string - type: object - rekor: - description: |- - Rekor provides configuration for the Rekor transparency log service. If an empty object - is provided the public instance of Rekor (https://rekor.sigstore.dev) is used. - properties: - ignoreTlog: - description: IgnoreTlog skips - transparency log verification. - type: boolean - pubkey: - description: |- - RekorPubKey is an optional PEM-encoded public key to use for a custom Rekor. - If set, this will be used to validate transparency log signatures from a custom Rekor. - type: string - url: - description: URL is the address - of the transparency log. Defaults - to the public Rekor log instance - https://rekor.sigstore.dev. - type: string - type: object - type: object - keyless: - description: |- - Keyless is a set of attribute used to verify a Sigstore keyless attestor. - See https://github.com/sigstore/cosign/blob/main/KEYLESS.md. - properties: - additionalExtensions: - additionalProperties: - type: string - description: AdditionalExtensions - are certificate-extensions used - for keyless signing. - type: object - ctlog: - description: |- - CTLog (certificate timestamp log) provides a configuration for validation of Signed Certificate - Timestamps (SCTs). If the value is unset, the default behavior by Cosign is used. - properties: - ignoreSCT: - description: |- - IgnoreSCT defines whether to use the Signed Certificate Timestamp (SCT) log to check for a certificate - timestamp. Default is false. Set to true if this was opted out during signing. - type: boolean - pubkey: - description: PubKey, if set, is - used to validate SCTs against - a custom source. - type: string - tsaCertChain: - description: |- - TSACertChain, if set, is the PEM-encoded certificate chain file for the RFC3161 timestamp authority. Must - contain the root CA certificate. Optionally may contain intermediate CA certificates, and - may contain the leaf TSA certificate if not present in the timestamurce. - type: string - type: object - issuer: - description: Issuer is the certificate - issuer used for keyless signing. - type: string - issuerRegExp: - description: IssuerRegExp is the regular - expression to match certificate - issuer used for keyless signing. - type: string - rekor: - description: |- - Rekor provides configuration for the Rekor transparency log service. If an empty object - is provided the public instance of Rekor (https://rekor.sigstore.dev) is used. - properties: - ignoreTlog: - description: IgnoreTlog skips - transparency log verification. - type: boolean - pubkey: - description: |- - RekorPubKey is an optional PEM-encoded public key to use for a custom Rekor. - If set, this will be used to validate transparency log signatures from a custom Rekor. - type: string - url: - description: URL is the address - of the transparency log. Defaults - to the public Rekor log instance - https://rekor.sigstore.dev. - type: string - type: object - roots: - description: |- - Roots is an optional set of PEM encoded trusted root certificates. - If not provided, the system roots are used. - type: string - subject: - description: Subject is the verified - identity used for keyless signing, - for example the email address. - type: string - subjectRegExp: - description: SubjectRegExp is the - regular expression to match identity - used for keyless signing, for example - the email address. - type: string - type: object - keys: - description: Keys specifies one or more - public keys. - properties: - ctlog: - description: |- - CTLog (certificate timestamp log) provides a configuration for validation of Signed Certificate - Timestamps (SCTs). If the value is unset, the default behavior by Cosign is used. - properties: - ignoreSCT: - description: |- - IgnoreSCT defines whether to use the Signed Certificate Timestamp (SCT) log to check for a certificate - timestamp. Default is false. Set to true if this was opted out during signing. - type: boolean - pubkey: - description: PubKey, if set, is - used to validate SCTs against - a custom source. - type: string - tsaCertChain: - description: |- - TSACertChain, if set, is the PEM-encoded certificate chain file for the RFC3161 timestamp authority. Must - contain the root CA certificate. Optionally may contain intermediate CA certificates, and - may contain the leaf TSA certificate if not present in the timestamurce. - type: string - type: object - kms: - description: |- - KMS provides the URI to the public key stored in a Key Management System. See: - https://github.com/sigstore/cosign/blob/main/KMS.md - type: string - publicKeys: - description: |- - Keys is a set of X.509 public keys used to verify image signatures. The keys can be directly - specified or can be a variable reference to a key specified in a ConfigMap (see - https://kyverno.io/docs/writing-policies/variables/), or reference a standard Kubernetes Secret - elsewhere in the cluster by specifying it in the format "k8s:///". - The named Secret must specify a key `cosign.pub` containing the public key used for - verification, (see https://github.com/sigstore/cosign/blob/main/KMS.md#kubernetes-secret). - When multiple keys are specified each key is processed as a separate staticKey entry - (.attestors[*].entries.keys) within the set of attestors and the count is applied across the keys. - type: string - rekor: - description: |- - Rekor provides configuration for the Rekor transparency log service. If an empty object - is provided the public instance of Rekor (https://rekor.sigstore.dev) is used. - properties: - ignoreTlog: - description: IgnoreTlog skips - transparency log verification. - type: boolean - pubkey: - description: |- - RekorPubKey is an optional PEM-encoded public key to use for a custom Rekor. - If set, this will be used to validate transparency log signatures from a custom Rekor. - type: string - url: - description: URL is the address - of the transparency log. Defaults - to the public Rekor log instance - https://rekor.sigstore.dev. - type: string - type: object - secret: - description: Reference to a Secret - resource that contains a public - key - properties: - name: - description: Name of the secret. - The provided secret must contain - a key named cosign.pub. - type: string - namespace: - description: Namespace name where - the Secret exists. - type: string - required: - - name - - namespace - type: object - signatureAlgorithm: - default: sha256 - description: Deprecated. Use attestor.signatureAlgorithm - instead. - type: string - type: object - repository: - description: |- - Repository is an optional alternate OCI repository to use for signatures and attestations that match this rule. - If specified Repository will override other OCI image repository locations for this Attestor. - type: string - signatureAlgorithm: - default: sha256 - description: Specify signature algorithm - for public keys. Supported values are - sha224, sha256, sha384 and sha512. - type: string - type: object - type: array - type: object - type: array - cosignOCI11: - description: |- - CosignOCI11 enables the experimental OCI 1.1 behaviour in cosign image verification. - Defaults to false. - type: boolean - failureAction: - description: Allowed values are Audit or Enforce. - enum: - - Audit - - Enforce - type: string - image: - description: Deprecated. Use ImageReferences instead. - type: string - imageReferences: - description: |- - ImageReferences is a list of matching image reference patterns. At least one pattern in the - list must match the image for the rule to apply. Each image reference consists of a registry - address (defaults to docker.io), repository, image, and tag (defaults to latest). - Wildcards ('*' and '?') are allowed. See: https://kubernetes.io/docs/concepts/containers/images. - items: - type: string - type: array - imageRegistryCredentials: - description: ImageRegistryCredentials provides credentials - that will be used for authentication with registry. - properties: - allowInsecureRegistry: - description: AllowInsecureRegistry allows insecure - access to a registry. - type: boolean - providers: - description: |- - Providers specifies a list of OCI Registry names, whose authentication providers are provided. - It can be of one of these values: default,google,azure,amazon,github. - items: - description: ImageRegistryCredentialsProvidersType - provides the list of credential providers - required. - enum: - - default - - amazon - - azure - - google - - github - type: string - type: array - secrets: - description: |- - Secrets specifies a list of secrets that are provided for credentials. - Secrets must live in the Kyverno namespace. - items: - type: string - type: array - type: object - issuer: - description: Deprecated. Use KeylessAttestor instead. - type: string - key: - description: Deprecated. Use StaticKeyAttestor instead. - type: string - mutateDigest: - default: true - description: |- - MutateDigest enables replacement of image tags with digests. - Defaults to true. - type: boolean - repository: - description: |- - Repository is an optional alternate OCI repository to use for image signatures and attestations that match this rule. - If specified Repository will override the default OCI image repository configured for the installation. - The repository can also be overridden per Attestor or Attestation. - type: string - required: - default: true - description: Required validates that images are verified - i.e. have matched passed a signature or attestation - check. - type: boolean - roots: - description: Deprecated. Use KeylessAttestor instead. - type: string - skipImageReferences: - description: |- - SkipImageReferences is a list of matching image reference patterns that should be skipped. - At least one pattern in the list must match the image for the rule to be skipped. Each image reference - consists of a registry address (defaults to docker.io), repository, image, and tag (defaults to latest). - Wildcards ('*' and '?') are allowed. See: https://kubernetes.io/docs/concepts/containers/images. - items: - type: string - type: array - subject: - description: Deprecated. Use KeylessAttestor instead. - type: string - type: - description: |- - Type specifies the method of signature validation. The allowed options - are Cosign, Sigstore Bundle and Notary. By default Cosign is used if a type is not specified. - enum: - - Cosign - - SigstoreBundle - - Notary - type: string - useCache: - default: true - description: UseCache enables caching of image verify - responses for this rule. - type: boolean - validate: - description: |- - Validation checks conditions across multiple image - verification attestations or context entries - properties: - deny: - description: Deny defines conditions used to pass - or fail a validation rule. - properties: - conditions: - description: |- - Multiple conditions can be declared under an `any` or `all` statement. A direct list - of conditions (without `any` or `all` statements) is also supported for backwards compatibility - but will be deprecated in the next major release. - See: https://kyverno.io/docs/writing-policies/validate/#deny-rules - x-kubernetes-preserve-unknown-fields: true - type: object - message: - description: Message specifies a custom message - to be displayed on failure. - type: string - type: object - verifyDigest: - default: true - description: VerifyDigest validates that images have - a digest. - type: boolean - type: object - type: array - required: - - match - - name - type: object - type: array - type: object - conditions: - items: - description: Condition contains details for one aspect of the current - state of this API Resource. - properties: - lastTransitionTime: - description: |- - lastTransitionTime is the last time the condition transitioned from one status to another. - This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable. - format: date-time - type: string - message: - description: |- - message is a human readable message indicating details about the transition. - This may be an empty string. - maxLength: 32768 - type: string - observedGeneration: - description: |- - observedGeneration represents the .metadata.generation that the condition was set based upon. - For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date - with respect to the current state of the instance. - format: int64 - minimum: 0 - type: integer - reason: - description: |- - reason contains a programmatic identifier indicating the reason for the condition's last transition. - Producers of specific condition types may define expected values and meanings for this field, - and whether the values are considered a guaranteed API. - The value should be a CamelCase string. - This field may not be empty. - maxLength: 1024 - minLength: 1 - pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ - type: string - status: - description: status of the condition, one of True, False, Unknown. - enum: - - "True" - - "False" - - Unknown - type: string - type: - description: type of condition in CamelCase or in foo.example.com/CamelCase. - maxLength: 316 - pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ - type: string - required: - - lastTransitionTime - - message - - reason - - status - - type - type: object - type: array - ready: - description: Deprecated in favor of Conditions - type: boolean - rulecount: - description: |- - RuleCountStatus contains four variables which describes counts for - validate, generate, mutate and verify images rules - properties: - generate: - description: Count for generate rules in policy - type: integer - mutate: - description: Count for mutate rules in policy - type: integer - validate: - description: Count for validate rules in policy - type: integer - verifyimages: - description: Count for verify image rules in policy - type: integer - required: - - generate - - mutate - - validate - - verifyimages - type: object - validatingadmissionpolicy: - description: ValidatingAdmissionPolicy contains status information - properties: - generated: - description: Generated indicates whether a validating admission - policy is generated from the policy or not - type: boolean - message: - description: |- - Message is a human readable message indicating details about the generation of validating admission policy - It is an empty string when validating admission policy is successfully generated. - type: string - required: - - generated - - message - type: object - type: object - required: - - spec - type: object - served: true - storage: false - subresources: - status: {} ---- -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - labels: - app.kubernetes.io/component: crds - app.kubernetes.io/instance: kyverno - app.kubernetes.io/managed-by: Helm - app.kubernetes.io/part-of: kyverno-crds - app.kubernetes.io/version: 3.5.1 - helm.sh/chart: crds-3.5.1 - annotations: - controller-gen.kubebuilder.io/version: v0.17.3 - name: policyexceptions.kyverno.io -spec: - group: kyverno.io - names: - categories: - - kyverno - kind: PolicyException - listKind: PolicyExceptionList - plural: policyexceptions - shortNames: - - polex - singular: policyexception - scope: Namespaced - versions: - - name: v2 - schema: - openAPIV3Schema: - description: PolicyException declares resources to be excluded from specified - policies. - properties: - apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - type: string - kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - metadata: - type: object - spec: - description: Spec declares policy exception behaviors. - properties: - background: - description: |- - Background controls if exceptions are applied to existing policies during a background scan. - Optional. Default value is "true". The value must be set to "false" if the policy rule - uses variables that are only available in the admission review request (e.g. user name). - type: boolean - conditions: - description: |- - Conditions are used to determine if a resource applies to the exception by evaluating a - set of conditions. The declaration can contain nested `any` or `all` statements. - properties: - all: - description: |- - AllConditions enable variable-based conditional rule execution. This is useful for - finer control of when an rule is applied. A condition can reference object data - using JMESPath notation. - Here, all of the conditions need to pass. - items: - properties: - key: - description: Key is the context entry (using JMESPath) for - conditional rule evaluation. - x-kubernetes-preserve-unknown-fields: true - message: - description: Message is an optional display message - type: string - operator: - description: |- - Operator is the conditional operation to perform. Valid operators are: - Equals, NotEquals, In, AnyIn, AllIn, NotIn, AnyNotIn, AllNotIn, GreaterThanOrEquals, - GreaterThan, LessThanOrEquals, LessThan, DurationGreaterThanOrEquals, DurationGreaterThan, - DurationLessThanOrEquals, DurationLessThan - enum: - - Equals - - NotEquals - - AnyIn - - AllIn - - AnyNotIn - - AllNotIn - - GreaterThanOrEquals - - GreaterThan - - LessThanOrEquals - - LessThan - - DurationGreaterThanOrEquals - - DurationGreaterThan - - DurationLessThanOrEquals - - DurationLessThan - type: string - value: - description: |- - Value is the conditional value, or set of values. The values can be fixed set - or can be variables declared using JMESPath. - x-kubernetes-preserve-unknown-fields: true - type: object - type: array - any: - description: |- - AnyConditions enable variable-based conditional rule execution. This is useful for - finer control of when an rule is applied. A condition can reference object data - using JMESPath notation. - Here, at least one of the conditions need to pass. - items: - properties: - key: - description: Key is the context entry (using JMESPath) for - conditional rule evaluation. - x-kubernetes-preserve-unknown-fields: true - message: - description: Message is an optional display message - type: string - operator: - description: |- - Operator is the conditional operation to perform. Valid operators are: - Equals, NotEquals, In, AnyIn, AllIn, NotIn, AnyNotIn, AllNotIn, GreaterThanOrEquals, - GreaterThan, LessThanOrEquals, LessThan, DurationGreaterThanOrEquals, DurationGreaterThan, - DurationLessThanOrEquals, DurationLessThan - enum: - - Equals - - NotEquals - - AnyIn - - AllIn - - AnyNotIn - - AllNotIn - - GreaterThanOrEquals - - GreaterThan - - LessThanOrEquals - - LessThan - - DurationGreaterThanOrEquals - - DurationGreaterThan - - DurationLessThanOrEquals - - DurationLessThan - type: string - value: - description: |- - Value is the conditional value, or set of values. The values can be fixed set - or can be variables declared using JMESPath. - x-kubernetes-preserve-unknown-fields: true - type: object - type: array - type: object - exceptions: - description: Exceptions is a list policy/rules to be excluded - items: - description: Exception stores infos about a policy and rules - properties: - policyName: - description: |- - PolicyName identifies the policy to which the exception is applied. - The policy name uses the format / unless it - references a ClusterPolicy. - type: string - ruleNames: - description: RuleNames identifies the rules to which the exception - is applied. - items: - type: string - type: array - required: - - policyName - - ruleNames - type: object - type: array - match: - description: Match defines match clause used to check if a resource - applies to the exception - not: - required: - - any - - all - properties: - all: - description: All allows specifying resources which will be ANDed - items: - description: ResourceFilter allow users to "AND" or "OR" between - resources - properties: - clusterRoles: - description: ClusterRoles is the list of cluster-wide role - names for the user. - items: - type: string - type: array - resources: - description: ResourceDescription contains information about - the resource being created or modified. - not: - required: - - name - - names - properties: - annotations: - additionalProperties: - type: string - description: |- - Annotations is a map of annotations (key-value pairs of type string). Annotation keys - and values support the wildcard characters "*" (matches zero or many characters) and - "?" (matches at least one character). - type: object - kinds: - description: Kinds is a list of resource kinds. - items: - type: string - type: array - name: - description: |- - Name is the name of the resource. The name supports wildcard characters - "*" (matches zero or many characters) and "?" (at least one character). - NOTE: "Name" is being deprecated in favor of "Names". - type: string - names: - description: |- - Names are the names of the resources. Each name supports wildcard characters - "*" (matches zero or many characters) and "?" (at least one character). - items: - type: string - type: array - namespaceSelector: - description: |- - NamespaceSelector is a label selector for the resource namespace. Label keys and values - in `matchLabels` support the wildcard characters `*` (matches zero or many characters) - and `?` (matches one character).Wildcards allows writing label selectors like - ["storage.k8s.io/*": "*"]. Note that using ["*" : "*"] matches any key and value but - does not match an empty label set. - properties: - matchExpressions: - description: matchExpressions is a list of label - selector requirements. The requirements are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key that the - selector applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - namespaces: - description: |- - Namespaces is a list of namespaces names. Each name supports wildcard characters - "*" (matches zero or many characters) and "?" (at least one character). - items: - type: string - type: array - operations: - description: Operations can contain values ["CREATE, - "UPDATE", "CONNECT", "DELETE"], which are used to - match a specific action. - items: - description: AdmissionOperation can have one of the - values CREATE, UPDATE, CONNECT, DELETE, which are - used to match a specific action. - enum: - - CREATE - - CONNECT - - UPDATE - - DELETE - type: string - type: array - selector: - description: |- - Selector is a label selector. Label keys and values in `matchLabels` support the wildcard - characters `*` (matches zero or many characters) and `?` (matches one character). - Wildcards allows writing label selectors like ["storage.k8s.io/*": "*"]. Note that - using ["*" : "*"] matches any key and value but does not match an empty label set. - properties: - matchExpressions: - description: matchExpressions is a list of label - selector requirements. The requirements are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key that the - selector applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - type: object - roles: - description: Roles is the list of namespaced role names - for the user. - items: - type: string - type: array - subjects: - description: Subjects is the list of subject names like - users, user groups, and service accounts. - items: - description: |- - Subject contains a reference to the object or user identities a role binding applies to. This can either hold a direct API object reference, - or a value for non-objects such as user and group names. - properties: - apiGroup: - description: |- - APIGroup holds the API group of the referenced subject. - Defaults to "" for ServiceAccount subjects. - Defaults to "rbac.authorization.k8s.io" for User and Group subjects. - type: string - kind: - description: |- - Kind of object being referenced. Values defined by this API group are "User", "Group", and "ServiceAccount". - If the Authorizer does not recognized the kind value, the Authorizer should report an error. - type: string - name: - description: Name of the object being referenced. - type: string - namespace: - description: |- - Namespace of the referenced object. If the object kind is non-namespace, such as "User" or "Group", and this value is not empty - the Authorizer should report an error. - type: string - required: - - kind - - name - type: object - x-kubernetes-map-type: atomic - type: array - type: object - type: array - any: - description: Any allows specifying resources which will be ORed - items: - description: ResourceFilter allow users to "AND" or "OR" between - resources - properties: - clusterRoles: - description: ClusterRoles is the list of cluster-wide role - names for the user. - items: - type: string - type: array - resources: - description: ResourceDescription contains information about - the resource being created or modified. - not: - required: - - name - - names - properties: - annotations: - additionalProperties: - type: string - description: |- - Annotations is a map of annotations (key-value pairs of type string). Annotation keys - and values support the wildcard characters "*" (matches zero or many characters) and - "?" (matches at least one character). - type: object - kinds: - description: Kinds is a list of resource kinds. - items: - type: string - type: array - name: - description: |- - Name is the name of the resource. The name supports wildcard characters - "*" (matches zero or many characters) and "?" (at least one character). - NOTE: "Name" is being deprecated in favor of "Names". - type: string - names: - description: |- - Names are the names of the resources. Each name supports wildcard characters - "*" (matches zero or many characters) and "?" (at least one character). - items: - type: string - type: array - namespaceSelector: - description: |- - NamespaceSelector is a label selector for the resource namespace. Label keys and values - in `matchLabels` support the wildcard characters `*` (matches zero or many characters) - and `?` (matches one character).Wildcards allows writing label selectors like - ["storage.k8s.io/*": "*"]. Note that using ["*" : "*"] matches any key and value but - does not match an empty label set. - properties: - matchExpressions: - description: matchExpressions is a list of label - selector requirements. The requirements are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key that the - selector applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - namespaces: - description: |- - Namespaces is a list of namespaces names. Each name supports wildcard characters - "*" (matches zero or many characters) and "?" (at least one character). - items: - type: string - type: array - operations: - description: Operations can contain values ["CREATE, - "UPDATE", "CONNECT", "DELETE"], which are used to - match a specific action. - items: - description: AdmissionOperation can have one of the - values CREATE, UPDATE, CONNECT, DELETE, which are - used to match a specific action. - enum: - - CREATE - - CONNECT - - UPDATE - - DELETE - type: string - type: array - selector: - description: |- - Selector is a label selector. Label keys and values in `matchLabels` support the wildcard - characters `*` (matches zero or many characters) and `?` (matches one character). - Wildcards allows writing label selectors like ["storage.k8s.io/*": "*"]. Note that - using ["*" : "*"] matches any key and value but does not match an empty label set. - properties: - matchExpressions: - description: matchExpressions is a list of label - selector requirements. The requirements are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key that the - selector applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - type: object - roles: - description: Roles is the list of namespaced role names - for the user. - items: - type: string - type: array - subjects: - description: Subjects is the list of subject names like - users, user groups, and service accounts. - items: - description: |- - Subject contains a reference to the object or user identities a role binding applies to. This can either hold a direct API object reference, - or a value for non-objects such as user and group names. - properties: - apiGroup: - description: |- - APIGroup holds the API group of the referenced subject. - Defaults to "" for ServiceAccount subjects. - Defaults to "rbac.authorization.k8s.io" for User and Group subjects. - type: string - kind: - description: |- - Kind of object being referenced. Values defined by this API group are "User", "Group", and "ServiceAccount". - If the Authorizer does not recognized the kind value, the Authorizer should report an error. - type: string - name: - description: Name of the object being referenced. - type: string - namespace: - description: |- - Namespace of the referenced object. If the object kind is non-namespace, such as "User" or "Group", and this value is not empty - the Authorizer should report an error. - type: string - required: - - kind - - name - type: object - x-kubernetes-map-type: atomic - type: array - type: object - type: array - type: object - podSecurity: - description: |- - PodSecurity specifies the Pod Security Standard controls to be excluded. - Applicable only to policies that have validate.podSecurity subrule. - items: - description: PodSecurityStandard specifies the Pod Security Standard - controls to be excluded. - properties: - controlName: - description: |- - ControlName specifies the name of the Pod Security Standard control. - See: https://kubernetes.io/docs/concepts/security/pod-security-standards/ - enum: - - HostProcess - - Host Namespaces - - Privileged Containers - - Capabilities - - HostPath Volumes - - Host Ports - - AppArmor - - SELinux - - /proc Mount Type - - Seccomp - - Sysctls - - Volume Types - - Privilege Escalation - - Running as Non-root - - Running as Non-root user - type: string - images: - description: |- - Images selects matching containers and applies the container level PSS. - Each image is the image name consisting of the registry address, repository, image, and tag. - Empty list matches no containers, PSS checks are applied at the pod level only. - Wildcards ('*' and '?') are allowed. See: https://kubernetes.io/docs/concepts/containers/images. - items: - type: string - type: array - restrictedField: - description: |- - RestrictedField selects the field for the given Pod Security Standard control. - When not set, all restricted fields for the control are selected. - type: string - values: - description: Values defines the allowed values that can be excluded. - items: - type: string - type: array - required: - - controlName - type: object - type: array - required: - - exceptions - - match - type: object - required: - - spec - type: object - served: true - storage: true - - deprecated: true - name: v2beta1 - schema: - openAPIV3Schema: - description: PolicyException declares resources to be excluded from specified - policies. - properties: - apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - type: string - kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - metadata: - type: object - spec: - description: Spec declares policy exception behaviors. - properties: - background: - description: |- - Background controls if exceptions are applied to existing policies during a background scan. - Optional. Default value is "true". The value must be set to "false" if the policy rule - uses variables that are only available in the admission review request (e.g. user name). - type: boolean - conditions: - description: |- - Conditions are used to determine if a resource applies to the exception by evaluating a - set of conditions. The declaration can contain nested `any` or `all` statements. - properties: - all: - description: |- - AllConditions enable variable-based conditional rule execution. This is useful for - finer control of when an rule is applied. A condition can reference object data - using JMESPath notation. - Here, all of the conditions need to pass. - items: - properties: - key: - description: Key is the context entry (using JMESPath) for - conditional rule evaluation. - x-kubernetes-preserve-unknown-fields: true - message: - description: Message is an optional display message - type: string - operator: - description: |- - Operator is the conditional operation to perform. Valid operators are: - Equals, NotEquals, In, AnyIn, AllIn, NotIn, AnyNotIn, AllNotIn, GreaterThanOrEquals, - GreaterThan, LessThanOrEquals, LessThan, DurationGreaterThanOrEquals, DurationGreaterThan, - DurationLessThanOrEquals, DurationLessThan - enum: - - Equals - - NotEquals - - AnyIn - - AllIn - - AnyNotIn - - AllNotIn - - GreaterThanOrEquals - - GreaterThan - - LessThanOrEquals - - LessThan - - DurationGreaterThanOrEquals - - DurationGreaterThan - - DurationLessThanOrEquals - - DurationLessThan - type: string - value: - description: |- - Value is the conditional value, or set of values. The values can be fixed set - or can be variables declared using JMESPath. - x-kubernetes-preserve-unknown-fields: true - type: object - type: array - any: - description: |- - AnyConditions enable variable-based conditional rule execution. This is useful for - finer control of when an rule is applied. A condition can reference object data - using JMESPath notation. - Here, at least one of the conditions need to pass. - items: - properties: - key: - description: Key is the context entry (using JMESPath) for - conditional rule evaluation. - x-kubernetes-preserve-unknown-fields: true - message: - description: Message is an optional display message - type: string - operator: - description: |- - Operator is the conditional operation to perform. Valid operators are: - Equals, NotEquals, In, AnyIn, AllIn, NotIn, AnyNotIn, AllNotIn, GreaterThanOrEquals, - GreaterThan, LessThanOrEquals, LessThan, DurationGreaterThanOrEquals, DurationGreaterThan, - DurationLessThanOrEquals, DurationLessThan - enum: - - Equals - - NotEquals - - AnyIn - - AllIn - - AnyNotIn - - AllNotIn - - GreaterThanOrEquals - - GreaterThan - - LessThanOrEquals - - LessThan - - DurationGreaterThanOrEquals - - DurationGreaterThan - - DurationLessThanOrEquals - - DurationLessThan - type: string - value: - description: |- - Value is the conditional value, or set of values. The values can be fixed set - or can be variables declared using JMESPath. - x-kubernetes-preserve-unknown-fields: true - type: object - type: array - type: object - exceptions: - description: Exceptions is a list policy/rules to be excluded - items: - description: Exception stores infos about a policy and rules - properties: - policyName: - description: |- - PolicyName identifies the policy to which the exception is applied. - The policy name uses the format / unless it - references a ClusterPolicy. - type: string - ruleNames: - description: RuleNames identifies the rules to which the exception - is applied. - items: - type: string - type: array - required: - - policyName - - ruleNames - type: object - type: array - match: - description: Match defines match clause used to check if a resource - applies to the exception - not: - required: - - any - - all - properties: - all: - description: All allows specifying resources which will be ANDed - items: - description: ResourceFilter allow users to "AND" or "OR" between - resources - properties: - clusterRoles: - description: ClusterRoles is the list of cluster-wide role - names for the user. - items: - type: string - type: array - resources: - description: ResourceDescription contains information about - the resource being created or modified. - not: - required: - - name - - names - properties: - annotations: - additionalProperties: - type: string - description: |- - Annotations is a map of annotations (key-value pairs of type string). Annotation keys - and values support the wildcard characters "*" (matches zero or many characters) and - "?" (matches at least one character). - type: object - kinds: - description: Kinds is a list of resource kinds. - items: - type: string - type: array - name: - description: |- - Name is the name of the resource. The name supports wildcard characters - "*" (matches zero or many characters) and "?" (at least one character). - NOTE: "Name" is being deprecated in favor of "Names". - type: string - names: - description: |- - Names are the names of the resources. Each name supports wildcard characters - "*" (matches zero or many characters) and "?" (at least one character). - items: - type: string - type: array - namespaceSelector: - description: |- - NamespaceSelector is a label selector for the resource namespace. Label keys and values - in `matchLabels` support the wildcard characters `*` (matches zero or many characters) - and `?` (matches one character).Wildcards allows writing label selectors like - ["storage.k8s.io/*": "*"]. Note that using ["*" : "*"] matches any key and value but - does not match an empty label set. - properties: - matchExpressions: - description: matchExpressions is a list of label - selector requirements. The requirements are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key that the - selector applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - namespaces: - description: |- - Namespaces is a list of namespaces names. Each name supports wildcard characters - "*" (matches zero or many characters) and "?" (at least one character). - items: - type: string - type: array - operations: - description: Operations can contain values ["CREATE, - "UPDATE", "CONNECT", "DELETE"], which are used to - match a specific action. - items: - description: AdmissionOperation can have one of the - values CREATE, UPDATE, CONNECT, DELETE, which are - used to match a specific action. - enum: - - CREATE - - CONNECT - - UPDATE - - DELETE - type: string - type: array - selector: - description: |- - Selector is a label selector. Label keys and values in `matchLabels` support the wildcard - characters `*` (matches zero or many characters) and `?` (matches one character). - Wildcards allows writing label selectors like ["storage.k8s.io/*": "*"]. Note that - using ["*" : "*"] matches any key and value but does not match an empty label set. - properties: - matchExpressions: - description: matchExpressions is a list of label - selector requirements. The requirements are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key that the - selector applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - type: object - roles: - description: Roles is the list of namespaced role names - for the user. - items: - type: string - type: array - subjects: - description: Subjects is the list of subject names like - users, user groups, and service accounts. - items: - description: |- - Subject contains a reference to the object or user identities a role binding applies to. This can either hold a direct API object reference, - or a value for non-objects such as user and group names. - properties: - apiGroup: - description: |- - APIGroup holds the API group of the referenced subject. - Defaults to "" for ServiceAccount subjects. - Defaults to "rbac.authorization.k8s.io" for User and Group subjects. - type: string - kind: - description: |- - Kind of object being referenced. Values defined by this API group are "User", "Group", and "ServiceAccount". - If the Authorizer does not recognized the kind value, the Authorizer should report an error. - type: string - name: - description: Name of the object being referenced. - type: string - namespace: - description: |- - Namespace of the referenced object. If the object kind is non-namespace, such as "User" or "Group", and this value is not empty - the Authorizer should report an error. - type: string - required: - - kind - - name - type: object - x-kubernetes-map-type: atomic - type: array - type: object - type: array - any: - description: Any allows specifying resources which will be ORed - items: - description: ResourceFilter allow users to "AND" or "OR" between - resources - properties: - clusterRoles: - description: ClusterRoles is the list of cluster-wide role - names for the user. - items: - type: string - type: array - resources: - description: ResourceDescription contains information about - the resource being created or modified. - not: - required: - - name - - names - properties: - annotations: - additionalProperties: - type: string - description: |- - Annotations is a map of annotations (key-value pairs of type string). Annotation keys - and values support the wildcard characters "*" (matches zero or many characters) and - "?" (matches at least one character). - type: object - kinds: - description: Kinds is a list of resource kinds. - items: - type: string - type: array - name: - description: |- - Name is the name of the resource. The name supports wildcard characters - "*" (matches zero or many characters) and "?" (at least one character). - NOTE: "Name" is being deprecated in favor of "Names". - type: string - names: - description: |- - Names are the names of the resources. Each name supports wildcard characters - "*" (matches zero or many characters) and "?" (at least one character). - items: - type: string - type: array - namespaceSelector: - description: |- - NamespaceSelector is a label selector for the resource namespace. Label keys and values - in `matchLabels` support the wildcard characters `*` (matches zero or many characters) - and `?` (matches one character).Wildcards allows writing label selectors like - ["storage.k8s.io/*": "*"]. Note that using ["*" : "*"] matches any key and value but - does not match an empty label set. - properties: - matchExpressions: - description: matchExpressions is a list of label - selector requirements. The requirements are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key that the - selector applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - namespaces: - description: |- - Namespaces is a list of namespaces names. Each name supports wildcard characters - "*" (matches zero or many characters) and "?" (at least one character). - items: - type: string - type: array - operations: - description: Operations can contain values ["CREATE, - "UPDATE", "CONNECT", "DELETE"], which are used to - match a specific action. - items: - description: AdmissionOperation can have one of the - values CREATE, UPDATE, CONNECT, DELETE, which are - used to match a specific action. - enum: - - CREATE - - CONNECT - - UPDATE - - DELETE - type: string - type: array - selector: - description: |- - Selector is a label selector. Label keys and values in `matchLabels` support the wildcard - characters `*` (matches zero or many characters) and `?` (matches one character). - Wildcards allows writing label selectors like ["storage.k8s.io/*": "*"]. Note that - using ["*" : "*"] matches any key and value but does not match an empty label set. - properties: - matchExpressions: - description: matchExpressions is a list of label - selector requirements. The requirements are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key that the - selector applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - type: object - roles: - description: Roles is the list of namespaced role names - for the user. - items: - type: string - type: array - subjects: - description: Subjects is the list of subject names like - users, user groups, and service accounts. - items: - description: |- - Subject contains a reference to the object or user identities a role binding applies to. This can either hold a direct API object reference, - or a value for non-objects such as user and group names. - properties: - apiGroup: - description: |- - APIGroup holds the API group of the referenced subject. - Defaults to "" for ServiceAccount subjects. - Defaults to "rbac.authorization.k8s.io" for User and Group subjects. - type: string - kind: - description: |- - Kind of object being referenced. Values defined by this API group are "User", "Group", and "ServiceAccount". - If the Authorizer does not recognized the kind value, the Authorizer should report an error. - type: string - name: - description: Name of the object being referenced. - type: string - namespace: - description: |- - Namespace of the referenced object. If the object kind is non-namespace, such as "User" or "Group", and this value is not empty - the Authorizer should report an error. - type: string - required: - - kind - - name - type: object - x-kubernetes-map-type: atomic - type: array - type: object - type: array - type: object - podSecurity: - description: |- - PodSecurity specifies the Pod Security Standard controls to be excluded. - Applicable only to policies that have validate.podSecurity subrule. - items: - description: PodSecurityStandard specifies the Pod Security Standard - controls to be excluded. - properties: - controlName: - description: |- - ControlName specifies the name of the Pod Security Standard control. - See: https://kubernetes.io/docs/concepts/security/pod-security-standards/ - enum: - - HostProcess - - Host Namespaces - - Privileged Containers - - Capabilities - - HostPath Volumes - - Host Ports - - AppArmor - - SELinux - - /proc Mount Type - - Seccomp - - Sysctls - - Volume Types - - Privilege Escalation - - Running as Non-root - - Running as Non-root user - type: string - images: - description: |- - Images selects matching containers and applies the container level PSS. - Each image is the image name consisting of the registry address, repository, image, and tag. - Empty list matches no containers, PSS checks are applied at the pod level only. - Wildcards ('*' and '?') are allowed. See: https://kubernetes.io/docs/concepts/containers/images. - items: - type: string - type: array - restrictedField: - description: |- - RestrictedField selects the field for the given Pod Security Standard control. - When not set, all restricted fields for the control are selected. - type: string - values: - description: Values defines the allowed values that can be excluded. - items: - type: string - type: array - required: - - controlName - type: object - type: array - required: - - exceptions - - match - type: object - required: - - spec - type: object - served: true - storage: false ---- -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - labels: - app.kubernetes.io/component: crds - app.kubernetes.io/instance: kyverno - app.kubernetes.io/managed-by: Helm - app.kubernetes.io/part-of: kyverno-crds - app.kubernetes.io/version: 3.5.1 - helm.sh/chart: crds-3.5.1 - annotations: - controller-gen.kubebuilder.io/version: v0.17.3 - name: updaterequests.kyverno.io -spec: - group: kyverno.io - names: - categories: - - kyverno - kind: UpdateRequest - listKind: UpdateRequestList - plural: updaterequests - shortNames: - - ur - singular: updaterequest - scope: Namespaced - versions: - - additionalPrinterColumns: - - jsonPath: .spec.policy - name: Policy - type: string - - jsonPath: .spec.rule - name: Rule - type: string - - jsonPath: .spec.requestType - name: RuleType - type: string - - jsonPath: .spec.resource.kind - name: ResourceKind - type: string - - jsonPath: .spec.resource.name - name: ResourceName - type: string - - jsonPath: .spec.resource.namespace - name: ResourceNamespace - type: string - - jsonPath: .status.state - name: status - type: string - - jsonPath: .metadata.creationTimestamp - name: Age - type: date - deprecated: true - name: v1beta1 - schema: - openAPIV3Schema: - description: UpdateRequest is a request to process mutate and generate rules - in background. - properties: - apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - type: string - kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - metadata: - type: object - spec: - description: ResourceSpec is the information to identify the trigger resource. - properties: - context: - description: Context ... - properties: - admissionRequestInfo: - description: AdmissionRequestInfoObject stores the admission request - and operation details - properties: - admissionRequest: - description: AdmissionRequest describes the admission.Attributes - for the admission request. - properties: - dryRun: - description: |- - DryRun indicates that modifications will definitely not be persisted for this request. - Defaults to false. - type: boolean - kind: - description: Kind is the fully-qualified type of object - being submitted (for example, v1.Pod or autoscaling.v1.Scale) - properties: - group: - type: string - kind: - type: string - version: - type: string - required: - - group - - kind - - version - type: object - name: - description: |- - Name is the name of the object as presented in the request. On a CREATE operation, the client may omit name and - rely on the server to generate the name. If that is the case, this field will contain an empty string. - type: string - namespace: - description: Namespace is the namespace associated with - the request (if any). - type: string - object: - description: Object is the object from the incoming request. - type: object - x-kubernetes-preserve-unknown-fields: true - oldObject: - description: OldObject is the existing object. Only populated - for DELETE and UPDATE requests. - type: object - x-kubernetes-preserve-unknown-fields: true - operation: - description: |- - Operation is the operation being performed. This may be different than the operation - requested. e.g. a patch can result in either a CREATE or UPDATE Operation. - type: string - options: - description: |- - Options is the operation option structure of the operation being performed. - e.g. `meta.k8s.io/v1.DeleteOptions` or `meta.k8s.io/v1.CreateOptions`. This may be - different than the options the caller provided. e.g. for a patch request the performed - Operation might be a CREATE, in which case the Options will a - `meta.k8s.io/v1.CreateOptions` even though the caller provided `meta.k8s.io/v1.PatchOptions`. - type: object - x-kubernetes-preserve-unknown-fields: true - requestKind: - description: |- - RequestKind is the fully-qualified type of the original API request (for example, v1.Pod or autoscaling.v1.Scale). - If this is specified and differs from the value in "kind", an equivalent match and conversion was performed. - - For example, if deployments can be modified via apps/v1 and apps/v1beta1, and a webhook registered a rule of - `apiGroups:["apps"], apiVersions:["v1"], resources: ["deployments"]` and `matchPolicy: Equivalent`, - an API request to apps/v1beta1 deployments would be converted and sent to the webhook - with `kind: {group:"apps", version:"v1", kind:"Deployment"}` (matching the rule the webhook registered for), - and `requestKind: {group:"apps", version:"v1beta1", kind:"Deployment"}` (indicating the kind of the original API request). - - See documentation for the "matchPolicy" field in the webhook configuration type for more details. - properties: - group: - type: string - kind: - type: string - version: - type: string - required: - - group - - kind - - version - type: object - requestResource: - description: |- - RequestResource is the fully-qualified resource of the original API request (for example, v1.pods). - If this is specified and differs from the value in "resource", an equivalent match and conversion was performed. - - For example, if deployments can be modified via apps/v1 and apps/v1beta1, and a webhook registered a rule of - `apiGroups:["apps"], apiVersions:["v1"], resources: ["deployments"]` and `matchPolicy: Equivalent`, - an API request to apps/v1beta1 deployments would be converted and sent to the webhook - with `resource: {group:"apps", version:"v1", resource:"deployments"}` (matching the resource the webhook registered for), - and `requestResource: {group:"apps", version:"v1beta1", resource:"deployments"}` (indicating the resource of the original API request). - - See documentation for the "matchPolicy" field in the webhook configuration type. - properties: - group: - type: string - resource: - type: string - version: - type: string - required: - - group - - resource - - version - type: object - requestSubResource: - description: |- - RequestSubResource is the name of the subresource of the original API request, if any (for example, "status" or "scale") - If this is specified and differs from the value in "subResource", an equivalent match and conversion was performed. - See documentation for the "matchPolicy" field in the webhook configuration type. - type: string - resource: - description: Resource is the fully-qualified resource - being requested (for example, v1.pods) - properties: - group: - type: string - resource: - type: string - version: - type: string - required: - - group - - resource - - version - type: object - subResource: - description: SubResource is the subresource being requested, - if any (for example, "status" or "scale") - type: string - uid: - description: |- - UID is an identifier for the individual request/response. It allows us to distinguish instances of requests which are - otherwise identical (parallel requests, requests when earlier requests did not modify etc) - The UID is meant to track the round trip (request/response) between the KAS and the WebHook, not the user request. - It is suitable for correlating log entries between the webhook and apiserver, for either auditing or debugging. - type: string - userInfo: - description: UserInfo is information about the requesting - user - properties: - extra: - additionalProperties: - description: ExtraValue masks the value so protobuf - can generate - items: - type: string - type: array - description: Any additional information provided by - the authenticator. - type: object - groups: - description: The names of groups this user is a part - of. - items: - type: string - type: array - x-kubernetes-list-type: atomic - uid: - description: |- - A unique value that identifies this user across time. If this user is - deleted and another user by the same name is added, they will have - different UIDs. - type: string - username: - description: The name that uniquely identifies this - user among all active users. - type: string - type: object - required: - - kind - - operation - - resource - - uid - - userInfo - type: object - operation: - description: Operation is the type of resource operation being - checked for admission control - type: string - type: object - userInfo: - description: RequestInfo contains permission info carried in an - admission request. - properties: - clusterRoles: - description: ClusterRoles is a list of possible clusterRoles - send the request. - items: - type: string - nullable: true - type: array - roles: - description: Roles is a list of possible role send the request. - items: - type: string - nullable: true - type: array - userInfo: - description: UserInfo is the userInfo carried in the admission - request. - properties: - extra: - additionalProperties: - description: ExtraValue masks the value so protobuf - can generate - items: - type: string - type: array - description: Any additional information provided by the - authenticator. - type: object - groups: - description: The names of groups this user is a part of. - items: - type: string - type: array - x-kubernetes-list-type: atomic - uid: - description: |- - A unique value that identifies this user across time. If this user is - deleted and another user by the same name is added, they will have - different UIDs. - type: string - username: - description: The name that uniquely identifies this user - among all active users. - type: string - type: object - type: object - type: object - deleteDownstream: - description: DeleteDownstream represents whether the downstream needs - to be deleted. - type: boolean - policy: - description: Specifies the name of the policy. - type: string - requestType: - description: Type represents request type for background processing - enum: - - mutate - - generate - type: string - resource: - description: ResourceSpec is the information to identify the trigger - resource. - properties: - apiVersion: - description: APIVersion specifies resource apiVersion. - type: string - kind: - description: Kind specifies resource kind. - type: string - name: - description: Name specifies the resource name. - type: string - namespace: - description: Namespace specifies resource namespace. - type: string - uid: - description: UID specifies the resource uid. - type: string - type: object - rule: - description: Rule is the associate rule name of the current UR. - type: string - synchronize: - description: |- - Synchronize represents the sync behavior of the corresponding rule - Optional. Defaults to "false" if not specified. - type: boolean - required: - - context - - deleteDownstream - - policy - - resource - - rule - type: object - status: - description: Status contains statistics related to update request. - properties: - generatedResources: - description: |- - This will track the resources that are updated by the generate Policy. - Will be used during clean up resources. - items: - properties: - apiVersion: - description: APIVersion specifies resource apiVersion. - type: string - kind: - description: Kind specifies resource kind. - type: string - name: - description: Name specifies the resource name. - type: string - namespace: - description: Namespace specifies resource namespace. - type: string - uid: - description: UID specifies the resource uid. - type: string - type: object - type: array - handler: - description: Deprecated - type: string - message: - description: Specifies request status message. - type: string - retryCount: - type: integer - state: - description: State represents state of the update request. - type: string - required: - - state - type: object - type: object - served: true - storage: false - subresources: - status: {} - - additionalPrinterColumns: - - jsonPath: .spec.policy - name: Policy - type: string - - jsonPath: .spec.requestType - name: RuleType - type: string - - jsonPath: .spec.resource.kind - name: ResourceKind - type: string - - jsonPath: .spec.resource.name - name: ResourceName - type: string - - jsonPath: .spec.resource.namespace - name: ResourceNamespace - type: string - - jsonPath: .status.state - name: status - type: string - - jsonPath: .metadata.creationTimestamp - name: Age - type: date - name: v2 - schema: - openAPIV3Schema: - description: UpdateRequest is a request to process mutate and generate rules - in background. - properties: - apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - type: string - kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - metadata: - type: object - spec: - description: ResourceSpec is the information to identify the trigger resource. - properties: - context: - description: |- - Context represents admission request context. - It is used upon admission review only and is shared across rules within the same UR. - properties: - admissionRequestInfo: - description: AdmissionRequestInfoObject stores the admission request - and operation details - properties: - admissionRequest: - description: AdmissionRequest describes the admission.Attributes - for the admission request. - properties: - dryRun: - description: |- - DryRun indicates that modifications will definitely not be persisted for this request. - Defaults to false. - type: boolean - kind: - description: Kind is the fully-qualified type of object - being submitted (for example, v1.Pod or autoscaling.v1.Scale) - properties: - group: - type: string - kind: - type: string - version: - type: string - required: - - group - - kind - - version - type: object - name: - description: |- - Name is the name of the object as presented in the request. On a CREATE operation, the client may omit name and - rely on the server to generate the name. If that is the case, this field will contain an empty string. - type: string - namespace: - description: Namespace is the namespace associated with - the request (if any). - type: string - object: - description: Object is the object from the incoming request. - type: object - x-kubernetes-preserve-unknown-fields: true - oldObject: - description: OldObject is the existing object. Only populated - for DELETE and UPDATE requests. - type: object - x-kubernetes-preserve-unknown-fields: true - operation: - description: |- - Operation is the operation being performed. This may be different than the operation - requested. e.g. a patch can result in either a CREATE or UPDATE Operation. - type: string - options: - description: |- - Options is the operation option structure of the operation being performed. - e.g. `meta.k8s.io/v1.DeleteOptions` or `meta.k8s.io/v1.CreateOptions`. This may be - different than the options the caller provided. e.g. for a patch request the performed - Operation might be a CREATE, in which case the Options will a - `meta.k8s.io/v1.CreateOptions` even though the caller provided `meta.k8s.io/v1.PatchOptions`. - type: object - x-kubernetes-preserve-unknown-fields: true - requestKind: - description: |- - RequestKind is the fully-qualified type of the original API request (for example, v1.Pod or autoscaling.v1.Scale). - If this is specified and differs from the value in "kind", an equivalent match and conversion was performed. - - For example, if deployments can be modified via apps/v1 and apps/v1beta1, and a webhook registered a rule of - `apiGroups:["apps"], apiVersions:["v1"], resources: ["deployments"]` and `matchPolicy: Equivalent`, - an API request to apps/v1beta1 deployments would be converted and sent to the webhook - with `kind: {group:"apps", version:"v1", kind:"Deployment"}` (matching the rule the webhook registered for), - and `requestKind: {group:"apps", version:"v1beta1", kind:"Deployment"}` (indicating the kind of the original API request). - - See documentation for the "matchPolicy" field in the webhook configuration type for more details. - properties: - group: - type: string - kind: - type: string - version: - type: string - required: - - group - - kind - - version - type: object - requestResource: - description: |- - RequestResource is the fully-qualified resource of the original API request (for example, v1.pods). - If this is specified and differs from the value in "resource", an equivalent match and conversion was performed. - - For example, if deployments can be modified via apps/v1 and apps/v1beta1, and a webhook registered a rule of - `apiGroups:["apps"], apiVersions:["v1"], resources: ["deployments"]` and `matchPolicy: Equivalent`, - an API request to apps/v1beta1 deployments would be converted and sent to the webhook - with `resource: {group:"apps", version:"v1", resource:"deployments"}` (matching the resource the webhook registered for), - and `requestResource: {group:"apps", version:"v1beta1", resource:"deployments"}` (indicating the resource of the original API request). - - See documentation for the "matchPolicy" field in the webhook configuration type. - properties: - group: - type: string - resource: - type: string - version: - type: string - required: - - group - - resource - - version - type: object - requestSubResource: - description: |- - RequestSubResource is the name of the subresource of the original API request, if any (for example, "status" or "scale") - If this is specified and differs from the value in "subResource", an equivalent match and conversion was performed. - See documentation for the "matchPolicy" field in the webhook configuration type. - type: string - resource: - description: Resource is the fully-qualified resource - being requested (for example, v1.pods) - properties: - group: - type: string - resource: - type: string - version: - type: string - required: - - group - - resource - - version - type: object - subResource: - description: SubResource is the subresource being requested, - if any (for example, "status" or "scale") - type: string - uid: - description: |- - UID is an identifier for the individual request/response. It allows us to distinguish instances of requests which are - otherwise identical (parallel requests, requests when earlier requests did not modify etc) - The UID is meant to track the round trip (request/response) between the KAS and the WebHook, not the user request. - It is suitable for correlating log entries between the webhook and apiserver, for either auditing or debugging. - type: string - userInfo: - description: UserInfo is information about the requesting - user - properties: - extra: - additionalProperties: - description: ExtraValue masks the value so protobuf - can generate - items: - type: string - type: array - description: Any additional information provided by - the authenticator. - type: object - groups: - description: The names of groups this user is a part - of. - items: - type: string - type: array - x-kubernetes-list-type: atomic - uid: - description: |- - A unique value that identifies this user across time. If this user is - deleted and another user by the same name is added, they will have - different UIDs. - type: string - username: - description: The name that uniquely identifies this - user among all active users. - type: string - type: object - required: - - kind - - operation - - resource - - uid - - userInfo - type: object - operation: - description: Operation is the type of resource operation being - checked for admission control - type: string - type: object - userInfo: - description: RequestInfo contains permission info carried in an - admission request. - properties: - clusterRoles: - description: ClusterRoles is a list of possible clusterRoles - send the request. - items: - type: string - nullable: true - type: array - roles: - description: Roles is a list of possible role send the request. - items: - type: string - nullable: true - type: array - synchronize: - description: |- - DryRun indicates that modifications will definitely not be persisted for this request. - Defaults to false. - type: boolean - userInfo: - description: UserInfo is the userInfo carried in the admission - request. - properties: - extra: - additionalProperties: - description: ExtraValue masks the value so protobuf - can generate - items: - type: string - type: array - description: Any additional information provided by the - authenticator. - type: object - groups: - description: The names of groups this user is a part of. - items: - type: string - type: array - x-kubernetes-list-type: atomic - uid: - description: |- - A unique value that identifies this user across time. If this user is - deleted and another user by the same name is added, they will have - different UIDs. - type: string - username: - description: The name that uniquely identifies this user - among all active users. - type: string - type: object - type: object - type: object - deleteDownstream: - description: |- - DeleteDownstream represents whether the downstream needs to be deleted. - Deprecated - type: boolean - policy: - description: Specifies the name of the policy. - type: string - requestType: - description: Type represents request type for background processing - enum: - - mutate - - generate - - cel-generate - - cel-mutate - type: string - resource: - description: ResourceSpec is the information to identify the trigger - resource. - properties: - apiVersion: - description: APIVersion specifies resource apiVersion. - type: string - kind: - description: Kind specifies resource kind. - type: string - name: - description: Name specifies the resource name. - type: string - namespace: - description: Namespace specifies resource namespace. - type: string - uid: - description: UID specifies the resource uid. - type: string - type: object - rule: - description: Rule is the associate rule name of the current UR. - type: string - ruleContext: - description: |- - RuleContext is the associate context to apply rules. - optional - items: - properties: - cacheRestore: - description: CacheRestore indicates whether the cache should - be restored. - type: boolean - deleteDownstream: - description: DeleteDownstream represents whether the downstream - needs to be deleted. - type: boolean - rule: - description: Rule is the associate rule name of the current - UR. - type: string - synchronize: - description: |- - Synchronize represents the sync behavior of the corresponding rule - Optional. Defaults to "false" if not specified. - type: boolean - trigger: - description: ResourceSpec is the information to identify the - trigger resource. - properties: - apiVersion: - description: APIVersion specifies resource apiVersion. - type: string - kind: - description: Kind specifies resource kind. - type: string - name: - description: Name specifies the resource name. - type: string - namespace: - description: Namespace specifies resource namespace. - type: string - uid: - description: UID specifies the resource uid. - type: string - type: object - required: - - deleteDownstream - - rule - - trigger - type: object - type: array - synchronize: - description: |- - Synchronize represents the sync behavior of the corresponding rule - Optional. Defaults to "false" if not specified. - Deprecated, will be removed in 1.14. - type: boolean - required: - - context - - deleteDownstream - - policy - - resource - - rule - type: object - status: - description: Status contains statistics related to update request. - properties: - generatedResources: - description: |- - This will track the resources that are updated by the generate Policy. - Will be used during clean up resources. - items: - properties: - apiVersion: - description: APIVersion specifies resource apiVersion. - type: string - kind: - description: Kind specifies resource kind. - type: string - name: - description: Name specifies the resource name. - type: string - namespace: - description: Namespace specifies resource namespace. - type: string - uid: - description: UID specifies the resource uid. - type: string - type: object - type: array - message: - description: Specifies request status message. - type: string - retryCount: - type: integer - state: - description: State represents state of the update request. - type: string - required: - - state - type: object - type: object - served: true - storage: true - subresources: - status: {} ---- -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - labels: - app.kubernetes.io/component: crds - app.kubernetes.io/instance: kyverno - app.kubernetes.io/managed-by: Helm - app.kubernetes.io/part-of: kyverno-crds - app.kubernetes.io/version: 3.5.1 - helm.sh/chart: crds-3.5.1 - annotations: - controller-gen.kubebuilder.io/version: v0.17.3 - name: deletingpolicies.policies.kyverno.io -spec: - group: policies.kyverno.io - names: - categories: - - kyverno - kind: DeletingPolicy - listKind: DeletingPolicyList - plural: deletingpolicies - shortNames: - - dpol - singular: deletingpolicy - scope: Cluster - versions: - - additionalPrinterColumns: - - jsonPath: .metadata.creationTimestamp - name: AGE - type: date - - jsonPath: .status.conditionStatus.ready - name: READY - type: string - name: v1alpha1 - schema: - openAPIV3Schema: - properties: - apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - type: string - kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - metadata: - type: object - spec: - description: DeletingPolicySpec is the specification of the desired behavior - of the DeletingPolicy. - properties: - conditions: - description: |- - Conditions is a list of conditions that must be met for a resource to be deleted. - Conditions filter resources that have already been matched by the match constraints, - namespaceSelector, and objectSelector. An empty list of conditions matches all resources. - There are a maximum of 64 conditions allowed. - - The exact matching logic is (in order): - 1. If ANY condition evaluates to FALSE, the policy is skipped. - 2. If ALL conditions evaluate to TRUE, the policy is executed. - items: - description: MatchCondition represents a condition which must by - fulfilled for a request to be sent to a webhook. - properties: - expression: - description: |- - Expression represents the expression which will be evaluated by CEL. Must evaluate to bool. - CEL expressions have access to the contents of the AdmissionRequest and Authorizer, organized into CEL variables: - - 'object' - The object from the incoming request. The value is null for DELETE requests. - 'oldObject' - The existing object. The value is null for CREATE requests. - 'request' - Attributes of the admission request(/pkg/apis/admission/types.go#AdmissionRequest). - 'authorizer' - A CEL Authorizer. May be used to perform authorization checks for the principal (user or service account) of the request. - See https://pkg.go.dev/k8s.io/apiserver/pkg/cel/library#Authz - 'authorizer.requestResource' - A CEL ResourceCheck constructed from the 'authorizer' and configured with the - request resource. - Documentation on CEL: https://kubernetes.io/docs/reference/using-api/cel/ - - Required. - type: string - name: - description: |- - Name is an identifier for this match condition, used for strategic merging of MatchConditions, - as well as providing an identifier for logging purposes. A good name should be descriptive of - the associated expression. - Name must be a qualified name consisting of alphanumeric characters, '-', '_' or '.', and - must start and end with an alphanumeric character (e.g. 'MyName', or 'my.name', or - '123-abc', regex used for validation is '([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9]') with an - optional DNS subdomain prefix and '/' (e.g. 'example.com/MyName') - - Required. - type: string - required: - - expression - - name - type: object - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map - deletionPropagationPolicy: - description: DeletionPropagationPolicy defines how resources will - be deleted (Foreground, Background, Orphan). - enum: - - Foreground - - Background - - Orphan - type: string - matchConstraints: - description: |- - MatchConstraints specifies what resources this policy is designed to validate. - The AdmissionPolicy cares about a request if it matches _all_ Constraints. - Required. - properties: - excludeResourceRules: - description: |- - ExcludeResourceRules describes what operations on what resources/subresources the ValidatingAdmissionPolicy should not care about. - The exclude rules take precedence over include rules (if a resource matches both, it is excluded) - items: - description: NamedRuleWithOperations is a tuple of Operations - and Resources with ResourceNames. - properties: - apiGroups: - description: |- - APIGroups is the API groups the resources belong to. '*' is all groups. - If '*' is present, the length of the slice must be one. - Required. - items: - type: string - type: array - x-kubernetes-list-type: atomic - apiVersions: - description: |- - APIVersions is the API versions the resources belong to. '*' is all versions. - If '*' is present, the length of the slice must be one. - Required. - items: - type: string - type: array - x-kubernetes-list-type: atomic - operations: - description: |- - Operations is the operations the admission hook cares about - CREATE, UPDATE, DELETE, CONNECT or * - for all of those operations and any future admission operations that are added. - If '*' is present, the length of the slice must be one. - Required. - items: - description: OperationType specifies an operation for - a request. - type: string - type: array - x-kubernetes-list-type: atomic - resourceNames: - description: ResourceNames is an optional white list of - names that the rule applies to. An empty set means that - everything is allowed. - items: - type: string - type: array - x-kubernetes-list-type: atomic - resources: - description: |- - Resources is a list of resources this rule applies to. - - For example: - 'pods' means pods. - 'pods/log' means the log subresource of pods. - '*' means all resources, but not subresources. - 'pods/*' means all subresources of pods. - '*/scale' means all scale subresources. - '*/*' means all resources and their subresources. - - If wildcard is present, the validation rule will ensure resources do not - overlap with each other. - - Depending on the enclosing object, subresources might not be allowed. - Required. - items: - type: string - type: array - x-kubernetes-list-type: atomic - scope: - description: |- - scope specifies the scope of this rule. - Valid values are "Cluster", "Namespaced", and "*" - "Cluster" means that only cluster-scoped resources will match this rule. - Namespace API objects are cluster-scoped. - "Namespaced" means that only namespaced resources will match this rule. - "*" means that there are no scope restrictions. - Subresources match the scope of their parent resource. - Default is "*". - type: string - type: object - x-kubernetes-map-type: atomic - type: array - x-kubernetes-list-type: atomic - matchPolicy: - description: |- - matchPolicy defines how the "MatchResources" list is used to match incoming requests. - Allowed values are "Exact" or "Equivalent". - - - Exact: match a request only if it exactly matches a specified rule. - For example, if deployments can be modified via apps/v1, apps/v1beta1, and extensions/v1beta1, - but "rules" only included `apiGroups:["apps"], apiVersions:["v1"], resources: ["deployments"]`, - a request to apps/v1beta1 or extensions/v1beta1 would not be sent to the ValidatingAdmissionPolicy. - - - Equivalent: match a request if modifies a resource listed in rules, even via another API group or version. - For example, if deployments can be modified via apps/v1, apps/v1beta1, and extensions/v1beta1, - and "rules" only included `apiGroups:["apps"], apiVersions:["v1"], resources: ["deployments"]`, - a request to apps/v1beta1 or extensions/v1beta1 would be converted to apps/v1 and sent to the ValidatingAdmissionPolicy. - - Defaults to "Equivalent" - type: string - namespaceSelector: - description: |- - NamespaceSelector decides whether to run the admission control policy on an object based - on whether the namespace for that object matches the selector. If the - object itself is a namespace, the matching is performed on - object.metadata.labels. If the object is another cluster scoped resource, - it never skips the policy. - - For example, to run the webhook on any objects whose namespace is not - associated with "runlevel" of "0" or "1"; you will set the selector as - follows: - "namespaceSelector": { - "matchExpressions": [ - { - "key": "runlevel", - "operator": "NotIn", - "values": [ - "0", - "1" - ] - } - ] - } - - If instead you want to only run the policy on any objects whose - namespace is associated with the "environment" of "prod" or "staging"; - you will set the selector as follows: - "namespaceSelector": { - "matchExpressions": [ - { - "key": "environment", - "operator": "In", - "values": [ - "prod", - "staging" - ] - } - ] - } - - See - https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/ - for more examples of label selectors. - - Default to the empty LabelSelector, which matches everything. - properties: - matchExpressions: - description: matchExpressions is a list of label selector - requirements. The requirements are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key that the selector - applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - objectSelector: - description: |- - ObjectSelector decides whether to run the validation based on if the - object has matching labels. objectSelector is evaluated against both - the oldObject and newObject that would be sent to the cel validation, and - is considered to match if either object matches the selector. A null - object (oldObject in the case of create, or newObject in the case of - delete) or an object that cannot have labels (like a - DeploymentRollback or a PodProxyOptions object) is not considered to - match. - Use the object selector only if the webhook is opt-in, because end - users may skip the admission webhook by setting the labels. - Default to the empty LabelSelector, which matches everything. - properties: - matchExpressions: - description: matchExpressions is a list of label selector - requirements. The requirements are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key that the selector - applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - resourceRules: - description: |- - ResourceRules describes what operations on what resources/subresources the ValidatingAdmissionPolicy matches. - The policy cares about an operation if it matches _any_ Rule. - items: - description: NamedRuleWithOperations is a tuple of Operations - and Resources with ResourceNames. - properties: - apiGroups: - description: |- - APIGroups is the API groups the resources belong to. '*' is all groups. - If '*' is present, the length of the slice must be one. - Required. - items: - type: string - type: array - x-kubernetes-list-type: atomic - apiVersions: - description: |- - APIVersions is the API versions the resources belong to. '*' is all versions. - If '*' is present, the length of the slice must be one. - Required. - items: - type: string - type: array - x-kubernetes-list-type: atomic - operations: - description: |- - Operations is the operations the admission hook cares about - CREATE, UPDATE, DELETE, CONNECT or * - for all of those operations and any future admission operations that are added. - If '*' is present, the length of the slice must be one. - Required. - items: - description: OperationType specifies an operation for - a request. - type: string - type: array - x-kubernetes-list-type: atomic - resourceNames: - description: ResourceNames is an optional white list of - names that the rule applies to. An empty set means that - everything is allowed. - items: - type: string - type: array - x-kubernetes-list-type: atomic - resources: - description: |- - Resources is a list of resources this rule applies to. - - For example: - 'pods' means pods. - 'pods/log' means the log subresource of pods. - '*' means all resources, but not subresources. - 'pods/*' means all subresources of pods. - '*/scale' means all scale subresources. - '*/*' means all resources and their subresources. - - If wildcard is present, the validation rule will ensure resources do not - overlap with each other. - - Depending on the enclosing object, subresources might not be allowed. - Required. - items: - type: string - type: array - x-kubernetes-list-type: atomic - scope: - description: |- - scope specifies the scope of this rule. - Valid values are "Cluster", "Namespaced", and "*" - "Cluster" means that only cluster-scoped resources will match this rule. - Namespace API objects are cluster-scoped. - "Namespaced" means that only namespaced resources will match this rule. - "*" means that there are no scope restrictions. - Subresources match the scope of their parent resource. - Default is "*". - type: string - type: object - x-kubernetes-map-type: atomic - type: array - x-kubernetes-list-type: atomic - type: object - x-kubernetes-map-type: atomic - schedule: - description: |- - The schedule in Cron format - Required. - type: string - variables: - description: |- - Variables contain definitions of variables that can be used in composition of other expressions. - Each variable is defined as a named CEL expression. - The variables defined here will be available under `variables` in other expressions of the policy - except MatchConditions because MatchConditions are evaluated before the rest of the policy. - - The expression of a variable can refer to other variables defined earlier in the list but not those after. - Thus, Variables must be sorted by the order of first appearance and acyclic. - items: - description: Variable is the definition of a variable that is used - for composition. A variable is defined as a named expression. - properties: - expression: - description: |- - Expression is the expression that will be evaluated as the value of the variable. - The CEL expression has access to the same identifiers as the CEL expressions in Validation. - type: string - name: - description: |- - Name is the name of the variable. The name must be a valid CEL identifier and unique among all variables. - The variable can be accessed in other expressions through `variables` - For example, if name is "foo", the variable will be available as `variables.foo` - type: string - required: - - expression - - name - type: object - x-kubernetes-map-type: atomic - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map - required: - - schedule - type: object - status: - description: Status contains policy runtime data. - properties: - conditionStatus: - description: ConditionStatus is the shared status across all policy - types - properties: - conditions: - items: - description: Condition contains details for one aspect of the - current state of this API Resource. - properties: - lastTransitionTime: - description: |- - lastTransitionTime is the last time the condition transitioned from one status to another. - This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable. - format: date-time - type: string - message: - description: |- - message is a human readable message indicating details about the transition. - This may be an empty string. - maxLength: 32768 - type: string - observedGeneration: - description: |- - observedGeneration represents the .metadata.generation that the condition was set based upon. - For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date - with respect to the current state of the instance. - format: int64 - minimum: 0 - type: integer - reason: - description: |- - reason contains a programmatic identifier indicating the reason for the condition's last transition. - Producers of specific condition types may define expected values and meanings for this field, - and whether the values are considered a guaranteed API. - The value should be a CamelCase string. - This field may not be empty. - maxLength: 1024 - minLength: 1 - pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ - type: string - status: - description: status of the condition, one of True, False, - Unknown. - enum: - - "True" - - "False" - - Unknown - type: string - type: - description: type of condition in CamelCase or in foo.example.com/CamelCase. - maxLength: 316 - pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ - type: string - required: - - lastTransitionTime - - message - - reason - - status - - type - type: object - type: array - message: - description: |- - Message is a human readable message indicating details about the generation of ValidatingAdmissionPolicy/MutatingAdmissionPolicy - It is an empty string when ValidatingAdmissionPolicy/MutatingAdmissionPolicy is successfully generated. - type: string - ready: - description: |- - The ready of a policy is a high-level summary of where the policy is in its lifecycle. - The conditions array, the reason and message fields contain more detail about the policy's status. - type: boolean - type: object - lastExecutionTime: - format: date-time - type: string - type: object - required: - - spec - type: object - served: true - storage: true - subresources: - status: {} ---- -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - labels: - app.kubernetes.io/component: crds - app.kubernetes.io/instance: kyverno - app.kubernetes.io/managed-by: Helm - app.kubernetes.io/part-of: kyverno-crds - app.kubernetes.io/version: 3.5.1 - helm.sh/chart: crds-3.5.1 - annotations: - controller-gen.kubebuilder.io/version: v0.17.3 - name: generatingpolicies.policies.kyverno.io -spec: - group: policies.kyverno.io - names: - categories: - - kyverno - kind: GeneratingPolicy - listKind: GeneratingPolicyList - plural: generatingpolicies - shortNames: - - gpol - singular: generatingpolicy - scope: Cluster - versions: - - additionalPrinterColumns: - - jsonPath: .metadata.creationTimestamp - name: AGE - type: date - name: v1alpha1 - schema: - openAPIV3Schema: - properties: - apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - type: string - kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - metadata: - type: object - spec: - description: GeneratingPolicySpec is the specification of the desired - behavior of the GeneratingPolicy. - properties: - evaluation: - description: EvaluationConfiguration defines the configuration for - the policy evaluation. - properties: - admission: - description: Admission controls policy evaluation during admission. - properties: - enabled: - default: true - description: |- - Enabled controls if rules are applied during admission. - Optional. Default value is "true". - type: boolean - type: object - generateExisting: - description: GenerateExisting defines the configuration for generating - resources for existing triggeres. - properties: - enabled: - default: false - description: |- - Enabled controls whether to trigger the policy for existing resources - If is set to "true" the policy will be triggered and applied to existing matched resources. - Optional. Defaults to "false" if not specified. - type: boolean - type: object - orphanDownstreamOnPolicyDelete: - description: OrphanDownstreamOnPolicyDelete defines the configuration - for orphaning downstream resources on policy delete. - properties: - enabled: - default: false - description: |- - Enabled controls whether generated resources should be deleted when the policy that generated - them is deleted with synchronization enabled. This option is only applicable to generate rules of the data type. - Optional. Defaults to "false" if not specified. - type: boolean - type: object - synchronize: - description: Synchronization defines the configuration for the - synchronization of generated resources. - properties: - enabled: - default: false - description: |- - Enabled controls if generated resources should be kept in-sync with their source resource. - If Synchronize is set to "true" changes to generated resources will be overwritten with resource - data from Data or the resource specified in the Clone declaration. - Optional. Defaults to "false" if not specified. - type: boolean - type: object - type: object - generate: - description: |- - Generation defines a set of CEL expressions that will be evaluated to generate resources. - Required. - items: - description: Generation defines the configuration for the generation - of resources. - properties: - expression: - description: Expression is a CEL expression that takes a list - of resources to be generated. - type: string - type: object - minItems: 1 - type: array - matchConditions: - description: |- - MatchConditions is a list of conditions that must be met for a request to be validated. - Match conditions filter requests that have already been matched by the rules, - namespaceSelector, and objectSelector. An empty list of matchConditions matches all requests. - There are a maximum of 64 match conditions allowed. - - If a parameter object is provided, it can be accessed via the `params` handle in the same - manner as validation expressions. - - The exact matching logic is (in order): - 1. If ANY matchCondition evaluates to FALSE, the policy is skipped. - 2. If ALL matchConditions evaluate to TRUE, the policy is evaluated. - 3. If any matchCondition evaluates to an error (but none are FALSE): - - If failurePolicy=Fail, reject the request - - If failurePolicy=Ignore, the policy is skipped - items: - description: MatchCondition represents a condition which must by - fulfilled for a request to be sent to a webhook. - properties: - expression: - description: |- - Expression represents the expression which will be evaluated by CEL. Must evaluate to bool. - CEL expressions have access to the contents of the AdmissionRequest and Authorizer, organized into CEL variables: - - 'object' - The object from the incoming request. The value is null for DELETE requests. - 'oldObject' - The existing object. The value is null for CREATE requests. - 'request' - Attributes of the admission request(/pkg/apis/admission/types.go#AdmissionRequest). - 'authorizer' - A CEL Authorizer. May be used to perform authorization checks for the principal (user or service account) of the request. - See https://pkg.go.dev/k8s.io/apiserver/pkg/cel/library#Authz - 'authorizer.requestResource' - A CEL ResourceCheck constructed from the 'authorizer' and configured with the - request resource. - Documentation on CEL: https://kubernetes.io/docs/reference/using-api/cel/ - - Required. - type: string - name: - description: |- - Name is an identifier for this match condition, used for strategic merging of MatchConditions, - as well as providing an identifier for logging purposes. A good name should be descriptive of - the associated expression. - Name must be a qualified name consisting of alphanumeric characters, '-', '_' or '.', and - must start and end with an alphanumeric character (e.g. 'MyName', or 'my.name', or - '123-abc', regex used for validation is '([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9]') with an - optional DNS subdomain prefix and '/' (e.g. 'example.com/MyName') - - Required. - type: string - required: - - expression - - name - type: object - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map - matchConstraints: - description: |- - MatchConstraints specifies what resources will trigger this policy. - The AdmissionPolicy cares about a request if it matches _all_ Constraints. - Required. - properties: - excludeResourceRules: - description: |- - ExcludeResourceRules describes what operations on what resources/subresources the ValidatingAdmissionPolicy should not care about. - The exclude rules take precedence over include rules (if a resource matches both, it is excluded) - items: - description: NamedRuleWithOperations is a tuple of Operations - and Resources with ResourceNames. - properties: - apiGroups: - description: |- - APIGroups is the API groups the resources belong to. '*' is all groups. - If '*' is present, the length of the slice must be one. - Required. - items: - type: string - type: array - x-kubernetes-list-type: atomic - apiVersions: - description: |- - APIVersions is the API versions the resources belong to. '*' is all versions. - If '*' is present, the length of the slice must be one. - Required. - items: - type: string - type: array - x-kubernetes-list-type: atomic - operations: - description: |- - Operations is the operations the admission hook cares about - CREATE, UPDATE, DELETE, CONNECT or * - for all of those operations and any future admission operations that are added. - If '*' is present, the length of the slice must be one. - Required. - items: - description: OperationType specifies an operation for - a request. - type: string - type: array - x-kubernetes-list-type: atomic - resourceNames: - description: ResourceNames is an optional white list of - names that the rule applies to. An empty set means that - everything is allowed. - items: - type: string - type: array - x-kubernetes-list-type: atomic - resources: - description: |- - Resources is a list of resources this rule applies to. - - For example: - 'pods' means pods. - 'pods/log' means the log subresource of pods. - '*' means all resources, but not subresources. - 'pods/*' means all subresources of pods. - '*/scale' means all scale subresources. - '*/*' means all resources and their subresources. - - If wildcard is present, the validation rule will ensure resources do not - overlap with each other. - - Depending on the enclosing object, subresources might not be allowed. - Required. - items: - type: string - type: array - x-kubernetes-list-type: atomic - scope: - description: |- - scope specifies the scope of this rule. - Valid values are "Cluster", "Namespaced", and "*" - "Cluster" means that only cluster-scoped resources will match this rule. - Namespace API objects are cluster-scoped. - "Namespaced" means that only namespaced resources will match this rule. - "*" means that there are no scope restrictions. - Subresources match the scope of their parent resource. - Default is "*". - type: string - type: object - x-kubernetes-map-type: atomic - type: array - x-kubernetes-list-type: atomic - matchPolicy: - description: |- - matchPolicy defines how the "MatchResources" list is used to match incoming requests. - Allowed values are "Exact" or "Equivalent". - - - Exact: match a request only if it exactly matches a specified rule. - For example, if deployments can be modified via apps/v1, apps/v1beta1, and extensions/v1beta1, - but "rules" only included `apiGroups:["apps"], apiVersions:["v1"], resources: ["deployments"]`, - a request to apps/v1beta1 or extensions/v1beta1 would not be sent to the ValidatingAdmissionPolicy. - - - Equivalent: match a request if modifies a resource listed in rules, even via another API group or version. - For example, if deployments can be modified via apps/v1, apps/v1beta1, and extensions/v1beta1, - and "rules" only included `apiGroups:["apps"], apiVersions:["v1"], resources: ["deployments"]`, - a request to apps/v1beta1 or extensions/v1beta1 would be converted to apps/v1 and sent to the ValidatingAdmissionPolicy. - - Defaults to "Equivalent" - type: string - namespaceSelector: - description: |- - NamespaceSelector decides whether to run the admission control policy on an object based - on whether the namespace for that object matches the selector. If the - object itself is a namespace, the matching is performed on - object.metadata.labels. If the object is another cluster scoped resource, - it never skips the policy. - - For example, to run the webhook on any objects whose namespace is not - associated with "runlevel" of "0" or "1"; you will set the selector as - follows: - "namespaceSelector": { - "matchExpressions": [ - { - "key": "runlevel", - "operator": "NotIn", - "values": [ - "0", - "1" - ] - } - ] - } - - If instead you want to only run the policy on any objects whose - namespace is associated with the "environment" of "prod" or "staging"; - you will set the selector as follows: - "namespaceSelector": { - "matchExpressions": [ - { - "key": "environment", - "operator": "In", - "values": [ - "prod", - "staging" - ] - } - ] - } - - See - https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/ - for more examples of label selectors. - - Default to the empty LabelSelector, which matches everything. - properties: - matchExpressions: - description: matchExpressions is a list of label selector - requirements. The requirements are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key that the selector - applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - objectSelector: - description: |- - ObjectSelector decides whether to run the validation based on if the - object has matching labels. objectSelector is evaluated against both - the oldObject and newObject that would be sent to the cel validation, and - is considered to match if either object matches the selector. A null - object (oldObject in the case of create, or newObject in the case of - delete) or an object that cannot have labels (like a - DeploymentRollback or a PodProxyOptions object) is not considered to - match. - Use the object selector only if the webhook is opt-in, because end - users may skip the admission webhook by setting the labels. - Default to the empty LabelSelector, which matches everything. - properties: - matchExpressions: - description: matchExpressions is a list of label selector - requirements. The requirements are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key that the selector - applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - resourceRules: - description: |- - ResourceRules describes what operations on what resources/subresources the ValidatingAdmissionPolicy matches. - The policy cares about an operation if it matches _any_ Rule. - items: - description: NamedRuleWithOperations is a tuple of Operations - and Resources with ResourceNames. - properties: - apiGroups: - description: |- - APIGroups is the API groups the resources belong to. '*' is all groups. - If '*' is present, the length of the slice must be one. - Required. - items: - type: string - type: array - x-kubernetes-list-type: atomic - apiVersions: - description: |- - APIVersions is the API versions the resources belong to. '*' is all versions. - If '*' is present, the length of the slice must be one. - Required. - items: - type: string - type: array - x-kubernetes-list-type: atomic - operations: - description: |- - Operations is the operations the admission hook cares about - CREATE, UPDATE, DELETE, CONNECT or * - for all of those operations and any future admission operations that are added. - If '*' is present, the length of the slice must be one. - Required. - items: - description: OperationType specifies an operation for - a request. - type: string - type: array - x-kubernetes-list-type: atomic - resourceNames: - description: ResourceNames is an optional white list of - names that the rule applies to. An empty set means that - everything is allowed. - items: - type: string - type: array - x-kubernetes-list-type: atomic - resources: - description: |- - Resources is a list of resources this rule applies to. - - For example: - 'pods' means pods. - 'pods/log' means the log subresource of pods. - '*' means all resources, but not subresources. - 'pods/*' means all subresources of pods. - '*/scale' means all scale subresources. - '*/*' means all resources and their subresources. - - If wildcard is present, the validation rule will ensure resources do not - overlap with each other. - - Depending on the enclosing object, subresources might not be allowed. - Required. - items: - type: string - type: array - x-kubernetes-list-type: atomic - scope: - description: |- - scope specifies the scope of this rule. - Valid values are "Cluster", "Namespaced", and "*" - "Cluster" means that only cluster-scoped resources will match this rule. - Namespace API objects are cluster-scoped. - "Namespaced" means that only namespaced resources will match this rule. - "*" means that there are no scope restrictions. - Subresources match the scope of their parent resource. - Default is "*". - type: string - type: object - x-kubernetes-map-type: atomic - type: array - x-kubernetes-list-type: atomic - type: object - x-kubernetes-map-type: atomic - variables: - description: |- - Variables contain definitions of variables that can be used in composition of other expressions. - Each variable is defined as a named CEL expression. - The variables defined here will be available under `variables` in other expressions of the policy - except MatchConditions because MatchConditions are evaluated before the rest of the policy. - - The expression of a variable can refer to other variables defined earlier in the list but not those after. - Thus, Variables must be sorted by the order of first appearance and acyclic. - items: - description: Variable is the definition of a variable that is used - for composition. A variable is defined as a named expression. - properties: - expression: - description: |- - Expression is the expression that will be evaluated as the value of the variable. - The CEL expression has access to the same identifiers as the CEL expressions in Validation. - type: string - name: - description: |- - Name is the name of the variable. The name must be a valid CEL identifier and unique among all variables. - The variable can be accessed in other expressions through `variables` - For example, if name is "foo", the variable will be available as `variables.foo` - type: string - required: - - expression - - name - type: object - x-kubernetes-map-type: atomic - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map - webhookConfiguration: - description: WebhookConfiguration defines the configuration for the - webhook. - properties: - timeoutSeconds: - description: |- - TimeoutSeconds specifies the maximum time in seconds allowed to apply this policy. - After the configured time expires, the admission request may fail, or may simply ignore the policy results, - based on the failure policy. The default timeout is 10s, the value must be between 1 and 30 seconds. - format: int32 - type: integer - type: object - required: - - generate - type: object - status: - description: Status contains policy runtime data. - properties: - conditionStatus: - description: ConditionStatus is the shared status across all policy - types - properties: - conditions: - items: - description: Condition contains details for one aspect of the - current state of this API Resource. - properties: - lastTransitionTime: - description: |- - lastTransitionTime is the last time the condition transitioned from one status to another. - This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable. - format: date-time - type: string - message: - description: |- - message is a human readable message indicating details about the transition. - This may be an empty string. - maxLength: 32768 - type: string - observedGeneration: - description: |- - observedGeneration represents the .metadata.generation that the condition was set based upon. - For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date - with respect to the current state of the instance. - format: int64 - minimum: 0 - type: integer - reason: - description: |- - reason contains a programmatic identifier indicating the reason for the condition's last transition. - Producers of specific condition types may define expected values and meanings for this field, - and whether the values are considered a guaranteed API. - The value should be a CamelCase string. - This field may not be empty. - maxLength: 1024 - minLength: 1 - pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ - type: string - status: - description: status of the condition, one of True, False, - Unknown. - enum: - - "True" - - "False" - - Unknown - type: string - type: - description: type of condition in CamelCase or in foo.example.com/CamelCase. - maxLength: 316 - pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ - type: string - required: - - lastTransitionTime - - message - - reason - - status - - type - type: object - type: array - message: - description: |- - Message is a human readable message indicating details about the generation of ValidatingAdmissionPolicy/MutatingAdmissionPolicy - It is an empty string when ValidatingAdmissionPolicy/MutatingAdmissionPolicy is successfully generated. - type: string - ready: - description: |- - The ready of a policy is a high-level summary of where the policy is in its lifecycle. - The conditions array, the reason and message fields contain more detail about the policy's status. - type: boolean - type: object - type: object - required: - - spec - type: object - served: true - storage: true - subresources: - status: {} ---- -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - labels: - app.kubernetes.io/component: crds - app.kubernetes.io/instance: kyverno - app.kubernetes.io/managed-by: Helm - app.kubernetes.io/part-of: kyverno-crds - app.kubernetes.io/version: 3.5.1 - helm.sh/chart: crds-3.5.1 - annotations: - controller-gen.kubebuilder.io/version: v0.17.3 - name: imagevalidatingpolicies.policies.kyverno.io -spec: - group: policies.kyverno.io - names: - categories: - - kyverno - kind: ImageValidatingPolicy - listKind: ImageValidatingPolicyList - plural: imagevalidatingpolicies - shortNames: - - ivpol - singular: imagevalidatingpolicy - scope: Cluster - versions: - - additionalPrinterColumns: - - jsonPath: .metadata.creationTimestamp - name: AGE - type: date - - jsonPath: .status.conditionStatus.ready - name: READY - type: string - name: v1alpha1 - schema: - openAPIV3Schema: - properties: - apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - type: string - kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - metadata: - type: object - spec: - description: ImageValidatingPolicySpec is the specification of the desired - behavior of the ImageValidatingPolicy. - properties: - attestations: - description: Attestations provides a list of image metadata to verify - items: - description: Attestation defines the identification details of the metadata - that has to be verified - properties: - intoto: - description: InToto defines the details of attestation attached - using intoto format - properties: - type: - description: Type defines the type of attestation contained - within the statement. - type: string - required: - - type - type: object - name: - description: Name is the name for this attestation. It is used - to refer to the attestation in verification - type: string - referrer: - description: Referrer defines the details of attestation attached - using OCI 1.1 format - properties: - type: - description: Type defines the type of attestation attached - to the image. - type: string - required: - - type - type: object - required: - - name - type: object - type: array - attestors: - description: Attestors provides a list of trusted authorities. - items: - description: Attestor is an identity that confirms or verifies the - authenticity of an image or an attestation - oneOf: - - required: - - cosign - - required: - - notary - properties: - cosign: - description: Cosign defines attestor configuration for Cosign - based signatures - properties: - annotations: - additionalProperties: - type: string - description: |- - Annotations are used for image verification. - Every specified key-value pair must exist and match in the verified payload. - The payload may contain other key-value pairs. - type: object - certificate: - description: Certificate defines the configuration for local - signature verification - properties: - cert: - description: Certificate is the to the public certificate - for local signature verification. - oneOf: - - required: - - value - - required: - - expression - properties: - expression: - description: Expression defines the a CEL expression - input. - type: string - value: - description: Value defines the raw string input. - type: string - type: object - certChain: - description: |- - CertificateChain is the list of CA certificates in PEM format which will be needed - when building the certificate chain for the signing certificate. Must start with the - parent intermediate CA certificate of the signing certificate and end with the root certificate - oneOf: - - required: - - value - - required: - - expression - properties: - expression: - description: Expression defines the a CEL expression - input. - type: string - value: - description: Value defines the raw string input. - type: string - type: object - type: object - ctlog: - description: CTLog sets the configuration to verify the - authority against a Rekor instance. - properties: - ctLogPubKey: - description: CTLogPubKey, if set, is used to validate - SCTs against a custom source. - type: string - insecureIgnoreSCT: - description: |- - IgnoreSCT defines whether to use the Signed Certificate Timestamp (SCT) log to check for a certificate - timestamp. Default is false. Set to true if this was opted out during signing. - type: boolean - insecureIgnoreTlog: - description: InsecureIgnoreTlog skips transparency log - verification. - type: boolean - rekorPubKey: - description: |- - RekorPubKey is an optional PEM-encoded public key to use for a custom Rekor. - If set, this will be used to validate transparency log signatures from a custom Rekor. - type: string - tsaCertChain: - description: |- - TSACertChain, if set, is the PEM-encoded certificate chain file for the RFC3161 timestamp authority. Must - contain the root CA certificate. Optionally may contain intermediate CA certificates, and - may contain the leaf TSA certificate if not present in the timestamurce. - type: string - url: - description: URL sets the url to the rekor instance - (by default the public rekor.sigstore.dev) - type: string - type: object - key: - description: Key defines the type of key to validate the - image. - properties: - data: - description: Data contains the inline public key - type: string - expression: - description: Expression is a Expression expression that - returns the public key. - type: string - hashAlgorithm: - description: |- - HashAlgorithm specifues signature algorithm for public keys. Supported values are - sha224, sha256, sha384 and sha512. Defaults to sha256. - type: string - kms: - description: |- - KMS contains the KMS url of the public key - Supported formats differ based on the KMS system used. - type: string - type: object - keyless: - description: Keyless sets the configuration to verify the - authority against a Fulcio instance. - properties: - identities: - description: Identities sets a list of identities. - items: - description: |- - Identity may contain the issuer and/or the subject found in the transparency - log. - Issuer/Subject uses a strict match, while IssuerRegExp and SubjectRegExp - apply a regexp for matching. - properties: - issuer: - description: Issuer defines the issuer for this - identity. - type: string - issuerRegExp: - description: IssuerRegExp specifies a regular - expression to match the issuer for this identity. - type: string - subject: - description: Subject defines the subject for this - identity. - type: string - subjectRegExp: - description: SubjectRegExp specifies a regular - expression to match the subject for this identity. - type: string - type: object - type: array - roots: - description: |- - Roots is an optional set of PEM encoded trusted root certificates. - If not provided, the system roots are used. - type: string - required: - - identities - type: object - source: - description: Sources sets the configuration to specify the - sources from where to consume the signature and attestations. - properties: - PullSecrets: - description: |- - SignaturePullSecrets is an optional list of references to secrets in the - same namespace as the deploying resource for pulling any of the signatures - used by this Source. - items: - description: |- - LocalObjectReference contains enough information to let you locate the - referenced object inside the same namespace. - properties: - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - type: string - type: object - x-kubernetes-map-type: atomic - type: array - repository: - description: Repository defines the location from where - to pull the signature / attestations. - type: string - tagPrefix: - description: |- - TagPrefix is an optional prefix that signature and attestations have. - This is the 'tag based discovery' and in the future once references are - fully supported that should likely be the preferred way to handle these. - type: string - type: object - tuf: - description: TUF defines the configuration to fetch sigstore - root - properties: - mirror: - description: Mirror is the base URL of Sigstore TUF - repository - type: string - root: - description: Root defines the path or data of the trusted - root - properties: - data: - description: Data is the base64 encoded TUF root - type: string - path: - description: Path is the URL or File location of - the TUF root - type: string - type: object - type: object - type: object - name: - description: Name is the name for this attestor. It is used - to refer to the attestor in verification - type: string - notary: - description: Notary defines attestor configuration for Notary - based signatures - properties: - certs: - description: Certs define the cert chain for Notary signature - verification - oneOf: - - required: - - value - - required: - - expression - properties: - expression: - description: Expression defines the a CEL expression - input. - type: string - value: - description: Value defines the raw string input. - type: string - type: object - tsaCerts: - description: TSACerts define the cert chain for verifying - timestamps of notary signature - oneOf: - - required: - - value - - required: - - expression - properties: - expression: - description: Expression defines the a CEL expression - input. - type: string - value: - description: Value defines the raw string input. - type: string - type: object - type: object - required: - - name - type: object - type: array - auditAnnotations: - description: |- - auditAnnotations contains CEL expressions which are used to produce audit - annotations for the audit event of the API request. - validations and auditAnnotations may not both be empty; a least one of validations or auditAnnotations is - required. - items: - description: AuditAnnotation describes how to produce an audit annotation - for an API request. - properties: - key: - description: |- - key specifies the audit annotation key. The audit annotation keys of - a ValidatingAdmissionPolicy must be unique. The key must be a qualified - name ([A-Za-z0-9][-A-Za-z0-9_.]*) no more than 63 bytes in length. - - The key is combined with the resource name of the - ValidatingAdmissionPolicy to construct an audit annotation key: - "{ValidatingAdmissionPolicy name}/{key}". - - If an admission webhook uses the same resource name as this ValidatingAdmissionPolicy - and the same audit annotation key, the annotation key will be identical. - In this case, the first annotation written with the key will be included - in the audit event and all subsequent annotations with the same key - will be discarded. - - Required. - type: string - valueExpression: - description: |- - valueExpression represents the expression which is evaluated by CEL to - produce an audit annotation value. The expression must evaluate to either - a string or null value. If the expression evaluates to a string, the - audit annotation is included with the string value. If the expression - evaluates to null or empty string the audit annotation will be omitted. - The valueExpression may be no longer than 5kb in length. - If the result of the valueExpression is more than 10kb in length, it - will be truncated to 10kb. - - If multiple ValidatingAdmissionPolicyBinding resources match an - API request, then the valueExpression will be evaluated for - each binding. All unique values produced by the valueExpressions - will be joined together in a comma-separated list. - - Required. - type: string - required: - - key - - valueExpression - type: object - type: array - x-kubernetes-list-type: atomic - autogen: - description: AutogenConfiguration defines the configuration for the - generation controller. - properties: - podControllers: - description: PodControllers specifies whether to generate a pod - controllers rules. - properties: - controllers: - items: - type: string - type: array - type: object - type: object - credentials: - description: Credentials provides credentials that will be used for - authentication with registry. - properties: - allowInsecureRegistry: - description: AllowInsecureRegistry allows insecure access to a - registry. - type: boolean - providers: - description: |- - Providers specifies a list of OCI Registry names, whose authentication providers are provided. - It can be of one of these values: default,google,azure,amazon,github. - items: - description: CredentialsProvidersType provides the list of credential - providers required. - enum: - - default - - amazon - - azure - - google - - github - type: string - type: array - secrets: - description: |- - Secrets specifies a list of secrets that are provided for credentials. - Secrets must live in the Kyverno namespace. - items: - type: string - type: array - type: object - evaluation: - description: EvaluationConfiguration defines the configuration for - the policy evaluation. - properties: - admission: - description: Admission controls policy evaluation during admission. - properties: - enabled: - default: true - description: |- - Enabled controls if rules are applied during admission. - Optional. Default value is "true". - type: boolean - type: object - background: - description: Background controls policy evaluation during background - scan. - properties: - enabled: - default: true - description: |- - Enabled controls if rules are applied to existing resources during a background scan. - Optional. Default value is "true". The value must be set to "false" if the policy rule - uses variables that are only available in the admission review request (e.g. user name). - type: boolean - type: object - mode: - description: |- - Mode is the mode of policy evaluation. - Allowed values are "Kubernetes" or "JSON". - Optional. Default value is "Kubernetes". - type: string - type: object - failurePolicy: - description: |- - FailurePolicy defines how to handle failures for the admission policy. Failures can - occur from CEL expression parse errors, type check errors, runtime errors and invalid - or mis-configured policy definitions or bindings. - enum: - - Ignore - - Fail - type: string - images: - description: ImageExtractors is a list of CEL expression to extract - images from the resource - items: - properties: - expression: - description: Expression defines CEL expression to extract images - from the resource. - type: string - name: - description: Name is the name for this imageList. It is used - to refer to the images in verification block as images. - type: string - required: - - expression - - name - type: object - type: array - matchConditions: - description: |- - MatchConditions is a list of conditions that must be met for a request to be validated. - Match conditions filter requests that have already been matched by the rules, - namespaceSelector, and objectSelector. An empty list of matchConditions matches all requests. - There are a maximum of 64 match conditions allowed. - items: - description: MatchCondition represents a condition which must by - fulfilled for a request to be sent to a webhook. - properties: - expression: - description: |- - Expression represents the expression which will be evaluated by CEL. Must evaluate to bool. - CEL expressions have access to the contents of the AdmissionRequest and Authorizer, organized into CEL variables: - - 'object' - The object from the incoming request. The value is null for DELETE requests. - 'oldObject' - The existing object. The value is null for CREATE requests. - 'request' - Attributes of the admission request(/pkg/apis/admission/types.go#AdmissionRequest). - 'authorizer' - A CEL Authorizer. May be used to perform authorization checks for the principal (user or service account) of the request. - See https://pkg.go.dev/k8s.io/apiserver/pkg/cel/library#Authz - 'authorizer.requestResource' - A CEL ResourceCheck constructed from the 'authorizer' and configured with the - request resource. - Documentation on CEL: https://kubernetes.io/docs/reference/using-api/cel/ - - Required. - type: string - name: - description: |- - Name is an identifier for this match condition, used for strategic merging of MatchConditions, - as well as providing an identifier for logging purposes. A good name should be descriptive of - the associated expression. - Name must be a qualified name consisting of alphanumeric characters, '-', '_' or '.', and - must start and end with an alphanumeric character (e.g. 'MyName', or 'my.name', or - '123-abc', regex used for validation is '([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9]') with an - optional DNS subdomain prefix and '/' (e.g. 'example.com/MyName') - - Required. - type: string - required: - - expression - - name - type: object - type: array - matchConstraints: - description: MatchConstraints specifies what resources this policy - is designed to validate. - properties: - excludeResourceRules: - description: |- - ExcludeResourceRules describes what operations on what resources/subresources the ValidatingAdmissionPolicy should not care about. - The exclude rules take precedence over include rules (if a resource matches both, it is excluded) - items: - description: NamedRuleWithOperations is a tuple of Operations - and Resources with ResourceNames. - properties: - apiGroups: - description: |- - APIGroups is the API groups the resources belong to. '*' is all groups. - If '*' is present, the length of the slice must be one. - Required. - items: - type: string - type: array - x-kubernetes-list-type: atomic - apiVersions: - description: |- - APIVersions is the API versions the resources belong to. '*' is all versions. - If '*' is present, the length of the slice must be one. - Required. - items: - type: string - type: array - x-kubernetes-list-type: atomic - operations: - description: |- - Operations is the operations the admission hook cares about - CREATE, UPDATE, DELETE, CONNECT or * - for all of those operations and any future admission operations that are added. - If '*' is present, the length of the slice must be one. - Required. - items: - description: OperationType specifies an operation for - a request. - type: string - type: array - x-kubernetes-list-type: atomic - resourceNames: - description: ResourceNames is an optional white list of - names that the rule applies to. An empty set means that - everything is allowed. - items: - type: string - type: array - x-kubernetes-list-type: atomic - resources: - description: |- - Resources is a list of resources this rule applies to. - - For example: - 'pods' means pods. - 'pods/log' means the log subresource of pods. - '*' means all resources, but not subresources. - 'pods/*' means all subresources of pods. - '*/scale' means all scale subresources. - '*/*' means all resources and their subresources. - - If wildcard is present, the validation rule will ensure resources do not - overlap with each other. - - Depending on the enclosing object, subresources might not be allowed. - Required. - items: - type: string - type: array - x-kubernetes-list-type: atomic - scope: - description: |- - scope specifies the scope of this rule. - Valid values are "Cluster", "Namespaced", and "*" - "Cluster" means that only cluster-scoped resources will match this rule. - Namespace API objects are cluster-scoped. - "Namespaced" means that only namespaced resources will match this rule. - "*" means that there are no scope restrictions. - Subresources match the scope of their parent resource. - Default is "*". - type: string - type: object - x-kubernetes-map-type: atomic - type: array - x-kubernetes-list-type: atomic - matchPolicy: - description: |- - matchPolicy defines how the "MatchResources" list is used to match incoming requests. - Allowed values are "Exact" or "Equivalent". - - - Exact: match a request only if it exactly matches a specified rule. - For example, if deployments can be modified via apps/v1, apps/v1beta1, and extensions/v1beta1, - but "rules" only included `apiGroups:["apps"], apiVersions:["v1"], resources: ["deployments"]`, - a request to apps/v1beta1 or extensions/v1beta1 would not be sent to the ValidatingAdmissionPolicy. - - - Equivalent: match a request if modifies a resource listed in rules, even via another API group or version. - For example, if deployments can be modified via apps/v1, apps/v1beta1, and extensions/v1beta1, - and "rules" only included `apiGroups:["apps"], apiVersions:["v1"], resources: ["deployments"]`, - a request to apps/v1beta1 or extensions/v1beta1 would be converted to apps/v1 and sent to the ValidatingAdmissionPolicy. - - Defaults to "Equivalent" - type: string - namespaceSelector: - description: |- - NamespaceSelector decides whether to run the admission control policy on an object based - on whether the namespace for that object matches the selector. If the - object itself is a namespace, the matching is performed on - object.metadata.labels. If the object is another cluster scoped resource, - it never skips the policy. - - For example, to run the webhook on any objects whose namespace is not - associated with "runlevel" of "0" or "1"; you will set the selector as - follows: - "namespaceSelector": { - "matchExpressions": [ - { - "key": "runlevel", - "operator": "NotIn", - "values": [ - "0", - "1" - ] - } - ] - } - - If instead you want to only run the policy on any objects whose - namespace is associated with the "environment" of "prod" or "staging"; - you will set the selector as follows: - "namespaceSelector": { - "matchExpressions": [ - { - "key": "environment", - "operator": "In", - "values": [ - "prod", - "staging" - ] - } - ] - } - - See - https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/ - for more examples of label selectors. - - Default to the empty LabelSelector, which matches everything. - properties: - matchExpressions: - description: matchExpressions is a list of label selector - requirements. The requirements are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key that the selector - applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - objectSelector: - description: |- - ObjectSelector decides whether to run the validation based on if the - object has matching labels. objectSelector is evaluated against both - the oldObject and newObject that would be sent to the cel validation, and - is considered to match if either object matches the selector. A null - object (oldObject in the case of create, or newObject in the case of - delete) or an object that cannot have labels (like a - DeploymentRollback or a PodProxyOptions object) is not considered to - match. - Use the object selector only if the webhook is opt-in, because end - users may skip the admission webhook by setting the labels. - Default to the empty LabelSelector, which matches everything. - properties: - matchExpressions: - description: matchExpressions is a list of label selector - requirements. The requirements are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key that the selector - applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - resourceRules: - description: |- - ResourceRules describes what operations on what resources/subresources the ValidatingAdmissionPolicy matches. - The policy cares about an operation if it matches _any_ Rule. - items: - description: NamedRuleWithOperations is a tuple of Operations - and Resources with ResourceNames. - properties: - apiGroups: - description: |- - APIGroups is the API groups the resources belong to. '*' is all groups. - If '*' is present, the length of the slice must be one. - Required. - items: - type: string - type: array - x-kubernetes-list-type: atomic - apiVersions: - description: |- - APIVersions is the API versions the resources belong to. '*' is all versions. - If '*' is present, the length of the slice must be one. - Required. - items: - type: string - type: array - x-kubernetes-list-type: atomic - operations: - description: |- - Operations is the operations the admission hook cares about - CREATE, UPDATE, DELETE, CONNECT or * - for all of those operations and any future admission operations that are added. - If '*' is present, the length of the slice must be one. - Required. - items: - description: OperationType specifies an operation for - a request. - type: string - type: array - x-kubernetes-list-type: atomic - resourceNames: - description: ResourceNames is an optional white list of - names that the rule applies to. An empty set means that - everything is allowed. - items: - type: string - type: array - x-kubernetes-list-type: atomic - resources: - description: |- - Resources is a list of resources this rule applies to. - - For example: - 'pods' means pods. - 'pods/log' means the log subresource of pods. - '*' means all resources, but not subresources. - 'pods/*' means all subresources of pods. - '*/scale' means all scale subresources. - '*/*' means all resources and their subresources. - - If wildcard is present, the validation rule will ensure resources do not - overlap with each other. - - Depending on the enclosing object, subresources might not be allowed. - Required. - items: - type: string - type: array - x-kubernetes-list-type: atomic - scope: - description: |- - scope specifies the scope of this rule. - Valid values are "Cluster", "Namespaced", and "*" - "Cluster" means that only cluster-scoped resources will match this rule. - Namespace API objects are cluster-scoped. - "Namespaced" means that only namespaced resources will match this rule. - "*" means that there are no scope restrictions. - Subresources match the scope of their parent resource. - Default is "*". - type: string - type: object - x-kubernetes-map-type: atomic - type: array - x-kubernetes-list-type: atomic - type: object - x-kubernetes-map-type: atomic - matchImageReferences: - description: |- - MatchImageReferences is a list of Glob and CELExpressions to match images. - Any image that matches one of the rules is considered for validation - Any image that does not match a rule is skipped, even when they are passed as arguments to - image verification functions - items: - description: MatchImageReference defines a Glob or a CEL expression - for matching images - oneOf: - - required: - - glob - - required: - - expression - properties: - expression: - description: Expression defines CEL Expressions for matching - images - type: string - glob: - description: Glob defines a globbing pattern for matching images - type: string - type: object - type: array - validationActions: - description: |- - ValidationAction specifies the action to be taken when the matched resource violates the policy. - Required. - items: - description: ValidationAction specifies a policy enforcement action. - enum: - - Deny - - Audit - - Warn - type: string - type: array - x-kubernetes-list-type: set - validationConfigurations: - default: {} - description: ValidationConfigurations defines settings for mutating - and verifying image digests, and enforcing image verification through - signatures. - properties: - mutateDigest: - default: true - description: |- - MutateDigest enables replacement of image tags with digests. - Defaults to true. - type: boolean - required: - default: true - description: Required validates that images are verified, i.e., - have passed a signature or attestation check. - type: boolean - verifyDigest: - default: true - description: VerifyDigest validates that images have a digest. - type: boolean - type: object - validations: - description: Validations contain CEL expressions which is used to - apply the image validation checks. - items: - description: Validation specifies the CEL expression which is used - to apply the validation. - properties: - expression: - description: "Expression represents the expression which will - be evaluated by CEL.\nref: https://github.com/google/cel-spec\nCEL - expressions have access to the contents of the API request/response, - organized into CEL variables as well as some other useful - variables:\n\n- 'object' - The object from the incoming request. - The value is null for DELETE requests.\n- 'oldObject' - The - existing object. The value is null for CREATE requests.\n- - 'request' - Attributes of the API request([ref](/pkg/apis/admission/types.go#AdmissionRequest)).\n- - 'params' - Parameter resource referred to by the policy binding - being evaluated. Only populated if the policy has a ParamKind.\n- - 'namespaceObject' - The namespace object that the incoming - object belongs to. The value is null for cluster-scoped resources.\n- - 'variables' - Map of composited variables, from its name to - its lazily evaluated value.\n For example, a variable named - 'foo' can be accessed as 'variables.foo'.\n- 'authorizer' - - A CEL Authorizer. May be used to perform authorization checks - for the principal (user or service account) of the request.\n - \ See https://pkg.go.dev/k8s.io/apiserver/pkg/cel/library#Authz\n- - 'authorizer.requestResource' - A CEL ResourceCheck constructed - from the 'authorizer' and configured with the\n request resource.\n\nThe - `apiVersion`, `kind`, `metadata.name` and `metadata.generateName` - are always accessible from the root of the\nobject. No other - metadata properties are accessible.\n\nOnly property names - of the form `[a-zA-Z_.-/][a-zA-Z0-9_.-/]*` are accessible.\nAccessible - property names are escaped according to the following rules - when accessed in the expression:\n- '__' escapes to '__underscores__'\n- - '.' escapes to '__dot__'\n- '-' escapes to '__dash__'\n- '/' - escapes to '__slash__'\n- Property names that exactly match - a CEL RESERVED keyword escape to '__{keyword}__'. The keywords - are:\n\t \"true\", \"false\", \"null\", \"in\", \"as\", \"break\", - \"const\", \"continue\", \"else\", \"for\", \"function\", - \"if\",\n\t \"import\", \"let\", \"loop\", \"package\", \"namespace\", - \"return\".\nExamples:\n - Expression accessing a property - named \"namespace\": {\"Expression\": \"object.__namespace__ - > 0\"}\n - Expression accessing a property named \"x-prop\": - {\"Expression\": \"object.x__dash__prop > 0\"}\n - Expression - accessing a property named \"redact__d\": {\"Expression\": - \"object.redact__underscores__d > 0\"}\n\nEquality on arrays - with list type of 'set' or 'map' ignores element order, i.e. - [1, 2] == [2, 1].\nConcatenation on arrays with x-kubernetes-list-type - use the semantics of the list type:\n - 'set': `X + Y` performs - a union where the array positions of all elements in `X` are - preserved and\n non-intersecting elements in `Y` are appended, - retaining their partial order.\n - 'map': `X + Y` performs - a merge where the array positions of all keys in `X` are preserved - but the values\n are overwritten by values in `Y` when - the key sets of `X` and `Y` intersect. Elements in `Y` with\n - \ non-intersecting keys are appended, retaining their partial - order.\nRequired." - type: string - message: - description: |- - Message represents the message displayed when validation fails. The message is required if the Expression contains - line breaks. The message must not contain line breaks. - If unset, the message is "failed rule: {Rule}". - e.g. "must be a URL with the host matching spec.host" - If the Expression contains line breaks. Message is required. - The message must not contain line breaks. - If unset, the message is "failed Expression: {Expression}". - type: string - messageExpression: - description: |- - messageExpression declares a CEL expression that evaluates to the validation failure message that is returned when this rule fails. - Since messageExpression is used as a failure message, it must evaluate to a string. - If both message and messageExpression are present on a validation, then messageExpression will be used if validation fails. - If messageExpression results in a runtime error, the runtime error is logged, and the validation failure message is produced - as if the messageExpression field were unset. If messageExpression evaluates to an empty string, a string with only spaces, or a string - that contains line breaks, then the validation failure message will also be produced as if the messageExpression field were unset, and - the fact that messageExpression produced an empty string/string with only spaces/string with line breaks will be logged. - messageExpression has access to all the same variables as the `expression` except for 'authorizer' and 'authorizer.requestResource'. - Example: - "object.x must be less than max ("+string(params.max)+")" - type: string - reason: - description: |- - Reason represents a machine-readable description of why this validation failed. - If this is the first validation in the list to fail, this reason, as well as the - corresponding HTTP response code, are used in the - HTTP response to the client. - The currently supported reasons are: "Unauthorized", "Forbidden", "Invalid", "RequestEntityTooLarge". - If not set, StatusReasonInvalid is used in the response to the client. - type: string - required: - - expression - type: object - type: array - x-kubernetes-list-type: atomic - variables: - description: |- - Variables contain definitions of variables that can be used in composition of other expressions. - Each variable is defined as a named CEL expression. - items: - description: Variable is the definition of a variable that is used - for composition. A variable is defined as a named expression. - properties: - expression: - description: |- - Expression is the expression that will be evaluated as the value of the variable. - The CEL expression has access to the same identifiers as the CEL expressions in Validation. - type: string - name: - description: |- - Name is the name of the variable. The name must be a valid CEL identifier and unique among all variables. - The variable can be accessed in other expressions through `variables` - For example, if name is "foo", the variable will be available as `variables.foo` - type: string - required: - - expression - - name - type: object - x-kubernetes-map-type: atomic - type: array - webhookConfiguration: - description: WebhookConfiguration defines the configuration for the - webhook. - properties: - timeoutSeconds: - description: |- - TimeoutSeconds specifies the maximum time in seconds allowed to apply this policy. - After the configured time expires, the admission request may fail, or may simply ignore the policy results, - based on the failure policy. The default timeout is 10s, the value must be between 1 and 30 seconds. - format: int32 - type: integer - type: object - required: - - attestors - - validations - type: object - status: - description: Status contains policy runtime data. - properties: - autogen: - properties: - configs: - additionalProperties: - properties: - spec: - description: ImageValidatingPolicySpec is the specification - of the desired behavior of the ImageValidatingPolicy. - properties: - attestations: - description: Attestations provides a list of image metadata - to verify - items: - description: Attestation defines the identification - details of the metadata that has to be verified - properties: - intoto: - description: InToto defines the details of attestation - attached using intoto format - properties: - type: - description: Type defines the type of attestation - contained within the statement. - type: string - required: - - type - type: object - name: - description: Name is the name for this attestation. - It is used to refer to the attestation in verification - type: string - referrer: - description: Referrer defines the details of attestation - attached using OCI 1.1 format - properties: - type: - description: Type defines the type of attestation - attached to the image. - type: string - required: - - type - type: object - required: - - name - type: object - type: array - attestors: - description: Attestors provides a list of trusted authorities. - items: - description: Attestor is an identity that confirms - or verifies the authenticity of an image or an attestation - oneOf: - - required: - - cosign - - required: - - notary - properties: - cosign: - description: Cosign defines attestor configuration - for Cosign based signatures - properties: - annotations: - additionalProperties: - type: string - description: |- - Annotations are used for image verification. - Every specified key-value pair must exist and match in the verified payload. - The payload may contain other key-value pairs. - type: object - certificate: - description: Certificate defines the configuration - for local signature verification - properties: - cert: - description: Certificate is the to the - public certificate for local signature - verification. - oneOf: - - required: - - value - - required: - - expression - properties: - expression: - description: Expression defines the - a CEL expression input. - type: string - value: - description: Value defines the raw - string input. - type: string - type: object - certChain: - description: |- - CertificateChain is the list of CA certificates in PEM format which will be needed - when building the certificate chain for the signing certificate. Must start with the - parent intermediate CA certificate of the signing certificate and end with the root certificate - oneOf: - - required: - - value - - required: - - expression - properties: - expression: - description: Expression defines the - a CEL expression input. - type: string - value: - description: Value defines the raw - string input. - type: string - type: object - type: object - ctlog: - description: CTLog sets the configuration - to verify the authority against a Rekor - instance. - properties: - ctLogPubKey: - description: CTLogPubKey, if set, is used - to validate SCTs against a custom source. - type: string - insecureIgnoreSCT: - description: |- - IgnoreSCT defines whether to use the Signed Certificate Timestamp (SCT) log to check for a certificate - timestamp. Default is false. Set to true if this was opted out during signing. - type: boolean - insecureIgnoreTlog: - description: InsecureIgnoreTlog skips - transparency log verification. - type: boolean - rekorPubKey: - description: |- - RekorPubKey is an optional PEM-encoded public key to use for a custom Rekor. - If set, this will be used to validate transparency log signatures from a custom Rekor. - type: string - tsaCertChain: - description: |- - TSACertChain, if set, is the PEM-encoded certificate chain file for the RFC3161 timestamp authority. Must - contain the root CA certificate. Optionally may contain intermediate CA certificates, and - may contain the leaf TSA certificate if not present in the timestamurce. - type: string - url: - description: URL sets the url to the rekor - instance (by default the public rekor.sigstore.dev) - type: string - type: object - key: - description: Key defines the type of key to - validate the image. - properties: - data: - description: Data contains the inline - public key - type: string - expression: - description: Expression is a Expression - expression that returns the public key. - type: string - hashAlgorithm: - description: |- - HashAlgorithm specifues signature algorithm for public keys. Supported values are - sha224, sha256, sha384 and sha512. Defaults to sha256. - type: string - kms: - description: |- - KMS contains the KMS url of the public key - Supported formats differ based on the KMS system used. - type: string - type: object - keyless: - description: Keyless sets the configuration - to verify the authority against a Fulcio - instance. - properties: - identities: - description: Identities sets a list of - identities. - items: - description: |- - Identity may contain the issuer and/or the subject found in the transparency - log. - Issuer/Subject uses a strict match, while IssuerRegExp and SubjectRegExp - apply a regexp for matching. - properties: - issuer: - description: Issuer defines the - issuer for this identity. - type: string - issuerRegExp: - description: IssuerRegExp specifies - a regular expression to match - the issuer for this identity. - type: string - subject: - description: Subject defines the - subject for this identity. - type: string - subjectRegExp: - description: SubjectRegExp specifies - a regular expression to match - the subject for this identity. - type: string - type: object - type: array - roots: - description: |- - Roots is an optional set of PEM encoded trusted root certificates. - If not provided, the system roots are used. - type: string - required: - - identities - type: object - source: - description: Sources sets the configuration - to specify the sources from where to consume - the signature and attestations. - properties: - PullSecrets: - description: |- - SignaturePullSecrets is an optional list of references to secrets in the - same namespace as the deploying resource for pulling any of the signatures - used by this Source. - items: - description: |- - LocalObjectReference contains enough information to let you locate the - referenced object inside the same namespace. - properties: - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - type: string - type: object - x-kubernetes-map-type: atomic - type: array - repository: - description: Repository defines the location - from where to pull the signature / attestations. - type: string - tagPrefix: - description: |- - TagPrefix is an optional prefix that signature and attestations have. - This is the 'tag based discovery' and in the future once references are - fully supported that should likely be the preferred way to handle these. - type: string - type: object - tuf: - description: TUF defines the configuration - to fetch sigstore root - properties: - mirror: - description: Mirror is the base URL of - Sigstore TUF repository - type: string - root: - description: Root defines the path or - data of the trusted root - properties: - data: - description: Data is the base64 encoded - TUF root - type: string - path: - description: Path is the URL or File - location of the TUF root - type: string - type: object - type: object - type: object - name: - description: Name is the name for this attestor. - It is used to refer to the attestor in verification - type: string - notary: - description: Notary defines attestor configuration - for Notary based signatures - properties: - certs: - description: Certs define the cert chain for - Notary signature verification - oneOf: - - required: - - value - - required: - - expression - properties: - expression: - description: Expression defines the a - CEL expression input. - type: string - value: - description: Value defines the raw string - input. - type: string - type: object - tsaCerts: - description: TSACerts define the cert chain - for verifying timestamps of notary signature - oneOf: - - required: - - value - - required: - - expression - properties: - expression: - description: Expression defines the a - CEL expression input. - type: string - value: - description: Value defines the raw string - input. - type: string - type: object - type: object - required: - - name - type: object - type: array - auditAnnotations: - description: |- - auditAnnotations contains CEL expressions which are used to produce audit - annotations for the audit event of the API request. - validations and auditAnnotations may not both be empty; a least one of validations or auditAnnotations is - required. - items: - description: AuditAnnotation describes how to produce - an audit annotation for an API request. - properties: - key: - description: |- - key specifies the audit annotation key. The audit annotation keys of - a ValidatingAdmissionPolicy must be unique. The key must be a qualified - name ([A-Za-z0-9][-A-Za-z0-9_.]*) no more than 63 bytes in length. - - The key is combined with the resource name of the - ValidatingAdmissionPolicy to construct an audit annotation key: - "{ValidatingAdmissionPolicy name}/{key}". - - If an admission webhook uses the same resource name as this ValidatingAdmissionPolicy - and the same audit annotation key, the annotation key will be identical. - In this case, the first annotation written with the key will be included - in the audit event and all subsequent annotations with the same key - will be discarded. - - Required. - type: string - valueExpression: - description: |- - valueExpression represents the expression which is evaluated by CEL to - produce an audit annotation value. The expression must evaluate to either - a string or null value. If the expression evaluates to a string, the - audit annotation is included with the string value. If the expression - evaluates to null or empty string the audit annotation will be omitted. - The valueExpression may be no longer than 5kb in length. - If the result of the valueExpression is more than 10kb in length, it - will be truncated to 10kb. - - If multiple ValidatingAdmissionPolicyBinding resources match an - API request, then the valueExpression will be evaluated for - each binding. All unique values produced by the valueExpressions - will be joined together in a comma-separated list. - - Required. - type: string - required: - - key - - valueExpression - type: object - type: array - x-kubernetes-list-type: atomic - autogen: - description: AutogenConfiguration defines the configuration - for the generation controller. - properties: - podControllers: - description: PodControllers specifies whether to - generate a pod controllers rules. - properties: - controllers: - items: - type: string - type: array - type: object - type: object - credentials: - description: Credentials provides credentials that will - be used for authentication with registry. - properties: - allowInsecureRegistry: - description: AllowInsecureRegistry allows insecure - access to a registry. - type: boolean - providers: - description: |- - Providers specifies a list of OCI Registry names, whose authentication providers are provided. - It can be of one of these values: default,google,azure,amazon,github. - items: - description: CredentialsProvidersType provides - the list of credential providers required. - enum: - - default - - amazon - - azure - - google - - github - type: string - type: array - secrets: - description: |- - Secrets specifies a list of secrets that are provided for credentials. - Secrets must live in the Kyverno namespace. - items: - type: string - type: array - type: object - evaluation: - description: EvaluationConfiguration defines the configuration - for the policy evaluation. - properties: - admission: - description: Admission controls policy evaluation - during admission. - properties: - enabled: - default: true - description: |- - Enabled controls if rules are applied during admission. - Optional. Default value is "true". - type: boolean - type: object - background: - description: Background controls policy evaluation - during background scan. - properties: - enabled: - default: true - description: |- - Enabled controls if rules are applied to existing resources during a background scan. - Optional. Default value is "true". The value must be set to "false" if the policy rule - uses variables that are only available in the admission review request (e.g. user name). - type: boolean - type: object - mode: - description: |- - Mode is the mode of policy evaluation. - Allowed values are "Kubernetes" or "JSON". - Optional. Default value is "Kubernetes". - type: string - type: object - failurePolicy: - description: |- - FailurePolicy defines how to handle failures for the admission policy. Failures can - occur from CEL expression parse errors, type check errors, runtime errors and invalid - or mis-configured policy definitions or bindings. - enum: - - Ignore - - Fail - type: string - images: - description: ImageExtractors is a list of CEL expression - to extract images from the resource - items: - properties: - expression: - description: Expression defines CEL expression - to extract images from the resource. - type: string - name: - description: Name is the name for this imageList. - It is used to refer to the images in verification - block as images. - type: string - required: - - expression - - name - type: object - type: array - matchConditions: - description: |- - MatchConditions is a list of conditions that must be met for a request to be validated. - Match conditions filter requests that have already been matched by the rules, - namespaceSelector, and objectSelector. An empty list of matchConditions matches all requests. - There are a maximum of 64 match conditions allowed. - items: - description: MatchCondition represents a condition - which must by fulfilled for a request to be sent - to a webhook. - properties: - expression: - description: |- - Expression represents the expression which will be evaluated by CEL. Must evaluate to bool. - CEL expressions have access to the contents of the AdmissionRequest and Authorizer, organized into CEL variables: - - 'object' - The object from the incoming request. The value is null for DELETE requests. - 'oldObject' - The existing object. The value is null for CREATE requests. - 'request' - Attributes of the admission request(/pkg/apis/admission/types.go#AdmissionRequest). - 'authorizer' - A CEL Authorizer. May be used to perform authorization checks for the principal (user or service account) of the request. - See https://pkg.go.dev/k8s.io/apiserver/pkg/cel/library#Authz - 'authorizer.requestResource' - A CEL ResourceCheck constructed from the 'authorizer' and configured with the - request resource. - Documentation on CEL: https://kubernetes.io/docs/reference/using-api/cel/ - - Required. - type: string - name: - description: |- - Name is an identifier for this match condition, used for strategic merging of MatchConditions, - as well as providing an identifier for logging purposes. A good name should be descriptive of - the associated expression. - Name must be a qualified name consisting of alphanumeric characters, '-', '_' or '.', and - must start and end with an alphanumeric character (e.g. 'MyName', or 'my.name', or - '123-abc', regex used for validation is '([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9]') with an - optional DNS subdomain prefix and '/' (e.g. 'example.com/MyName') - - Required. - type: string - required: - - expression - - name - type: object - type: array - matchConstraints: - description: MatchConstraints specifies what resources - this policy is designed to validate. - properties: - excludeResourceRules: - description: |- - ExcludeResourceRules describes what operations on what resources/subresources the ValidatingAdmissionPolicy should not care about. - The exclude rules take precedence over include rules (if a resource matches both, it is excluded) - items: - description: NamedRuleWithOperations is a tuple - of Operations and Resources with ResourceNames. - properties: - apiGroups: - description: |- - APIGroups is the API groups the resources belong to. '*' is all groups. - If '*' is present, the length of the slice must be one. - Required. - items: - type: string - type: array - x-kubernetes-list-type: atomic - apiVersions: - description: |- - APIVersions is the API versions the resources belong to. '*' is all versions. - If '*' is present, the length of the slice must be one. - Required. - items: - type: string - type: array - x-kubernetes-list-type: atomic - operations: - description: |- - Operations is the operations the admission hook cares about - CREATE, UPDATE, DELETE, CONNECT or * - for all of those operations and any future admission operations that are added. - If '*' is present, the length of the slice must be one. - Required. - items: - description: OperationType specifies an - operation for a request. - type: string - type: array - x-kubernetes-list-type: atomic - resourceNames: - description: ResourceNames is an optional - white list of names that the rule applies - to. An empty set means that everything - is allowed. - items: - type: string - type: array - x-kubernetes-list-type: atomic - resources: - description: |- - Resources is a list of resources this rule applies to. - - For example: - 'pods' means pods. - 'pods/log' means the log subresource of pods. - '*' means all resources, but not subresources. - 'pods/*' means all subresources of pods. - '*/scale' means all scale subresources. - '*/*' means all resources and their subresources. - - If wildcard is present, the validation rule will ensure resources do not - overlap with each other. - - Depending on the enclosing object, subresources might not be allowed. - Required. - items: - type: string - type: array - x-kubernetes-list-type: atomic - scope: - description: |- - scope specifies the scope of this rule. - Valid values are "Cluster", "Namespaced", and "*" - "Cluster" means that only cluster-scoped resources will match this rule. - Namespace API objects are cluster-scoped. - "Namespaced" means that only namespaced resources will match this rule. - "*" means that there are no scope restrictions. - Subresources match the scope of their parent resource. - Default is "*". - type: string - type: object - x-kubernetes-map-type: atomic - type: array - x-kubernetes-list-type: atomic - matchPolicy: - description: |- - matchPolicy defines how the "MatchResources" list is used to match incoming requests. - Allowed values are "Exact" or "Equivalent". - - - Exact: match a request only if it exactly matches a specified rule. - For example, if deployments can be modified via apps/v1, apps/v1beta1, and extensions/v1beta1, - but "rules" only included `apiGroups:["apps"], apiVersions:["v1"], resources: ["deployments"]`, - a request to apps/v1beta1 or extensions/v1beta1 would not be sent to the ValidatingAdmissionPolicy. - - - Equivalent: match a request if modifies a resource listed in rules, even via another API group or version. - For example, if deployments can be modified via apps/v1, apps/v1beta1, and extensions/v1beta1, - and "rules" only included `apiGroups:["apps"], apiVersions:["v1"], resources: ["deployments"]`, - a request to apps/v1beta1 or extensions/v1beta1 would be converted to apps/v1 and sent to the ValidatingAdmissionPolicy. - - Defaults to "Equivalent" - type: string - namespaceSelector: - description: |- - NamespaceSelector decides whether to run the admission control policy on an object based - on whether the namespace for that object matches the selector. If the - object itself is a namespace, the matching is performed on - object.metadata.labels. If the object is another cluster scoped resource, - it never skips the policy. - - For example, to run the webhook on any objects whose namespace is not - associated with "runlevel" of "0" or "1"; you will set the selector as - follows: - "namespaceSelector": { - "matchExpressions": [ - { - "key": "runlevel", - "operator": "NotIn", - "values": [ - "0", - "1" - ] - } - ] - } - - If instead you want to only run the policy on any objects whose - namespace is associated with the "environment" of "prod" or "staging"; - you will set the selector as follows: - "namespaceSelector": { - "matchExpressions": [ - { - "key": "environment", - "operator": "In", - "values": [ - "prod", - "staging" - ] - } - ] - } - - See - https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/ - for more examples of label selectors. - - Default to the empty LabelSelector, which matches everything. - properties: - matchExpressions: - description: matchExpressions is a list of label - selector requirements. The requirements are - ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key that - the selector applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - objectSelector: - description: |- - ObjectSelector decides whether to run the validation based on if the - object has matching labels. objectSelector is evaluated against both - the oldObject and newObject that would be sent to the cel validation, and - is considered to match if either object matches the selector. A null - object (oldObject in the case of create, or newObject in the case of - delete) or an object that cannot have labels (like a - DeploymentRollback or a PodProxyOptions object) is not considered to - match. - Use the object selector only if the webhook is opt-in, because end - users may skip the admission webhook by setting the labels. - Default to the empty LabelSelector, which matches everything. - properties: - matchExpressions: - description: matchExpressions is a list of label - selector requirements. The requirements are - ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key that - the selector applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - resourceRules: - description: |- - ResourceRules describes what operations on what resources/subresources the ValidatingAdmissionPolicy matches. - The policy cares about an operation if it matches _any_ Rule. - items: - description: NamedRuleWithOperations is a tuple - of Operations and Resources with ResourceNames. - properties: - apiGroups: - description: |- - APIGroups is the API groups the resources belong to. '*' is all groups. - If '*' is present, the length of the slice must be one. - Required. - items: - type: string - type: array - x-kubernetes-list-type: atomic - apiVersions: - description: |- - APIVersions is the API versions the resources belong to. '*' is all versions. - If '*' is present, the length of the slice must be one. - Required. - items: - type: string - type: array - x-kubernetes-list-type: atomic - operations: - description: |- - Operations is the operations the admission hook cares about - CREATE, UPDATE, DELETE, CONNECT or * - for all of those operations and any future admission operations that are added. - If '*' is present, the length of the slice must be one. - Required. - items: - description: OperationType specifies an - operation for a request. - type: string - type: array - x-kubernetes-list-type: atomic - resourceNames: - description: ResourceNames is an optional - white list of names that the rule applies - to. An empty set means that everything - is allowed. - items: - type: string - type: array - x-kubernetes-list-type: atomic - resources: - description: |- - Resources is a list of resources this rule applies to. - - For example: - 'pods' means pods. - 'pods/log' means the log subresource of pods. - '*' means all resources, but not subresources. - 'pods/*' means all subresources of pods. - '*/scale' means all scale subresources. - '*/*' means all resources and their subresources. - - If wildcard is present, the validation rule will ensure resources do not - overlap with each other. - - Depending on the enclosing object, subresources might not be allowed. - Required. - items: - type: string - type: array - x-kubernetes-list-type: atomic - scope: - description: |- - scope specifies the scope of this rule. - Valid values are "Cluster", "Namespaced", and "*" - "Cluster" means that only cluster-scoped resources will match this rule. - Namespace API objects are cluster-scoped. - "Namespaced" means that only namespaced resources will match this rule. - "*" means that there are no scope restrictions. - Subresources match the scope of their parent resource. - Default is "*". - type: string - type: object - x-kubernetes-map-type: atomic - type: array - x-kubernetes-list-type: atomic - type: object - x-kubernetes-map-type: atomic - matchImageReferences: - description: |- - MatchImageReferences is a list of Glob and CELExpressions to match images. - Any image that matches one of the rules is considered for validation - Any image that does not match a rule is skipped, even when they are passed as arguments to - image verification functions - items: - description: MatchImageReference defines a Glob or - a CEL expression for matching images - oneOf: - - required: - - glob - - required: - - expression - properties: - expression: - description: Expression defines CEL Expressions - for matching images - type: string - glob: - description: Glob defines a globbing pattern for - matching images - type: string - type: object - type: array - validationActions: - description: |- - ValidationAction specifies the action to be taken when the matched resource violates the policy. - Required. - items: - description: ValidationAction specifies a policy enforcement - action. - enum: - - Deny - - Audit - - Warn - type: string - type: array - x-kubernetes-list-type: set - validationConfigurations: - default: {} - description: ValidationConfigurations defines settings - for mutating and verifying image digests, and enforcing - image verification through signatures. - properties: - mutateDigest: - default: true - description: |- - MutateDigest enables replacement of image tags with digests. - Defaults to true. - type: boolean - required: - default: true - description: Required validates that images are - verified, i.e., have passed a signature or attestation - check. - type: boolean - verifyDigest: - default: true - description: VerifyDigest validates that images - have a digest. - type: boolean - type: object - validations: - description: Validations contain CEL expressions which - is used to apply the image validation checks. - items: - description: Validation specifies the CEL expression - which is used to apply the validation. - properties: - expression: - description: "Expression represents the expression - which will be evaluated by CEL.\nref: https://github.com/google/cel-spec\nCEL - expressions have access to the contents of the - API request/response, organized into CEL variables - as well as some other useful variables:\n\n- - 'object' - The object from the incoming request. - The value is null for DELETE requests.\n- 'oldObject' - - The existing object. The value is null for - CREATE requests.\n- 'request' - Attributes of - the API request([ref](/pkg/apis/admission/types.go#AdmissionRequest)).\n- - 'params' - Parameter resource referred to by - the policy binding being evaluated. Only populated - if the policy has a ParamKind.\n- 'namespaceObject' - - The namespace object that the incoming object - belongs to. The value is null for cluster-scoped - resources.\n- 'variables' - Map of composited - variables, from its name to its lazily evaluated - value.\n For example, a variable named 'foo' - can be accessed as 'variables.foo'.\n- 'authorizer' - - A CEL Authorizer. May be used to perform authorization - checks for the principal (user or service account) - of the request.\n See https://pkg.go.dev/k8s.io/apiserver/pkg/cel/library#Authz\n- - 'authorizer.requestResource' - A CEL ResourceCheck - constructed from the 'authorizer' and configured - with the\n request resource.\n\nThe `apiVersion`, - `kind`, `metadata.name` and `metadata.generateName` - are always accessible from the root of the\nobject. - No other metadata properties are accessible.\n\nOnly - property names of the form `[a-zA-Z_.-/][a-zA-Z0-9_.-/]*` - are accessible.\nAccessible property names are - escaped according to the following rules when - accessed in the expression:\n- '__' escapes - to '__underscores__'\n- '.' escapes to '__dot__'\n- - '-' escapes to '__dash__'\n- '/' escapes to - '__slash__'\n- Property names that exactly match - a CEL RESERVED keyword escape to '__{keyword}__'. - The keywords are:\n\t \"true\", \"false\", - \"null\", \"in\", \"as\", \"break\", \"const\", - \"continue\", \"else\", \"for\", \"function\", - \"if\",\n\t \"import\", \"let\", \"loop\", - \"package\", \"namespace\", \"return\".\nExamples:\n - \ - Expression accessing a property named \"namespace\": - {\"Expression\": \"object.__namespace__ > 0\"}\n - \ - Expression accessing a property named \"x-prop\": - {\"Expression\": \"object.x__dash__prop > 0\"}\n - \ - Expression accessing a property named \"redact__d\": - {\"Expression\": \"object.redact__underscores__d - > 0\"}\n\nEquality on arrays with list type - of 'set' or 'map' ignores element order, i.e. - [1, 2] == [2, 1].\nConcatenation on arrays with - x-kubernetes-list-type use the semantics of - the list type:\n - 'set': `X + Y` performs - a union where the array positions of all elements - in `X` are preserved and\n non-intersecting - elements in `Y` are appended, retaining their - partial order.\n - 'map': `X + Y` performs - a merge where the array positions of all keys - in `X` are preserved but the values\n are - overwritten by values in `Y` when the key sets - of `X` and `Y` intersect. Elements in `Y` with\n - \ non-intersecting keys are appended, retaining - their partial order.\nRequired." - type: string - message: - description: |- - Message represents the message displayed when validation fails. The message is required if the Expression contains - line breaks. The message must not contain line breaks. - If unset, the message is "failed rule: {Rule}". - e.g. "must be a URL with the host matching spec.host" - If the Expression contains line breaks. Message is required. - The message must not contain line breaks. - If unset, the message is "failed Expression: {Expression}". - type: string - messageExpression: - description: |- - messageExpression declares a CEL expression that evaluates to the validation failure message that is returned when this rule fails. - Since messageExpression is used as a failure message, it must evaluate to a string. - If both message and messageExpression are present on a validation, then messageExpression will be used if validation fails. - If messageExpression results in a runtime error, the runtime error is logged, and the validation failure message is produced - as if the messageExpression field were unset. If messageExpression evaluates to an empty string, a string with only spaces, or a string - that contains line breaks, then the validation failure message will also be produced as if the messageExpression field were unset, and - the fact that messageExpression produced an empty string/string with only spaces/string with line breaks will be logged. - messageExpression has access to all the same variables as the `expression` except for 'authorizer' and 'authorizer.requestResource'. - Example: - "object.x must be less than max ("+string(params.max)+")" - type: string - reason: - description: |- - Reason represents a machine-readable description of why this validation failed. - If this is the first validation in the list to fail, this reason, as well as the - corresponding HTTP response code, are used in the - HTTP response to the client. - The currently supported reasons are: "Unauthorized", "Forbidden", "Invalid", "RequestEntityTooLarge". - If not set, StatusReasonInvalid is used in the response to the client. - type: string - required: - - expression - type: object - type: array - x-kubernetes-list-type: atomic - variables: - description: |- - Variables contain definitions of variables that can be used in composition of other expressions. - Each variable is defined as a named CEL expression. - items: - description: Variable is the definition of a variable - that is used for composition. A variable is defined - as a named expression. - properties: - expression: - description: |- - Expression is the expression that will be evaluated as the value of the variable. - The CEL expression has access to the same identifiers as the CEL expressions in Validation. - type: string - name: - description: |- - Name is the name of the variable. The name must be a valid CEL identifier and unique among all variables. - The variable can be accessed in other expressions through `variables` - For example, if name is "foo", the variable will be available as `variables.foo` - type: string - required: - - expression - - name - type: object - x-kubernetes-map-type: atomic - type: array - webhookConfiguration: - description: WebhookConfiguration defines the configuration - for the webhook. - properties: - timeoutSeconds: - description: |- - TimeoutSeconds specifies the maximum time in seconds allowed to apply this policy. - After the configured time expires, the admission request may fail, or may simply ignore the policy results, - based on the failure policy. The default timeout is 10s, the value must be between 1 and 30 seconds. - format: int32 - type: integer - type: object - required: - - attestors - - validations - type: object - targets: - items: - properties: - group: - type: string - kind: - type: string - resource: - type: string - version: - type: string - required: - - kind - - resource - - version - type: object - type: array - required: - - spec - - targets - type: object - type: object - type: object - conditionStatus: - description: ConditionStatus is the shared status across all policy - types - properties: - conditions: - items: - description: Condition contains details for one aspect of the - current state of this API Resource. - properties: - lastTransitionTime: - description: |- - lastTransitionTime is the last time the condition transitioned from one status to another. - This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable. - format: date-time - type: string - message: - description: |- - message is a human readable message indicating details about the transition. - This may be an empty string. - maxLength: 32768 - type: string - observedGeneration: - description: |- - observedGeneration represents the .metadata.generation that the condition was set based upon. - For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date - with respect to the current state of the instance. - format: int64 - minimum: 0 - type: integer - reason: - description: |- - reason contains a programmatic identifier indicating the reason for the condition's last transition. - Producers of specific condition types may define expected values and meanings for this field, - and whether the values are considered a guaranteed API. - The value should be a CamelCase string. - This field may not be empty. - maxLength: 1024 - minLength: 1 - pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ - type: string - status: - description: status of the condition, one of True, False, - Unknown. - enum: - - "True" - - "False" - - Unknown - type: string - type: - description: type of condition in CamelCase or in foo.example.com/CamelCase. - maxLength: 316 - pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ - type: string - required: - - lastTransitionTime - - message - - reason - - status - - type - type: object - type: array - message: - description: |- - Message is a human readable message indicating details about the generation of ValidatingAdmissionPolicy/MutatingAdmissionPolicy - It is an empty string when ValidatingAdmissionPolicy/MutatingAdmissionPolicy is successfully generated. - type: string - ready: - description: |- - The ready of a policy is a high-level summary of where the policy is in its lifecycle. - The conditions array, the reason and message fields contain more detail about the policy's status. - type: boolean - type: object - type: object - required: - - spec - type: object - served: true - storage: true - subresources: - status: {} ---- -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - labels: - app.kubernetes.io/component: crds - app.kubernetes.io/instance: kyverno - app.kubernetes.io/managed-by: Helm - app.kubernetes.io/part-of: kyverno-crds - app.kubernetes.io/version: 3.5.1 - helm.sh/chart: crds-3.5.1 - annotations: - controller-gen.kubebuilder.io/version: v0.17.3 - name: mutatingpolicies.policies.kyverno.io -spec: - group: policies.kyverno.io - names: - categories: - - kyverno - kind: MutatingPolicy - listKind: MutatingPolicyList - plural: mutatingpolicies - shortNames: - - mpol - singular: mutatingpolicy - scope: Cluster - versions: - - additionalPrinterColumns: - - jsonPath: .metadata.creationTimestamp - name: AGE - type: date - - jsonPath: .status.conditionStatus.ready - name: READY - type: string - name: v1alpha1 - schema: - openAPIV3Schema: - properties: - apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - type: string - kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - metadata: - type: object - spec: - description: MutatingPolicySpec is the specification of the desired behavior - of the MutatingPolicy. - properties: - autogen: - description: AutogenConfiguration defines the configuration for the - generation controller. - properties: - mutatingAdmissionPolicy: - description: MutatingAdmissionPolicy specifies whether to generate - a Kubernetes MutatingAdmissionPolicy. - properties: - enabled: - description: |- - Enabled specifies whether to generate a Kubernetes MutatingAdmissionPolicy. - Optional. Defaults to "false" if not specified. - type: boolean - type: object - podControllers: - description: PodControllers specifies whether to generate a pod - controllers rules. - properties: - controllers: - items: - type: string - type: array - type: object - type: object - evaluation: - description: EvaluationConfiguration defines the configuration for - mutating policy evaluation. - properties: - admission: - description: Admission controls policy evaluation during admission. - properties: - enabled: - default: true - description: |- - Enabled controls if rules are applied during admission. - Optional. Default value is "true". - type: boolean - type: object - mutateExisting: - description: MutateExisting controls whether existing resources - are mutated. - properties: - enabled: - default: false - description: |- - Enabled enables mutation of existing resources. Default is false. - When spec.targetMatchConstraints is not defined, Kyverno mutates existing resources matched in spec.matchConstraints. - type: boolean - type: object - type: object - failurePolicy: - description: |- - failurePolicy defines how to handle failures for the admission policy. Failures can - occur from CEL expression parse errors, type check errors, runtime errors and invalid - or mis-configured policy definitions or bindings. - - failurePolicy does not define how validations that evaluate to false are handled. - - When failurePolicy is set to Fail, the validationActions field define how failures are enforced. - - Allowed values are Ignore or Fail. Defaults to Fail. - enum: - - Ignore - - Fail - type: string - matchConditions: - description: |- - MatchConditions is a list of conditions that must be met for a request to be validated. - Match conditions filter requests that have already been matched by the rules, - namespaceSelector, and objectSelector. An empty list of matchConditions matches all requests. - There are a maximum of 64 match conditions allowed. - - If a parameter object is provided, it can be accessed via the `params` handle in the same - manner as validation expressions. - - The exact matching logic is (in order): - 1. If ANY matchCondition evaluates to FALSE, the policy is skipped. - 2. If ALL matchConditions evaluate to TRUE, the policy is evaluated. - 3. If any matchCondition evaluates to an error (but none are FALSE): - - If failurePolicy=Fail, reject the request - - If failurePolicy=Ignore, the policy is skipped - items: - description: MatchCondition represents a condition which must by - fulfilled for a request to be sent to a webhook. - properties: - expression: - description: |- - Expression represents the expression which will be evaluated by CEL. Must evaluate to bool. - CEL expressions have access to the contents of the AdmissionRequest and Authorizer, organized into CEL variables: - - 'object' - The object from the incoming request. The value is null for DELETE requests. - 'oldObject' - The existing object. The value is null for CREATE requests. - 'request' - Attributes of the admission request(/pkg/apis/admission/types.go#AdmissionRequest). - 'authorizer' - A CEL Authorizer. May be used to perform authorization checks for the principal (user or service account) of the request. - See https://pkg.go.dev/k8s.io/apiserver/pkg/cel/library#Authz - 'authorizer.requestResource' - A CEL ResourceCheck constructed from the 'authorizer' and configured with the - request resource. - Documentation on CEL: https://kubernetes.io/docs/reference/using-api/cel/ - - Required. - type: string - name: - description: |- - Name is an identifier for this match condition, used for strategic merging of MatchConditions, - as well as providing an identifier for logging purposes. A good name should be descriptive of - the associated expression. - Name must be a qualified name consisting of alphanumeric characters, '-', '_' or '.', and - must start and end with an alphanumeric character (e.g. 'MyName', or 'my.name', or - '123-abc', regex used for validation is '([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9]') with an - optional DNS subdomain prefix and '/' (e.g. 'example.com/MyName') - - Required. - type: string - required: - - expression - - name - type: object - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map - matchConstraints: - description: |- - MatchConstraints specifies what resources this policy is designed to evaluate. - The AdmissionPolicy cares about a request if it matches _all_ Constraints. - Required. - properties: - excludeResourceRules: - description: |- - ExcludeResourceRules describes what operations on what resources/subresources the policy should not care about. - The exclude rules take precedence over include rules (if a resource matches both, it is excluded) - items: - description: NamedRuleWithOperations is a tuple of Operations - and Resources with ResourceNames. - properties: - apiGroups: - description: |- - APIGroups is the API groups the resources belong to. '*' is all groups. - If '*' is present, the length of the slice must be one. - Required. - items: - type: string - type: array - x-kubernetes-list-type: atomic - apiVersions: - description: |- - APIVersions is the API versions the resources belong to. '*' is all versions. - If '*' is present, the length of the slice must be one. - Required. - items: - type: string - type: array - x-kubernetes-list-type: atomic - operations: - description: |- - Operations is the operations the admission hook cares about - CREATE, UPDATE, DELETE, CONNECT or * - for all of those operations and any future admission operations that are added. - If '*' is present, the length of the slice must be one. - Required. - items: - description: OperationType specifies an operation for - a request. - type: string - type: array - x-kubernetes-list-type: atomic - resourceNames: - description: ResourceNames is an optional white list of - names that the rule applies to. An empty set means that - everything is allowed. - items: - type: string - type: array - x-kubernetes-list-type: atomic - resources: - description: |- - Resources is a list of resources this rule applies to. - - For example: - 'pods' means pods. - 'pods/log' means the log subresource of pods. - '*' means all resources, but not subresources. - 'pods/*' means all subresources of pods. - '*/scale' means all scale subresources. - '*/*' means all resources and their subresources. - - If wildcard is present, the validation rule will ensure resources do not - overlap with each other. - - Depending on the enclosing object, subresources might not be allowed. - Required. - items: - type: string - type: array - x-kubernetes-list-type: atomic - scope: - description: |- - scope specifies the scope of this rule. - Valid values are "Cluster", "Namespaced", and "*" - "Cluster" means that only cluster-scoped resources will match this rule. - Namespace API objects are cluster-scoped. - "Namespaced" means that only namespaced resources will match this rule. - "*" means that there are no scope restrictions. - Subresources match the scope of their parent resource. - Default is "*". - type: string - type: object - x-kubernetes-map-type: atomic - type: array - x-kubernetes-list-type: atomic - matchPolicy: - description: |- - matchPolicy defines how the "MatchResources" list is used to match incoming requests. - Allowed values are "Exact" or "Equivalent". - - - Exact: match a request only if it exactly matches a specified rule. - For example, if deployments can be modified via apps/v1, apps/v1beta1, and extensions/v1beta1, - but "rules" only included `apiGroups:["apps"], apiVersions:["v1"], resources: ["deployments"]`, - the admission policy does not consider requests to apps/v1beta1 or extensions/v1beta1 API groups. - - - Equivalent: match a request if modifies a resource listed in rules, even via another API group or version. - For example, if deployments can be modified via apps/v1, apps/v1beta1, and extensions/v1beta1, - and "rules" only included `apiGroups:["apps"], apiVersions:["v1"], resources: ["deployments"]`, - the admission policy **does** consider requests made to apps/v1beta1 or extensions/v1beta1 - API groups. The API server translates the request to a matched resource API if necessary. - - Defaults to "Equivalent" - type: string - namespaceSelector: - description: |- - NamespaceSelector decides whether to run the admission control policy on an object based - on whether the namespace for that object matches the selector. If the - object itself is a namespace, the matching is performed on - object.metadata.labels. If the object is another cluster scoped resource, - it never skips the policy. - - For example, to run the webhook on any objects whose namespace is not - associated with "runlevel" of "0" or "1"; you will set the selector as - follows: - "namespaceSelector": { - "matchExpressions": [ - { - "key": "runlevel", - "operator": "NotIn", - "values": [ - "0", - "1" - ] - } - ] - } - - If instead you want to only run the policy on any objects whose - namespace is associated with the "environment" of "prod" or "staging"; - you will set the selector as follows: - "namespaceSelector": { - "matchExpressions": [ - { - "key": "environment", - "operator": "In", - "values": [ - "prod", - "staging" - ] - } - ] - } - - See - https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/ - for more examples of label selectors. - - Default to the empty LabelSelector, which matches everything. - properties: - matchExpressions: - description: matchExpressions is a list of label selector - requirements. The requirements are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key that the selector - applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - objectSelector: - description: |- - ObjectSelector decides whether to run the policy based on if the - object has matching labels. objectSelector is evaluated against both - the oldObject and newObject that would be sent to the policy's expression (CEL), and - is considered to match if either object matches the selector. A null - object (oldObject in the case of create, or newObject in the case of - delete) or an object that cannot have labels (like a - DeploymentRollback or a PodProxyOptions object) is not considered to - match. - Use the object selector only if the webhook is opt-in, because end - users may skip the admission webhook by setting the labels. - Default to the empty LabelSelector, which matches everything. - properties: - matchExpressions: - description: matchExpressions is a list of label selector - requirements. The requirements are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key that the selector - applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - resourceRules: - description: |- - ResourceRules describes what operations on what resources/subresources the admission policy matches. - The policy cares about an operation if it matches _any_ Rule. - items: - description: NamedRuleWithOperations is a tuple of Operations - and Resources with ResourceNames. - properties: - apiGroups: - description: |- - APIGroups is the API groups the resources belong to. '*' is all groups. - If '*' is present, the length of the slice must be one. - Required. - items: - type: string - type: array - x-kubernetes-list-type: atomic - apiVersions: - description: |- - APIVersions is the API versions the resources belong to. '*' is all versions. - If '*' is present, the length of the slice must be one. - Required. - items: - type: string - type: array - x-kubernetes-list-type: atomic - operations: - description: |- - Operations is the operations the admission hook cares about - CREATE, UPDATE, DELETE, CONNECT or * - for all of those operations and any future admission operations that are added. - If '*' is present, the length of the slice must be one. - Required. - items: - description: OperationType specifies an operation for - a request. - type: string - type: array - x-kubernetes-list-type: atomic - resourceNames: - description: ResourceNames is an optional white list of - names that the rule applies to. An empty set means that - everything is allowed. - items: - type: string - type: array - x-kubernetes-list-type: atomic - resources: - description: |- - Resources is a list of resources this rule applies to. - - For example: - 'pods' means pods. - 'pods/log' means the log subresource of pods. - '*' means all resources, but not subresources. - 'pods/*' means all subresources of pods. - '*/scale' means all scale subresources. - '*/*' means all resources and their subresources. - - If wildcard is present, the validation rule will ensure resources do not - overlap with each other. - - Depending on the enclosing object, subresources might not be allowed. - Required. - items: - type: string - type: array - x-kubernetes-list-type: atomic - scope: - description: |- - scope specifies the scope of this rule. - Valid values are "Cluster", "Namespaced", and "*" - "Cluster" means that only cluster-scoped resources will match this rule. - Namespace API objects are cluster-scoped. - "Namespaced" means that only namespaced resources will match this rule. - "*" means that there are no scope restrictions. - Subresources match the scope of their parent resource. - Default is "*". - type: string - type: object - x-kubernetes-map-type: atomic - type: array - x-kubernetes-list-type: atomic - type: object - x-kubernetes-map-type: atomic - mutations: - description: |- - mutations contain operations to perform on matching objects. - mutations may not be empty; a minimum of one mutation is required. - mutations are evaluated in order, and are reinvoked according to - the reinvocationPolicy. - The mutations of a policy are invoked for each binding of this policy - and reinvocation of mutations occurs on a per binding basis. - items: - description: Mutation specifies the CEL expression which is used - to apply the Mutation. - properties: - applyConfiguration: - description: |- - applyConfiguration defines the desired configuration values of an object. - The configuration is applied to the admission object using - [structured merge diff](https://github.com/kubernetes-sigs/structured-merge-diff). - A CEL expression is used to create apply configuration. - properties: - expression: - description: "expression will be evaluated by CEL to create - an apply configuration.\nref: https://github.com/google/cel-spec\n\nApply - configurations are declared in CEL using object initialization. - For example, this CEL expression\nreturns an apply configuration - to set a single field:\n\n\tObject{\n\t spec: Object.spec{\n\t - \ serviceAccountName: \"example\"\n\t }\n\t}\n\nApply - configurations may not modify atomic structs, maps or - arrays due to the risk of accidental deletion of\nvalues - not included in the apply configuration.\n\nCEL expressions - have access to the object types needed to create apply - configurations:\n\n- 'Object' - CEL type of the resource - object.\n- 'Object.' - CEL type of object field - (such as 'Object.spec')\n- 'Object.....` - - CEL type of nested field (such as 'Object.spec.containers')\n\nCEL - expressions have access to the contents of the API request, - organized into CEL variables as well as some other useful - variables:\n\n- 'object' - The object from the incoming - request. The value is null for DELETE requests.\n- 'oldObject' - - The existing object. The value is null for CREATE requests.\n- - 'request' - Attributes of the API request([ref](/pkg/apis/admission/types.go#AdmissionRequest)).\n- - 'params' - Parameter resource referred to by the policy - binding being evaluated. Only populated if the policy - has a ParamKind.\n- 'namespaceObject' - The namespace - object that the incoming object belongs to. The value - is null for cluster-scoped resources.\n- 'variables' - - Map of composited variables, from its name to its lazily - evaluated value.\n For example, a variable named 'foo' - can be accessed as 'variables.foo'.\n- 'authorizer' - - A CEL Authorizer. May be used to perform authorization - checks for the principal (user or service account) of - the request.\n See https://pkg.go.dev/k8s.io/apiserver/pkg/cel/library#Authz\n- - 'authorizer.requestResource' - A CEL ResourceCheck constructed - from the 'authorizer' and configured with the\n request - resource.\n\nThe `apiVersion`, `kind`, `metadata.name` - and `metadata.generateName` are always accessible from - the root of the\nobject. No other metadata properties - are accessible.\n\nOnly property names of the form `[a-zA-Z_.-/][a-zA-Z0-9_.-/]*` - are accessible.\nRequired." - type: string - type: object - jsonPatch: - description: |- - jsonPatch defines a [JSON patch](https://jsonpatch.com/) operation to perform a mutation to the object. - A CEL expression is used to create the JSON patch. - properties: - expression: - description: "expression will be evaluated by CEL to create - a [JSON patch](https://jsonpatch.com/).\nref: https://github.com/google/cel-spec\n\nexpression - must return an array of JSONPatch values.\n\nFor example, - this CEL expression returns a JSON patch to conditionally - modify a value:\n\n\t [\n\t JSONPatch{op: \"test\", - path: \"/spec/example\", value: \"Red\"},\n\t JSONPatch{op: - \"replace\", path: \"/spec/example\", value: \"Green\"}\n\t - \ ]\n\nTo define an object for the patch value, use Object - types. For example:\n\n\t [\n\t JSONPatch{\n\t op: - \"add\",\n\t path: \"/spec/selector\",\n\t value: - Object.spec.selector{matchLabels: {\"environment\": \"test\"}}\n\t - \ }\n\t ]\n\nTo use strings containing '/' and '~' - as JSONPatch path keys, use \"jsonpatch.escapeKey\". For - example:\n\n\t [\n\t JSONPatch{\n\t op: \"add\",\n\t - \ path: \"/metadata/labels/\" + jsonpatch.escapeKey(\"example.com/environment\"),\n\t - \ value: \"test\"\n\t },\n\t ]\n\nCEL expressions - have access to the types needed to create JSON patches - and objects:\n\n- 'JSONPatch' - CEL type of JSON Patch - operations. JSONPatch has the fields 'op', 'from', 'path' - and 'value'.\n See [JSON patch](https://jsonpatch.com/) - for more details. The 'value' field may be set to any - of: string,\n integer, array, map or object. If set, - the 'path' and 'from' fields must be set to a\n [JSON - pointer](https://datatracker.ietf.org/doc/html/rfc6901/) - string, where the 'jsonpatch.escapeKey()' CEL\n function - may be used to escape path keys containing '/' and '~'.\n- - 'Object' - CEL type of the resource object.\n- 'Object.' - - CEL type of object field (such as 'Object.spec')\n- - 'Object.....` - CEL - type of nested field (such as 'Object.spec.containers')\n\nCEL - expressions have access to the contents of the API request, - organized into CEL variables as well as some other useful - variables:\n\n- 'object' - The object from the incoming - request. The value is null for DELETE requests.\n- 'oldObject' - - The existing object. The value is null for CREATE requests.\n- - 'request' - Attributes of the API request([ref](/pkg/apis/admission/types.go#AdmissionRequest)).\n- - 'params' - Parameter resource referred to by the policy - binding being evaluated. Only populated if the policy - has a ParamKind.\n- 'namespaceObject' - The namespace - object that the incoming object belongs to. The value - is null for cluster-scoped resources.\n- 'variables' - - Map of composited variables, from its name to its lazily - evaluated value.\n For example, a variable named 'foo' - can be accessed as 'variables.foo'.\n- 'authorizer' - - A CEL Authorizer. May be used to perform authorization - checks for the principal (user or service account) of - the request.\n See https://pkg.go.dev/k8s.io/apiserver/pkg/cel/library#Authz\n- - 'authorizer.requestResource' - A CEL ResourceCheck constructed - from the 'authorizer' and configured with the\n request - resource.\n\nCEL expressions have access to [Kubernetes - CEL function libraries](https://kubernetes.io/docs/reference/using-api/cel/#cel-options-language-features-and-libraries)\nas - well as:\n\n- 'jsonpatch.escapeKey' - Performs JSONPatch - key escaping. '~' and '/' are escaped as '~0' and `~1' - respectively).\n\nOnly property names of the form `[a-zA-Z_.-/][a-zA-Z0-9_.-/]*` - are accessible.\nRequired." - type: string - type: object - patchType: - description: |- - patchType indicates the patch strategy used. - Allowed values are "ApplyConfiguration" and "JSONPatch". - Required. - type: string - required: - - patchType - type: object - type: array - x-kubernetes-list-type: atomic - reinvocationPolicy: - description: |- - reinvocationPolicy indicates whether mutations may be called multiple times per MutatingAdmissionPolicyBinding - as part of a single admission evaluation. - Allowed values are "Never" and "IfNeeded". - - Never: These mutations will not be called more than once per binding in a single admission evaluation. - - IfNeeded: These mutations may be invoked more than once per binding for a single admission request and there is no guarantee of - order with respect to other admission plugins, admission webhooks, bindings of this policy and admission policies. Mutations are only - reinvoked when mutations change the object after this mutation is invoked. - Required. - type: string - targetMatchConstraints: - description: TargetMatchConstraints specifies what target mutation - resources this policy is designed to evaluate. - properties: - excludeResourceRules: - description: |- - ExcludeResourceRules describes what operations on what resources/subresources the policy should not care about. - The exclude rules take precedence over include rules (if a resource matches both, it is excluded) - items: - description: NamedRuleWithOperations is a tuple of Operations - and Resources with ResourceNames. - properties: - apiGroups: - description: |- - APIGroups is the API groups the resources belong to. '*' is all groups. - If '*' is present, the length of the slice must be one. - Required. - items: - type: string - type: array - x-kubernetes-list-type: atomic - apiVersions: - description: |- - APIVersions is the API versions the resources belong to. '*' is all versions. - If '*' is present, the length of the slice must be one. - Required. - items: - type: string - type: array - x-kubernetes-list-type: atomic - operations: - description: |- - Operations is the operations the admission hook cares about - CREATE, UPDATE, DELETE, CONNECT or * - for all of those operations and any future admission operations that are added. - If '*' is present, the length of the slice must be one. - Required. - items: - description: OperationType specifies an operation for - a request. - type: string - type: array - x-kubernetes-list-type: atomic - resourceNames: - description: ResourceNames is an optional white list of - names that the rule applies to. An empty set means that - everything is allowed. - items: - type: string - type: array - x-kubernetes-list-type: atomic - resources: - description: |- - Resources is a list of resources this rule applies to. - - For example: - 'pods' means pods. - 'pods/log' means the log subresource of pods. - '*' means all resources, but not subresources. - 'pods/*' means all subresources of pods. - '*/scale' means all scale subresources. - '*/*' means all resources and their subresources. - - If wildcard is present, the validation rule will ensure resources do not - overlap with each other. - - Depending on the enclosing object, subresources might not be allowed. - Required. - items: - type: string - type: array - x-kubernetes-list-type: atomic - scope: - description: |- - scope specifies the scope of this rule. - Valid values are "Cluster", "Namespaced", and "*" - "Cluster" means that only cluster-scoped resources will match this rule. - Namespace API objects are cluster-scoped. - "Namespaced" means that only namespaced resources will match this rule. - "*" means that there are no scope restrictions. - Subresources match the scope of their parent resource. - Default is "*". - type: string - type: object - x-kubernetes-map-type: atomic - type: array - x-kubernetes-list-type: atomic - matchPolicy: - description: |- - matchPolicy defines how the "MatchResources" list is used to match incoming requests. - Allowed values are "Exact" or "Equivalent". - - - Exact: match a request only if it exactly matches a specified rule. - For example, if deployments can be modified via apps/v1, apps/v1beta1, and extensions/v1beta1, - but "rules" only included `apiGroups:["apps"], apiVersions:["v1"], resources: ["deployments"]`, - the admission policy does not consider requests to apps/v1beta1 or extensions/v1beta1 API groups. - - - Equivalent: match a request if modifies a resource listed in rules, even via another API group or version. - For example, if deployments can be modified via apps/v1, apps/v1beta1, and extensions/v1beta1, - and "rules" only included `apiGroups:["apps"], apiVersions:["v1"], resources: ["deployments"]`, - the admission policy **does** consider requests made to apps/v1beta1 or extensions/v1beta1 - API groups. The API server translates the request to a matched resource API if necessary. - - Defaults to "Equivalent" - type: string - namespaceSelector: - description: |- - NamespaceSelector decides whether to run the admission control policy on an object based - on whether the namespace for that object matches the selector. If the - object itself is a namespace, the matching is performed on - object.metadata.labels. If the object is another cluster scoped resource, - it never skips the policy. - - For example, to run the webhook on any objects whose namespace is not - associated with "runlevel" of "0" or "1"; you will set the selector as - follows: - "namespaceSelector": { - "matchExpressions": [ - { - "key": "runlevel", - "operator": "NotIn", - "values": [ - "0", - "1" - ] - } - ] - } - - If instead you want to only run the policy on any objects whose - namespace is associated with the "environment" of "prod" or "staging"; - you will set the selector as follows: - "namespaceSelector": { - "matchExpressions": [ - { - "key": "environment", - "operator": "In", - "values": [ - "prod", - "staging" - ] - } - ] - } - - See - https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/ - for more examples of label selectors. - - Default to the empty LabelSelector, which matches everything. - properties: - matchExpressions: - description: matchExpressions is a list of label selector - requirements. The requirements are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key that the selector - applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - objectSelector: - description: |- - ObjectSelector decides whether to run the policy based on if the - object has matching labels. objectSelector is evaluated against both - the oldObject and newObject that would be sent to the policy's expression (CEL), and - is considered to match if either object matches the selector. A null - object (oldObject in the case of create, or newObject in the case of - delete) or an object that cannot have labels (like a - DeploymentRollback or a PodProxyOptions object) is not considered to - match. - Use the object selector only if the webhook is opt-in, because end - users may skip the admission webhook by setting the labels. - Default to the empty LabelSelector, which matches everything. - properties: - matchExpressions: - description: matchExpressions is a list of label selector - requirements. The requirements are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key that the selector - applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - resourceRules: - description: |- - ResourceRules describes what operations on what resources/subresources the admission policy matches. - The policy cares about an operation if it matches _any_ Rule. - items: - description: NamedRuleWithOperations is a tuple of Operations - and Resources with ResourceNames. - properties: - apiGroups: - description: |- - APIGroups is the API groups the resources belong to. '*' is all groups. - If '*' is present, the length of the slice must be one. - Required. - items: - type: string - type: array - x-kubernetes-list-type: atomic - apiVersions: - description: |- - APIVersions is the API versions the resources belong to. '*' is all versions. - If '*' is present, the length of the slice must be one. - Required. - items: - type: string - type: array - x-kubernetes-list-type: atomic - operations: - description: |- - Operations is the operations the admission hook cares about - CREATE, UPDATE, DELETE, CONNECT or * - for all of those operations and any future admission operations that are added. - If '*' is present, the length of the slice must be one. - Required. - items: - description: OperationType specifies an operation for - a request. - type: string - type: array - x-kubernetes-list-type: atomic - resourceNames: - description: ResourceNames is an optional white list of - names that the rule applies to. An empty set means that - everything is allowed. - items: - type: string - type: array - x-kubernetes-list-type: atomic - resources: - description: |- - Resources is a list of resources this rule applies to. - - For example: - 'pods' means pods. - 'pods/log' means the log subresource of pods. - '*' means all resources, but not subresources. - 'pods/*' means all subresources of pods. - '*/scale' means all scale subresources. - '*/*' means all resources and their subresources. - - If wildcard is present, the validation rule will ensure resources do not - overlap with each other. - - Depending on the enclosing object, subresources might not be allowed. - Required. - items: - type: string - type: array - x-kubernetes-list-type: atomic - scope: - description: |- - scope specifies the scope of this rule. - Valid values are "Cluster", "Namespaced", and "*" - "Cluster" means that only cluster-scoped resources will match this rule. - Namespace API objects are cluster-scoped. - "Namespaced" means that only namespaced resources will match this rule. - "*" means that there are no scope restrictions. - Subresources match the scope of their parent resource. - Default is "*". - type: string - type: object - x-kubernetes-map-type: atomic - type: array - x-kubernetes-list-type: atomic - type: object - x-kubernetes-map-type: atomic - variables: - description: |- - Variables contain definitions of variables that can be used in composition of other expressions. - Each variable is defined as a named CEL expression. - The variables defined here will be available under `variables` in other expressions of the policy - except MatchConditions because MatchConditions are evaluated before the rest of the policy. - - The expression of a variable can refer to other variables defined earlier in the list but not those after. - Thus, Variables must be sorted by the order of first appearance and acyclic. - items: - description: Variable is the definition of a variable that is used - for composition. - properties: - expression: - description: |- - Expression is the expression that will be evaluated as the value of the variable. - The CEL expression has access to the same identifiers as the CEL expressions in Validation. - type: string - name: - description: |- - Name is the name of the variable. The name must be a valid CEL identifier and unique among all variables. - The variable can be accessed in other expressions through `variables` - For example, if name is "foo", the variable will be available as `variables.foo` - type: string - required: - - expression - - name - type: object - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map - webhookConfiguration: - description: WebhookConfiguration defines the configuration for the - webhook. - properties: - timeoutSeconds: - description: |- - TimeoutSeconds specifies the maximum time in seconds allowed to apply this policy. - After the configured time expires, the admission request may fail, or may simply ignore the policy results, - based on the failure policy. The default timeout is 10s, the value must be between 1 and 30 seconds. - format: int32 - type: integer - type: object - type: object - status: - description: Status contains policy runtime data. - properties: - autogen: - properties: - configs: - additionalProperties: - properties: - spec: - description: MutatingPolicySpec is the specification of - the desired behavior of the MutatingPolicy. - properties: - autogen: - description: AutogenConfiguration defines the configuration - for the generation controller. - properties: - mutatingAdmissionPolicy: - description: MutatingAdmissionPolicy specifies whether - to generate a Kubernetes MutatingAdmissionPolicy. - properties: - enabled: - description: |- - Enabled specifies whether to generate a Kubernetes MutatingAdmissionPolicy. - Optional. Defaults to "false" if not specified. - type: boolean - type: object - podControllers: - description: PodControllers specifies whether to - generate a pod controllers rules. - properties: - controllers: - items: - type: string - type: array - type: object - type: object - evaluation: - description: EvaluationConfiguration defines the configuration - for mutating policy evaluation. - properties: - admission: - description: Admission controls policy evaluation - during admission. - properties: - enabled: - default: true - description: |- - Enabled controls if rules are applied during admission. - Optional. Default value is "true". - type: boolean - type: object - mutateExisting: - description: MutateExisting controls whether existing - resources are mutated. - properties: - enabled: - default: false - description: |- - Enabled enables mutation of existing resources. Default is false. - When spec.targetMatchConstraints is not defined, Kyverno mutates existing resources matched in spec.matchConstraints. - type: boolean - type: object - type: object - failurePolicy: - description: |- - failurePolicy defines how to handle failures for the admission policy. Failures can - occur from CEL expression parse errors, type check errors, runtime errors and invalid - or mis-configured policy definitions or bindings. - - failurePolicy does not define how validations that evaluate to false are handled. - - When failurePolicy is set to Fail, the validationActions field define how failures are enforced. - - Allowed values are Ignore or Fail. Defaults to Fail. - enum: - - Ignore - - Fail - type: string - matchConditions: - description: |- - MatchConditions is a list of conditions that must be met for a request to be validated. - Match conditions filter requests that have already been matched by the rules, - namespaceSelector, and objectSelector. An empty list of matchConditions matches all requests. - There are a maximum of 64 match conditions allowed. - - If a parameter object is provided, it can be accessed via the `params` handle in the same - manner as validation expressions. - - The exact matching logic is (in order): - 1. If ANY matchCondition evaluates to FALSE, the policy is skipped. - 2. If ALL matchConditions evaluate to TRUE, the policy is evaluated. - 3. If any matchCondition evaluates to an error (but none are FALSE): - - If failurePolicy=Fail, reject the request - - If failurePolicy=Ignore, the policy is skipped - items: - description: MatchCondition represents a condition - which must by fulfilled for a request to be sent - to a webhook. - properties: - expression: - description: |- - Expression represents the expression which will be evaluated by CEL. Must evaluate to bool. - CEL expressions have access to the contents of the AdmissionRequest and Authorizer, organized into CEL variables: - - 'object' - The object from the incoming request. The value is null for DELETE requests. - 'oldObject' - The existing object. The value is null for CREATE requests. - 'request' - Attributes of the admission request(/pkg/apis/admission/types.go#AdmissionRequest). - 'authorizer' - A CEL Authorizer. May be used to perform authorization checks for the principal (user or service account) of the request. - See https://pkg.go.dev/k8s.io/apiserver/pkg/cel/library#Authz - 'authorizer.requestResource' - A CEL ResourceCheck constructed from the 'authorizer' and configured with the - request resource. - Documentation on CEL: https://kubernetes.io/docs/reference/using-api/cel/ - - Required. - type: string - name: - description: |- - Name is an identifier for this match condition, used for strategic merging of MatchConditions, - as well as providing an identifier for logging purposes. A good name should be descriptive of - the associated expression. - Name must be a qualified name consisting of alphanumeric characters, '-', '_' or '.', and - must start and end with an alphanumeric character (e.g. 'MyName', or 'my.name', or - '123-abc', regex used for validation is '([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9]') with an - optional DNS subdomain prefix and '/' (e.g. 'example.com/MyName') - - Required. - type: string - required: - - expression - - name - type: object - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map - matchConstraints: - description: |- - MatchConstraints specifies what resources this policy is designed to evaluate. - The AdmissionPolicy cares about a request if it matches _all_ Constraints. - Required. - properties: - excludeResourceRules: - description: |- - ExcludeResourceRules describes what operations on what resources/subresources the policy should not care about. - The exclude rules take precedence over include rules (if a resource matches both, it is excluded) - items: - description: NamedRuleWithOperations is a tuple - of Operations and Resources with ResourceNames. - properties: - apiGroups: - description: |- - APIGroups is the API groups the resources belong to. '*' is all groups. - If '*' is present, the length of the slice must be one. - Required. - items: - type: string - type: array - x-kubernetes-list-type: atomic - apiVersions: - description: |- - APIVersions is the API versions the resources belong to. '*' is all versions. - If '*' is present, the length of the slice must be one. - Required. - items: - type: string - type: array - x-kubernetes-list-type: atomic - operations: - description: |- - Operations is the operations the admission hook cares about - CREATE, UPDATE, DELETE, CONNECT or * - for all of those operations and any future admission operations that are added. - If '*' is present, the length of the slice must be one. - Required. - items: - description: OperationType specifies an - operation for a request. - type: string - type: array - x-kubernetes-list-type: atomic - resourceNames: - description: ResourceNames is an optional - white list of names that the rule applies - to. An empty set means that everything - is allowed. - items: - type: string - type: array - x-kubernetes-list-type: atomic - resources: - description: |- - Resources is a list of resources this rule applies to. - - For example: - 'pods' means pods. - 'pods/log' means the log subresource of pods. - '*' means all resources, but not subresources. - 'pods/*' means all subresources of pods. - '*/scale' means all scale subresources. - '*/*' means all resources and their subresources. - - If wildcard is present, the validation rule will ensure resources do not - overlap with each other. - - Depending on the enclosing object, subresources might not be allowed. - Required. - items: - type: string - type: array - x-kubernetes-list-type: atomic - scope: - description: |- - scope specifies the scope of this rule. - Valid values are "Cluster", "Namespaced", and "*" - "Cluster" means that only cluster-scoped resources will match this rule. - Namespace API objects are cluster-scoped. - "Namespaced" means that only namespaced resources will match this rule. - "*" means that there are no scope restrictions. - Subresources match the scope of their parent resource. - Default is "*". - type: string - type: object - x-kubernetes-map-type: atomic - type: array - x-kubernetes-list-type: atomic - matchPolicy: - description: |- - matchPolicy defines how the "MatchResources" list is used to match incoming requests. - Allowed values are "Exact" or "Equivalent". - - - Exact: match a request only if it exactly matches a specified rule. - For example, if deployments can be modified via apps/v1, apps/v1beta1, and extensions/v1beta1, - but "rules" only included `apiGroups:["apps"], apiVersions:["v1"], resources: ["deployments"]`, - the admission policy does not consider requests to apps/v1beta1 or extensions/v1beta1 API groups. - - - Equivalent: match a request if modifies a resource listed in rules, even via another API group or version. - For example, if deployments can be modified via apps/v1, apps/v1beta1, and extensions/v1beta1, - and "rules" only included `apiGroups:["apps"], apiVersions:["v1"], resources: ["deployments"]`, - the admission policy **does** consider requests made to apps/v1beta1 or extensions/v1beta1 - API groups. The API server translates the request to a matched resource API if necessary. - - Defaults to "Equivalent" - type: string - namespaceSelector: - description: |- - NamespaceSelector decides whether to run the admission control policy on an object based - on whether the namespace for that object matches the selector. If the - object itself is a namespace, the matching is performed on - object.metadata.labels. If the object is another cluster scoped resource, - it never skips the policy. - - For example, to run the webhook on any objects whose namespace is not - associated with "runlevel" of "0" or "1"; you will set the selector as - follows: - "namespaceSelector": { - "matchExpressions": [ - { - "key": "runlevel", - "operator": "NotIn", - "values": [ - "0", - "1" - ] - } - ] - } - - If instead you want to only run the policy on any objects whose - namespace is associated with the "environment" of "prod" or "staging"; - you will set the selector as follows: - "namespaceSelector": { - "matchExpressions": [ - { - "key": "environment", - "operator": "In", - "values": [ - "prod", - "staging" - ] - } - ] - } - - See - https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/ - for more examples of label selectors. - - Default to the empty LabelSelector, which matches everything. - properties: - matchExpressions: - description: matchExpressions is a list of label - selector requirements. The requirements are - ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key that - the selector applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - objectSelector: - description: |- - ObjectSelector decides whether to run the policy based on if the - object has matching labels. objectSelector is evaluated against both - the oldObject and newObject that would be sent to the policy's expression (CEL), and - is considered to match if either object matches the selector. A null - object (oldObject in the case of create, or newObject in the case of - delete) or an object that cannot have labels (like a - DeploymentRollback or a PodProxyOptions object) is not considered to - match. - Use the object selector only if the webhook is opt-in, because end - users may skip the admission webhook by setting the labels. - Default to the empty LabelSelector, which matches everything. - properties: - matchExpressions: - description: matchExpressions is a list of label - selector requirements. The requirements are - ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key that - the selector applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - resourceRules: - description: |- - ResourceRules describes what operations on what resources/subresources the admission policy matches. - The policy cares about an operation if it matches _any_ Rule. - items: - description: NamedRuleWithOperations is a tuple - of Operations and Resources with ResourceNames. - properties: - apiGroups: - description: |- - APIGroups is the API groups the resources belong to. '*' is all groups. - If '*' is present, the length of the slice must be one. - Required. - items: - type: string - type: array - x-kubernetes-list-type: atomic - apiVersions: - description: |- - APIVersions is the API versions the resources belong to. '*' is all versions. - If '*' is present, the length of the slice must be one. - Required. - items: - type: string - type: array - x-kubernetes-list-type: atomic - operations: - description: |- - Operations is the operations the admission hook cares about - CREATE, UPDATE, DELETE, CONNECT or * - for all of those operations and any future admission operations that are added. - If '*' is present, the length of the slice must be one. - Required. - items: - description: OperationType specifies an - operation for a request. - type: string - type: array - x-kubernetes-list-type: atomic - resourceNames: - description: ResourceNames is an optional - white list of names that the rule applies - to. An empty set means that everything - is allowed. - items: - type: string - type: array - x-kubernetes-list-type: atomic - resources: - description: |- - Resources is a list of resources this rule applies to. - - For example: - 'pods' means pods. - 'pods/log' means the log subresource of pods. - '*' means all resources, but not subresources. - 'pods/*' means all subresources of pods. - '*/scale' means all scale subresources. - '*/*' means all resources and their subresources. - - If wildcard is present, the validation rule will ensure resources do not - overlap with each other. - - Depending on the enclosing object, subresources might not be allowed. - Required. - items: - type: string - type: array - x-kubernetes-list-type: atomic - scope: - description: |- - scope specifies the scope of this rule. - Valid values are "Cluster", "Namespaced", and "*" - "Cluster" means that only cluster-scoped resources will match this rule. - Namespace API objects are cluster-scoped. - "Namespaced" means that only namespaced resources will match this rule. - "*" means that there are no scope restrictions. - Subresources match the scope of their parent resource. - Default is "*". - type: string - type: object - x-kubernetes-map-type: atomic - type: array - x-kubernetes-list-type: atomic - type: object - x-kubernetes-map-type: atomic - mutations: - description: |- - mutations contain operations to perform on matching objects. - mutations may not be empty; a minimum of one mutation is required. - mutations are evaluated in order, and are reinvoked according to - the reinvocationPolicy. - The mutations of a policy are invoked for each binding of this policy - and reinvocation of mutations occurs on a per binding basis. - items: - description: Mutation specifies the CEL expression - which is used to apply the Mutation. - properties: - applyConfiguration: - description: |- - applyConfiguration defines the desired configuration values of an object. - The configuration is applied to the admission object using - [structured merge diff](https://github.com/kubernetes-sigs/structured-merge-diff). - A CEL expression is used to create apply configuration. - properties: - expression: - description: "expression will be evaluated - by CEL to create an apply configuration.\nref: - https://github.com/google/cel-spec\n\nApply - configurations are declared in CEL using - object initialization. For example, this - CEL expression\nreturns an apply configuration - to set a single field:\n\n\tObject{\n\t - \ spec: Object.spec{\n\t serviceAccountName: - \"example\"\n\t }\n\t}\n\nApply configurations - may not modify atomic structs, maps or arrays - due to the risk of accidental deletion of\nvalues - not included in the apply configuration.\n\nCEL - expressions have access to the object types - needed to create apply configurations:\n\n- - 'Object' - CEL type of the resource object.\n- - 'Object.' - CEL type of object - field (such as 'Object.spec')\n- 'Object.....` - - CEL type of nested field (such as 'Object.spec.containers')\n\nCEL - expressions have access to the contents - of the API request, organized into CEL variables - as well as some other useful variables:\n\n- - 'object' - The object from the incoming - request. The value is null for DELETE requests.\n- - 'oldObject' - The existing object. The value - is null for CREATE requests.\n- 'request' - - Attributes of the API request([ref](/pkg/apis/admission/types.go#AdmissionRequest)).\n- - 'params' - Parameter resource referred to - by the policy binding being evaluated. Only - populated if the policy has a ParamKind.\n- - 'namespaceObject' - The namespace object - that the incoming object belongs to. The - value is null for cluster-scoped resources.\n- - 'variables' - Map of composited variables, - from its name to its lazily evaluated value.\n - \ For example, a variable named 'foo' can - be accessed as 'variables.foo'.\n- 'authorizer' - - A CEL Authorizer. May be used to perform - authorization checks for the principal (user - or service account) of the request.\n See - https://pkg.go.dev/k8s.io/apiserver/pkg/cel/library#Authz\n- - 'authorizer.requestResource' - A CEL ResourceCheck - constructed from the 'authorizer' and configured - with the\n request resource.\n\nThe `apiVersion`, - `kind`, `metadata.name` and `metadata.generateName` - are always accessible from the root of the\nobject. - No other metadata properties are accessible.\n\nOnly - property names of the form `[a-zA-Z_.-/][a-zA-Z0-9_.-/]*` - are accessible.\nRequired." - type: string - type: object - jsonPatch: - description: |- - jsonPatch defines a [JSON patch](https://jsonpatch.com/) operation to perform a mutation to the object. - A CEL expression is used to create the JSON patch. - properties: - expression: - description: "expression will be evaluated - by CEL to create a [JSON patch](https://jsonpatch.com/).\nref: - https://github.com/google/cel-spec\n\nexpression - must return an array of JSONPatch values.\n\nFor - example, this CEL expression returns a JSON - patch to conditionally modify a value:\n\n\t - \ [\n\t JSONPatch{op: \"test\", path: - \"/spec/example\", value: \"Red\"},\n\t - \ JSONPatch{op: \"replace\", path: \"/spec/example\", - value: \"Green\"}\n\t ]\n\nTo define an - object for the patch value, use Object types. - For example:\n\n\t [\n\t JSONPatch{\n\t - \ op: \"add\",\n\t path: \"/spec/selector\",\n\t - \ value: Object.spec.selector{matchLabels: - {\"environment\": \"test\"}}\n\t }\n\t - \ ]\n\nTo use strings containing '/' and - '~' as JSONPatch path keys, use \"jsonpatch.escapeKey\". - For example:\n\n\t [\n\t JSONPatch{\n\t - \ op: \"add\",\n\t path: \"/metadata/labels/\" - + jsonpatch.escapeKey(\"example.com/environment\"),\n\t - \ value: \"test\"\n\t },\n\t ]\n\nCEL - expressions have access to the types needed - to create JSON patches and objects:\n\n- - 'JSONPatch' - CEL type of JSON Patch operations. - JSONPatch has the fields 'op', 'from', 'path' - and 'value'.\n See [JSON patch](https://jsonpatch.com/) - for more details. The 'value' field may - be set to any of: string,\n integer, array, - map or object. If set, the 'path' and 'from' - fields must be set to a\n [JSON pointer](https://datatracker.ietf.org/doc/html/rfc6901/) - string, where the 'jsonpatch.escapeKey()' - CEL\n function may be used to escape path - keys containing '/' and '~'.\n- 'Object' - - CEL type of the resource object.\n- 'Object.' - - CEL type of object field (such as 'Object.spec')\n- - 'Object.....` - - CEL type of nested field (such as 'Object.spec.containers')\n\nCEL - expressions have access to the contents - of the API request, organized into CEL variables - as well as some other useful variables:\n\n- - 'object' - The object from the incoming - request. The value is null for DELETE requests.\n- - 'oldObject' - The existing object. The value - is null for CREATE requests.\n- 'request' - - Attributes of the API request([ref](/pkg/apis/admission/types.go#AdmissionRequest)).\n- - 'params' - Parameter resource referred to - by the policy binding being evaluated. Only - populated if the policy has a ParamKind.\n- - 'namespaceObject' - The namespace object - that the incoming object belongs to. The - value is null for cluster-scoped resources.\n- - 'variables' - Map of composited variables, - from its name to its lazily evaluated value.\n - \ For example, a variable named 'foo' can - be accessed as 'variables.foo'.\n- 'authorizer' - - A CEL Authorizer. May be used to perform - authorization checks for the principal (user - or service account) of the request.\n See - https://pkg.go.dev/k8s.io/apiserver/pkg/cel/library#Authz\n- - 'authorizer.requestResource' - A CEL ResourceCheck - constructed from the 'authorizer' and configured - with the\n request resource.\n\nCEL expressions - have access to [Kubernetes CEL function - libraries](https://kubernetes.io/docs/reference/using-api/cel/#cel-options-language-features-and-libraries)\nas - well as:\n\n- 'jsonpatch.escapeKey' - Performs - JSONPatch key escaping. '~' and '/' are - escaped as '~0' and `~1' respectively).\n\nOnly - property names of the form `[a-zA-Z_.-/][a-zA-Z0-9_.-/]*` - are accessible.\nRequired." - type: string - type: object - patchType: - description: |- - patchType indicates the patch strategy used. - Allowed values are "ApplyConfiguration" and "JSONPatch". - Required. - type: string - required: - - patchType - type: object - type: array - x-kubernetes-list-type: atomic - reinvocationPolicy: - description: |- - reinvocationPolicy indicates whether mutations may be called multiple times per MutatingAdmissionPolicyBinding - as part of a single admission evaluation. - Allowed values are "Never" and "IfNeeded". - - Never: These mutations will not be called more than once per binding in a single admission evaluation. - - IfNeeded: These mutations may be invoked more than once per binding for a single admission request and there is no guarantee of - order with respect to other admission plugins, admission webhooks, bindings of this policy and admission policies. Mutations are only - reinvoked when mutations change the object after this mutation is invoked. - Required. - type: string - targetMatchConstraints: - description: TargetMatchConstraints specifies what target - mutation resources this policy is designed to evaluate. - properties: - excludeResourceRules: - description: |- - ExcludeResourceRules describes what operations on what resources/subresources the policy should not care about. - The exclude rules take precedence over include rules (if a resource matches both, it is excluded) - items: - description: NamedRuleWithOperations is a tuple - of Operations and Resources with ResourceNames. - properties: - apiGroups: - description: |- - APIGroups is the API groups the resources belong to. '*' is all groups. - If '*' is present, the length of the slice must be one. - Required. - items: - type: string - type: array - x-kubernetes-list-type: atomic - apiVersions: - description: |- - APIVersions is the API versions the resources belong to. '*' is all versions. - If '*' is present, the length of the slice must be one. - Required. - items: - type: string - type: array - x-kubernetes-list-type: atomic - operations: - description: |- - Operations is the operations the admission hook cares about - CREATE, UPDATE, DELETE, CONNECT or * - for all of those operations and any future admission operations that are added. - If '*' is present, the length of the slice must be one. - Required. - items: - description: OperationType specifies an - operation for a request. - type: string - type: array - x-kubernetes-list-type: atomic - resourceNames: - description: ResourceNames is an optional - white list of names that the rule applies - to. An empty set means that everything - is allowed. - items: - type: string - type: array - x-kubernetes-list-type: atomic - resources: - description: |- - Resources is a list of resources this rule applies to. - - For example: - 'pods' means pods. - 'pods/log' means the log subresource of pods. - '*' means all resources, but not subresources. - 'pods/*' means all subresources of pods. - '*/scale' means all scale subresources. - '*/*' means all resources and their subresources. - - If wildcard is present, the validation rule will ensure resources do not - overlap with each other. - - Depending on the enclosing object, subresources might not be allowed. - Required. - items: - type: string - type: array - x-kubernetes-list-type: atomic - scope: - description: |- - scope specifies the scope of this rule. - Valid values are "Cluster", "Namespaced", and "*" - "Cluster" means that only cluster-scoped resources will match this rule. - Namespace API objects are cluster-scoped. - "Namespaced" means that only namespaced resources will match this rule. - "*" means that there are no scope restrictions. - Subresources match the scope of their parent resource. - Default is "*". - type: string - type: object - x-kubernetes-map-type: atomic - type: array - x-kubernetes-list-type: atomic - matchPolicy: - description: |- - matchPolicy defines how the "MatchResources" list is used to match incoming requests. - Allowed values are "Exact" or "Equivalent". - - - Exact: match a request only if it exactly matches a specified rule. - For example, if deployments can be modified via apps/v1, apps/v1beta1, and extensions/v1beta1, - but "rules" only included `apiGroups:["apps"], apiVersions:["v1"], resources: ["deployments"]`, - the admission policy does not consider requests to apps/v1beta1 or extensions/v1beta1 API groups. - - - Equivalent: match a request if modifies a resource listed in rules, even via another API group or version. - For example, if deployments can be modified via apps/v1, apps/v1beta1, and extensions/v1beta1, - and "rules" only included `apiGroups:["apps"], apiVersions:["v1"], resources: ["deployments"]`, - the admission policy **does** consider requests made to apps/v1beta1 or extensions/v1beta1 - API groups. The API server translates the request to a matched resource API if necessary. - - Defaults to "Equivalent" - type: string - namespaceSelector: - description: |- - NamespaceSelector decides whether to run the admission control policy on an object based - on whether the namespace for that object matches the selector. If the - object itself is a namespace, the matching is performed on - object.metadata.labels. If the object is another cluster scoped resource, - it never skips the policy. - - For example, to run the webhook on any objects whose namespace is not - associated with "runlevel" of "0" or "1"; you will set the selector as - follows: - "namespaceSelector": { - "matchExpressions": [ - { - "key": "runlevel", - "operator": "NotIn", - "values": [ - "0", - "1" - ] - } - ] - } - - If instead you want to only run the policy on any objects whose - namespace is associated with the "environment" of "prod" or "staging"; - you will set the selector as follows: - "namespaceSelector": { - "matchExpressions": [ - { - "key": "environment", - "operator": "In", - "values": [ - "prod", - "staging" - ] - } - ] - } - - See - https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/ - for more examples of label selectors. - - Default to the empty LabelSelector, which matches everything. - properties: - matchExpressions: - description: matchExpressions is a list of label - selector requirements. The requirements are - ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key that - the selector applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - objectSelector: - description: |- - ObjectSelector decides whether to run the policy based on if the - object has matching labels. objectSelector is evaluated against both - the oldObject and newObject that would be sent to the policy's expression (CEL), and - is considered to match if either object matches the selector. A null - object (oldObject in the case of create, or newObject in the case of - delete) or an object that cannot have labels (like a - DeploymentRollback or a PodProxyOptions object) is not considered to - match. - Use the object selector only if the webhook is opt-in, because end - users may skip the admission webhook by setting the labels. - Default to the empty LabelSelector, which matches everything. - properties: - matchExpressions: - description: matchExpressions is a list of label - selector requirements. The requirements are - ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key that - the selector applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - resourceRules: - description: |- - ResourceRules describes what operations on what resources/subresources the admission policy matches. - The policy cares about an operation if it matches _any_ Rule. - items: - description: NamedRuleWithOperations is a tuple - of Operations and Resources with ResourceNames. - properties: - apiGroups: - description: |- - APIGroups is the API groups the resources belong to. '*' is all groups. - If '*' is present, the length of the slice must be one. - Required. - items: - type: string - type: array - x-kubernetes-list-type: atomic - apiVersions: - description: |- - APIVersions is the API versions the resources belong to. '*' is all versions. - If '*' is present, the length of the slice must be one. - Required. - items: - type: string - type: array - x-kubernetes-list-type: atomic - operations: - description: |- - Operations is the operations the admission hook cares about - CREATE, UPDATE, DELETE, CONNECT or * - for all of those operations and any future admission operations that are added. - If '*' is present, the length of the slice must be one. - Required. - items: - description: OperationType specifies an - operation for a request. - type: string - type: array - x-kubernetes-list-type: atomic - resourceNames: - description: ResourceNames is an optional - white list of names that the rule applies - to. An empty set means that everything - is allowed. - items: - type: string - type: array - x-kubernetes-list-type: atomic - resources: - description: |- - Resources is a list of resources this rule applies to. - - For example: - 'pods' means pods. - 'pods/log' means the log subresource of pods. - '*' means all resources, but not subresources. - 'pods/*' means all subresources of pods. - '*/scale' means all scale subresources. - '*/*' means all resources and their subresources. - - If wildcard is present, the validation rule will ensure resources do not - overlap with each other. - - Depending on the enclosing object, subresources might not be allowed. - Required. - items: - type: string - type: array - x-kubernetes-list-type: atomic - scope: - description: |- - scope specifies the scope of this rule. - Valid values are "Cluster", "Namespaced", and "*" - "Cluster" means that only cluster-scoped resources will match this rule. - Namespace API objects are cluster-scoped. - "Namespaced" means that only namespaced resources will match this rule. - "*" means that there are no scope restrictions. - Subresources match the scope of their parent resource. - Default is "*". - type: string - type: object - x-kubernetes-map-type: atomic - type: array - x-kubernetes-list-type: atomic - type: object - x-kubernetes-map-type: atomic - variables: - description: |- - Variables contain definitions of variables that can be used in composition of other expressions. - Each variable is defined as a named CEL expression. - The variables defined here will be available under `variables` in other expressions of the policy - except MatchConditions because MatchConditions are evaluated before the rest of the policy. - - The expression of a variable can refer to other variables defined earlier in the list but not those after. - Thus, Variables must be sorted by the order of first appearance and acyclic. - items: - description: Variable is the definition of a variable - that is used for composition. - properties: - expression: - description: |- - Expression is the expression that will be evaluated as the value of the variable. - The CEL expression has access to the same identifiers as the CEL expressions in Validation. - type: string - name: - description: |- - Name is the name of the variable. The name must be a valid CEL identifier and unique among all variables. - The variable can be accessed in other expressions through `variables` - For example, if name is "foo", the variable will be available as `variables.foo` - type: string - required: - - expression - - name - type: object - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map - webhookConfiguration: - description: WebhookConfiguration defines the configuration - for the webhook. - properties: - timeoutSeconds: - description: |- - TimeoutSeconds specifies the maximum time in seconds allowed to apply this policy. - After the configured time expires, the admission request may fail, or may simply ignore the policy results, - based on the failure policy. The default timeout is 10s, the value must be between 1 and 30 seconds. - format: int32 - type: integer - type: object - type: object - targets: - items: - properties: - group: - type: string - kind: - type: string - resource: - type: string - version: - type: string - required: - - kind - - resource - - version - type: object - type: array - required: - - spec - - targets - type: object - type: object - type: object - conditionStatus: - description: ConditionStatus is the shared status across all policy - types - properties: - conditions: - items: - description: Condition contains details for one aspect of the - current state of this API Resource. - properties: - lastTransitionTime: - description: |- - lastTransitionTime is the last time the condition transitioned from one status to another. - This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable. - format: date-time - type: string - message: - description: |- - message is a human readable message indicating details about the transition. - This may be an empty string. - maxLength: 32768 - type: string - observedGeneration: - description: |- - observedGeneration represents the .metadata.generation that the condition was set based upon. - For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date - with respect to the current state of the instance. - format: int64 - minimum: 0 - type: integer - reason: - description: |- - reason contains a programmatic identifier indicating the reason for the condition's last transition. - Producers of specific condition types may define expected values and meanings for this field, - and whether the values are considered a guaranteed API. - The value should be a CamelCase string. - This field may not be empty. - maxLength: 1024 - minLength: 1 - pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ - type: string - status: - description: status of the condition, one of True, False, - Unknown. - enum: - - "True" - - "False" - - Unknown - type: string - type: - description: type of condition in CamelCase or in foo.example.com/CamelCase. - maxLength: 316 - pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ - type: string - required: - - lastTransitionTime - - message - - reason - - status - - type - type: object - type: array - message: - description: |- - Message is a human readable message indicating details about the generation of ValidatingAdmissionPolicy/MutatingAdmissionPolicy - It is an empty string when ValidatingAdmissionPolicy/MutatingAdmissionPolicy is successfully generated. - type: string - ready: - description: |- - The ready of a policy is a high-level summary of where the policy is in its lifecycle. - The conditions array, the reason and message fields contain more detail about the policy's status. - type: boolean - type: object - generated: - description: Generated indicates whether a MutatingAdmissionPolicy - is generated from the policy or not - type: boolean - type: object - required: - - spec - type: object - served: true - storage: true - subresources: - status: {} ---- -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - labels: - app.kubernetes.io/component: crds - app.kubernetes.io/instance: kyverno - app.kubernetes.io/managed-by: Helm - app.kubernetes.io/part-of: kyverno-crds - app.kubernetes.io/version: 3.5.1 - helm.sh/chart: crds-3.5.1 - annotations: - controller-gen.kubebuilder.io/version: v0.17.3 - name: policyexceptions.policies.kyverno.io -spec: - group: policies.kyverno.io - names: - kind: PolicyException - listKind: PolicyExceptionList - plural: policyexceptions - singular: policyexception - scope: Namespaced - versions: - - name: v1alpha1 - schema: - openAPIV3Schema: - description: PolicyException declares resources to be excluded from specified - policies. - properties: - apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - type: string - kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - metadata: - type: object - spec: - description: Spec declares policy exception behaviors. - properties: - matchConditions: - description: MatchConditions is a list of CEL expressions that must - be met for a resource to be excluded. - items: - description: MatchCondition represents a condition which must by - fulfilled for a request to be sent to a webhook. - properties: - expression: - description: |- - Expression represents the expression which will be evaluated by CEL. Must evaluate to bool. - CEL expressions have access to the contents of the AdmissionRequest and Authorizer, organized into CEL variables: - - 'object' - The object from the incoming request. The value is null for DELETE requests. - 'oldObject' - The existing object. The value is null for CREATE requests. - 'request' - Attributes of the admission request(/pkg/apis/admission/types.go#AdmissionRequest). - 'authorizer' - A CEL Authorizer. May be used to perform authorization checks for the principal (user or service account) of the request. - See https://pkg.go.dev/k8s.io/apiserver/pkg/cel/library#Authz - 'authorizer.requestResource' - A CEL ResourceCheck constructed from the 'authorizer' and configured with the - request resource. - Documentation on CEL: https://kubernetes.io/docs/reference/using-api/cel/ - - Required. - type: string - name: - description: |- - Name is an identifier for this match condition, used for strategic merging of MatchConditions, - as well as providing an identifier for logging purposes. A good name should be descriptive of - the associated expression. - Name must be a qualified name consisting of alphanumeric characters, '-', '_' or '.', and - must start and end with an alphanumeric character (e.g. 'MyName', or 'my.name', or - '123-abc', regex used for validation is '([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9]') with an - optional DNS subdomain prefix and '/' (e.g. 'example.com/MyName') - - Required. - type: string - required: - - expression - - name - type: object - type: array - policyRefs: - description: PolicyRefs identifies the policies to which the exception - is applied. - items: - properties: - kind: - description: Kind is the kind of the policy - type: string - name: - description: Name is the name of the policy - type: string - required: - - kind - - name - type: object - type: array - required: - - policyRefs - type: object - required: - - spec - type: object - served: true - storage: true ---- -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - labels: - app.kubernetes.io/component: crds - app.kubernetes.io/instance: kyverno - app.kubernetes.io/managed-by: Helm - app.kubernetes.io/part-of: kyverno-crds - app.kubernetes.io/version: 3.5.1 - helm.sh/chart: crds-3.5.1 - annotations: - controller-gen.kubebuilder.io/version: v0.17.3 - name: validatingpolicies.policies.kyverno.io -spec: - group: policies.kyverno.io - names: - categories: - - kyverno - kind: ValidatingPolicy - listKind: ValidatingPolicyList - plural: validatingpolicies - shortNames: - - vpol - singular: validatingpolicy - scope: Cluster - versions: - - additionalPrinterColumns: - - jsonPath: .metadata.creationTimestamp - name: AGE - type: date - - jsonPath: .status.conditionStatus.ready - name: READY - type: string - name: v1alpha1 - schema: - openAPIV3Schema: - properties: - apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - type: string - kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - metadata: - type: object - spec: - description: ValidatingPolicySpec is the specification of the desired - behavior of the ValidatingPolicy. - properties: - auditAnnotations: - description: |- - auditAnnotations contains CEL expressions which are used to produce audit - annotations for the audit event of the API request. - validations and auditAnnotations may not both be empty; a least one of validations or auditAnnotations is - required. - items: - description: AuditAnnotation describes how to produce an audit annotation - for an API request. - properties: - key: - description: |- - key specifies the audit annotation key. The audit annotation keys of - a ValidatingAdmissionPolicy must be unique. The key must be a qualified - name ([A-Za-z0-9][-A-Za-z0-9_.]*) no more than 63 bytes in length. - - The key is combined with the resource name of the - ValidatingAdmissionPolicy to construct an audit annotation key: - "{ValidatingAdmissionPolicy name}/{key}". - - If an admission webhook uses the same resource name as this ValidatingAdmissionPolicy - and the same audit annotation key, the annotation key will be identical. - In this case, the first annotation written with the key will be included - in the audit event and all subsequent annotations with the same key - will be discarded. - - Required. - type: string - valueExpression: - description: |- - valueExpression represents the expression which is evaluated by CEL to - produce an audit annotation value. The expression must evaluate to either - a string or null value. If the expression evaluates to a string, the - audit annotation is included with the string value. If the expression - evaluates to null or empty string the audit annotation will be omitted. - The valueExpression may be no longer than 5kb in length. - If the result of the valueExpression is more than 10kb in length, it - will be truncated to 10kb. - - If multiple ValidatingAdmissionPolicyBinding resources match an - API request, then the valueExpression will be evaluated for - each binding. All unique values produced by the valueExpressions - will be joined together in a comma-separated list. - - Required. - type: string - required: - - key - - valueExpression - type: object - type: array - x-kubernetes-list-type: atomic - autogen: - description: AutogenConfiguration defines the configuration for the - generation controller. - properties: - podControllers: - description: PodControllers specifies whether to generate a pod - controllers rules. - properties: - controllers: - items: - type: string - type: array - type: object - validatingAdmissionPolicy: - description: ValidatingAdmissionPolicy specifies whether to generate - a Kubernetes ValidatingAdmissionPolicy. - properties: - enabled: - description: |- - Enabled specifies whether to generate a Kubernetes ValidatingAdmissionPolicy. - Optional. Defaults to "false" if not specified. - type: boolean - type: object - type: object - evaluation: - description: EvaluationConfiguration defines the configuration for - the policy evaluation. - properties: - admission: - description: Admission controls policy evaluation during admission. - properties: - enabled: - default: true - description: |- - Enabled controls if rules are applied during admission. - Optional. Default value is "true". - type: boolean - type: object - background: - description: Background controls policy evaluation during background - scan. - properties: - enabled: - default: true - description: |- - Enabled controls if rules are applied to existing resources during a background scan. - Optional. Default value is "true". The value must be set to "false" if the policy rule - uses variables that are only available in the admission review request (e.g. user name). - type: boolean - type: object - mode: - description: |- - Mode is the mode of policy evaluation. - Allowed values are "Kubernetes" or "JSON". - Optional. Default value is "Kubernetes". - type: string - type: object - failurePolicy: - description: |- - failurePolicy defines how to handle failures for the admission policy. Failures can - occur from CEL expression parse errors, type check errors, runtime errors and invalid - or mis-configured policy definitions or bindings. - - failurePolicy does not define how validations that evaluate to false are handled. - - When failurePolicy is set to Fail, the validationActions field define how failures are enforced. - - Allowed values are Ignore or Fail. Defaults to Fail. - enum: - - Ignore - - Fail - type: string - matchConditions: - description: |- - MatchConditions is a list of conditions that must be met for a request to be validated. - Match conditions filter requests that have already been matched by the rules, - namespaceSelector, and objectSelector. An empty list of matchConditions matches all requests. - There are a maximum of 64 match conditions allowed. - - If a parameter object is provided, it can be accessed via the `params` handle in the same - manner as validation expressions. - - The exact matching logic is (in order): - 1. If ANY matchCondition evaluates to FALSE, the policy is skipped. - 2. If ALL matchConditions evaluate to TRUE, the policy is evaluated. - 3. If any matchCondition evaluates to an error (but none are FALSE): - - If failurePolicy=Fail, reject the request - - If failurePolicy=Ignore, the policy is skipped - items: - description: MatchCondition represents a condition which must by - fulfilled for a request to be sent to a webhook. - properties: - expression: - description: |- - Expression represents the expression which will be evaluated by CEL. Must evaluate to bool. - CEL expressions have access to the contents of the AdmissionRequest and Authorizer, organized into CEL variables: - - 'object' - The object from the incoming request. The value is null for DELETE requests. - 'oldObject' - The existing object. The value is null for CREATE requests. - 'request' - Attributes of the admission request(/pkg/apis/admission/types.go#AdmissionRequest). - 'authorizer' - A CEL Authorizer. May be used to perform authorization checks for the principal (user or service account) of the request. - See https://pkg.go.dev/k8s.io/apiserver/pkg/cel/library#Authz - 'authorizer.requestResource' - A CEL ResourceCheck constructed from the 'authorizer' and configured with the - request resource. - Documentation on CEL: https://kubernetes.io/docs/reference/using-api/cel/ - - Required. - type: string - name: - description: |- - Name is an identifier for this match condition, used for strategic merging of MatchConditions, - as well as providing an identifier for logging purposes. A good name should be descriptive of - the associated expression. - Name must be a qualified name consisting of alphanumeric characters, '-', '_' or '.', and - must start and end with an alphanumeric character (e.g. 'MyName', or 'my.name', or - '123-abc', regex used for validation is '([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9]') with an - optional DNS subdomain prefix and '/' (e.g. 'example.com/MyName') - - Required. - type: string - required: - - expression - - name - type: object - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map - matchConstraints: - description: |- - MatchConstraints specifies what resources this policy is designed to validate. - The AdmissionPolicy cares about a request if it matches _all_ Constraints. - Required. - properties: - excludeResourceRules: - description: |- - ExcludeResourceRules describes what operations on what resources/subresources the ValidatingAdmissionPolicy should not care about. - The exclude rules take precedence over include rules (if a resource matches both, it is excluded) - items: - description: NamedRuleWithOperations is a tuple of Operations - and Resources with ResourceNames. - properties: - apiGroups: - description: |- - APIGroups is the API groups the resources belong to. '*' is all groups. - If '*' is present, the length of the slice must be one. - Required. - items: - type: string - type: array - x-kubernetes-list-type: atomic - apiVersions: - description: |- - APIVersions is the API versions the resources belong to. '*' is all versions. - If '*' is present, the length of the slice must be one. - Required. - items: - type: string - type: array - x-kubernetes-list-type: atomic - operations: - description: |- - Operations is the operations the admission hook cares about - CREATE, UPDATE, DELETE, CONNECT or * - for all of those operations and any future admission operations that are added. - If '*' is present, the length of the slice must be one. - Required. - items: - description: OperationType specifies an operation for - a request. - type: string - type: array - x-kubernetes-list-type: atomic - resourceNames: - description: ResourceNames is an optional white list of - names that the rule applies to. An empty set means that - everything is allowed. - items: - type: string - type: array - x-kubernetes-list-type: atomic - resources: - description: |- - Resources is a list of resources this rule applies to. - - For example: - 'pods' means pods. - 'pods/log' means the log subresource of pods. - '*' means all resources, but not subresources. - 'pods/*' means all subresources of pods. - '*/scale' means all scale subresources. - '*/*' means all resources and their subresources. - - If wildcard is present, the validation rule will ensure resources do not - overlap with each other. - - Depending on the enclosing object, subresources might not be allowed. - Required. - items: - type: string - type: array - x-kubernetes-list-type: atomic - scope: - description: |- - scope specifies the scope of this rule. - Valid values are "Cluster", "Namespaced", and "*" - "Cluster" means that only cluster-scoped resources will match this rule. - Namespace API objects are cluster-scoped. - "Namespaced" means that only namespaced resources will match this rule. - "*" means that there are no scope restrictions. - Subresources match the scope of their parent resource. - Default is "*". - type: string - type: object - x-kubernetes-map-type: atomic - type: array - x-kubernetes-list-type: atomic - matchPolicy: - description: |- - matchPolicy defines how the "MatchResources" list is used to match incoming requests. - Allowed values are "Exact" or "Equivalent". - - - Exact: match a request only if it exactly matches a specified rule. - For example, if deployments can be modified via apps/v1, apps/v1beta1, and extensions/v1beta1, - but "rules" only included `apiGroups:["apps"], apiVersions:["v1"], resources: ["deployments"]`, - a request to apps/v1beta1 or extensions/v1beta1 would not be sent to the ValidatingAdmissionPolicy. - - - Equivalent: match a request if modifies a resource listed in rules, even via another API group or version. - For example, if deployments can be modified via apps/v1, apps/v1beta1, and extensions/v1beta1, - and "rules" only included `apiGroups:["apps"], apiVersions:["v1"], resources: ["deployments"]`, - a request to apps/v1beta1 or extensions/v1beta1 would be converted to apps/v1 and sent to the ValidatingAdmissionPolicy. - - Defaults to "Equivalent" - type: string - namespaceSelector: - description: |- - NamespaceSelector decides whether to run the admission control policy on an object based - on whether the namespace for that object matches the selector. If the - object itself is a namespace, the matching is performed on - object.metadata.labels. If the object is another cluster scoped resource, - it never skips the policy. - - For example, to run the webhook on any objects whose namespace is not - associated with "runlevel" of "0" or "1"; you will set the selector as - follows: - "namespaceSelector": { - "matchExpressions": [ - { - "key": "runlevel", - "operator": "NotIn", - "values": [ - "0", - "1" - ] - } - ] - } - - If instead you want to only run the policy on any objects whose - namespace is associated with the "environment" of "prod" or "staging"; - you will set the selector as follows: - "namespaceSelector": { - "matchExpressions": [ - { - "key": "environment", - "operator": "In", - "values": [ - "prod", - "staging" - ] - } - ] - } - - See - https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/ - for more examples of label selectors. - - Default to the empty LabelSelector, which matches everything. - properties: - matchExpressions: - description: matchExpressions is a list of label selector - requirements. The requirements are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key that the selector - applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - objectSelector: - description: |- - ObjectSelector decides whether to run the validation based on if the - object has matching labels. objectSelector is evaluated against both - the oldObject and newObject that would be sent to the cel validation, and - is considered to match if either object matches the selector. A null - object (oldObject in the case of create, or newObject in the case of - delete) or an object that cannot have labels (like a - DeploymentRollback or a PodProxyOptions object) is not considered to - match. - Use the object selector only if the webhook is opt-in, because end - users may skip the admission webhook by setting the labels. - Default to the empty LabelSelector, which matches everything. - properties: - matchExpressions: - description: matchExpressions is a list of label selector - requirements. The requirements are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key that the selector - applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - resourceRules: - description: |- - ResourceRules describes what operations on what resources/subresources the ValidatingAdmissionPolicy matches. - The policy cares about an operation if it matches _any_ Rule. - items: - description: NamedRuleWithOperations is a tuple of Operations - and Resources with ResourceNames. - properties: - apiGroups: - description: |- - APIGroups is the API groups the resources belong to. '*' is all groups. - If '*' is present, the length of the slice must be one. - Required. - items: - type: string - type: array - x-kubernetes-list-type: atomic - apiVersions: - description: |- - APIVersions is the API versions the resources belong to. '*' is all versions. - If '*' is present, the length of the slice must be one. - Required. - items: - type: string - type: array - x-kubernetes-list-type: atomic - operations: - description: |- - Operations is the operations the admission hook cares about - CREATE, UPDATE, DELETE, CONNECT or * - for all of those operations and any future admission operations that are added. - If '*' is present, the length of the slice must be one. - Required. - items: - description: OperationType specifies an operation for - a request. - type: string - type: array - x-kubernetes-list-type: atomic - resourceNames: - description: ResourceNames is an optional white list of - names that the rule applies to. An empty set means that - everything is allowed. - items: - type: string - type: array - x-kubernetes-list-type: atomic - resources: - description: |- - Resources is a list of resources this rule applies to. - - For example: - 'pods' means pods. - 'pods/log' means the log subresource of pods. - '*' means all resources, but not subresources. - 'pods/*' means all subresources of pods. - '*/scale' means all scale subresources. - '*/*' means all resources and their subresources. - - If wildcard is present, the validation rule will ensure resources do not - overlap with each other. - - Depending on the enclosing object, subresources might not be allowed. - Required. - items: - type: string - type: array - x-kubernetes-list-type: atomic - scope: - description: |- - scope specifies the scope of this rule. - Valid values are "Cluster", "Namespaced", and "*" - "Cluster" means that only cluster-scoped resources will match this rule. - Namespace API objects are cluster-scoped. - "Namespaced" means that only namespaced resources will match this rule. - "*" means that there are no scope restrictions. - Subresources match the scope of their parent resource. - Default is "*". - type: string - type: object - x-kubernetes-map-type: atomic - type: array - x-kubernetes-list-type: atomic - type: object - x-kubernetes-map-type: atomic - validationActions: - description: |- - ValidationAction specifies the action to be taken when the matched resource violates the policy. - Required. - items: - description: ValidationAction specifies a policy enforcement action. - enum: - - Deny - - Audit - - Warn - type: string - type: array - x-kubernetes-list-type: set - validations: - description: |- - Validations contain CEL expressions which is used to apply the validation. - Validations and AuditAnnotations may not both be empty; a minimum of one Validations or AuditAnnotations is - required. - items: - description: Validation specifies the CEL expression which is used - to apply the validation. - properties: - expression: - description: "Expression represents the expression which will - be evaluated by CEL.\nref: https://github.com/google/cel-spec\nCEL - expressions have access to the contents of the API request/response, - organized into CEL variables as well as some other useful - variables:\n\n- 'object' - The object from the incoming request. - The value is null for DELETE requests.\n- 'oldObject' - The - existing object. The value is null for CREATE requests.\n- - 'request' - Attributes of the API request([ref](/pkg/apis/admission/types.go#AdmissionRequest)).\n- - 'params' - Parameter resource referred to by the policy binding - being evaluated. Only populated if the policy has a ParamKind.\n- - 'namespaceObject' - The namespace object that the incoming - object belongs to. The value is null for cluster-scoped resources.\n- - 'variables' - Map of composited variables, from its name to - its lazily evaluated value.\n For example, a variable named - 'foo' can be accessed as 'variables.foo'.\n- 'authorizer' - - A CEL Authorizer. May be used to perform authorization checks - for the principal (user or service account) of the request.\n - \ See https://pkg.go.dev/k8s.io/apiserver/pkg/cel/library#Authz\n- - 'authorizer.requestResource' - A CEL ResourceCheck constructed - from the 'authorizer' and configured with the\n request resource.\n\nThe - `apiVersion`, `kind`, `metadata.name` and `metadata.generateName` - are always accessible from the root of the\nobject. No other - metadata properties are accessible.\n\nOnly property names - of the form `[a-zA-Z_.-/][a-zA-Z0-9_.-/]*` are accessible.\nAccessible - property names are escaped according to the following rules - when accessed in the expression:\n- '__' escapes to '__underscores__'\n- - '.' escapes to '__dot__'\n- '-' escapes to '__dash__'\n- '/' - escapes to '__slash__'\n- Property names that exactly match - a CEL RESERVED keyword escape to '__{keyword}__'. The keywords - are:\n\t \"true\", \"false\", \"null\", \"in\", \"as\", \"break\", - \"const\", \"continue\", \"else\", \"for\", \"function\", - \"if\",\n\t \"import\", \"let\", \"loop\", \"package\", \"namespace\", - \"return\".\nExamples:\n - Expression accessing a property - named \"namespace\": {\"Expression\": \"object.__namespace__ - > 0\"}\n - Expression accessing a property named \"x-prop\": - {\"Expression\": \"object.x__dash__prop > 0\"}\n - Expression - accessing a property named \"redact__d\": {\"Expression\": - \"object.redact__underscores__d > 0\"}\n\nEquality on arrays - with list type of 'set' or 'map' ignores element order, i.e. - [1, 2] == [2, 1].\nConcatenation on arrays with x-kubernetes-list-type - use the semantics of the list type:\n - 'set': `X + Y` performs - a union where the array positions of all elements in `X` are - preserved and\n non-intersecting elements in `Y` are appended, - retaining their partial order.\n - 'map': `X + Y` performs - a merge where the array positions of all keys in `X` are preserved - but the values\n are overwritten by values in `Y` when - the key sets of `X` and `Y` intersect. Elements in `Y` with\n - \ non-intersecting keys are appended, retaining their partial - order.\nRequired." - type: string - message: - description: |- - Message represents the message displayed when validation fails. The message is required if the Expression contains - line breaks. The message must not contain line breaks. - If unset, the message is "failed rule: {Rule}". - e.g. "must be a URL with the host matching spec.host" - If the Expression contains line breaks. Message is required. - The message must not contain line breaks. - If unset, the message is "failed Expression: {Expression}". - type: string - messageExpression: - description: |- - messageExpression declares a CEL expression that evaluates to the validation failure message that is returned when this rule fails. - Since messageExpression is used as a failure message, it must evaluate to a string. - If both message and messageExpression are present on a validation, then messageExpression will be used if validation fails. - If messageExpression results in a runtime error, the runtime error is logged, and the validation failure message is produced - as if the messageExpression field were unset. If messageExpression evaluates to an empty string, a string with only spaces, or a string - that contains line breaks, then the validation failure message will also be produced as if the messageExpression field were unset, and - the fact that messageExpression produced an empty string/string with only spaces/string with line breaks will be logged. - messageExpression has access to all the same variables as the `expression` except for 'authorizer' and 'authorizer.requestResource'. - Example: - "object.x must be less than max ("+string(params.max)+")" - type: string - reason: - description: |- - Reason represents a machine-readable description of why this validation failed. - If this is the first validation in the list to fail, this reason, as well as the - corresponding HTTP response code, are used in the - HTTP response to the client. - The currently supported reasons are: "Unauthorized", "Forbidden", "Invalid", "RequestEntityTooLarge". - If not set, StatusReasonInvalid is used in the response to the client. - type: string - required: - - expression - type: object - type: array - x-kubernetes-list-type: atomic - variables: - description: |- - Variables contain definitions of variables that can be used in composition of other expressions. - Each variable is defined as a named CEL expression. - The variables defined here will be available under `variables` in other expressions of the policy - except MatchConditions because MatchConditions are evaluated before the rest of the policy. - - The expression of a variable can refer to other variables defined earlier in the list but not those after. - Thus, Variables must be sorted by the order of first appearance and acyclic. - items: - description: Variable is the definition of a variable that is used - for composition. A variable is defined as a named expression. - properties: - expression: - description: |- - Expression is the expression that will be evaluated as the value of the variable. - The CEL expression has access to the same identifiers as the CEL expressions in Validation. - type: string - name: - description: |- - Name is the name of the variable. The name must be a valid CEL identifier and unique among all variables. - The variable can be accessed in other expressions through `variables` - For example, if name is "foo", the variable will be available as `variables.foo` - type: string - required: - - expression - - name - type: object - x-kubernetes-map-type: atomic - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map - webhookConfiguration: - description: WebhookConfiguration defines the configuration for the - webhook. - properties: - timeoutSeconds: - description: |- - TimeoutSeconds specifies the maximum time in seconds allowed to apply this policy. - After the configured time expires, the admission request may fail, or may simply ignore the policy results, - based on the failure policy. The default timeout is 10s, the value must be between 1 and 30 seconds. - format: int32 - type: integer - type: object - type: object - status: - description: Status contains policy runtime data. - properties: - autogen: - properties: - configs: - additionalProperties: - properties: - spec: - description: ValidatingPolicySpec is the specification of - the desired behavior of the ValidatingPolicy. - properties: - auditAnnotations: - description: |- - auditAnnotations contains CEL expressions which are used to produce audit - annotations for the audit event of the API request. - validations and auditAnnotations may not both be empty; a least one of validations or auditAnnotations is - required. - items: - description: AuditAnnotation describes how to produce - an audit annotation for an API request. - properties: - key: - description: |- - key specifies the audit annotation key. The audit annotation keys of - a ValidatingAdmissionPolicy must be unique. The key must be a qualified - name ([A-Za-z0-9][-A-Za-z0-9_.]*) no more than 63 bytes in length. - - The key is combined with the resource name of the - ValidatingAdmissionPolicy to construct an audit annotation key: - "{ValidatingAdmissionPolicy name}/{key}". - - If an admission webhook uses the same resource name as this ValidatingAdmissionPolicy - and the same audit annotation key, the annotation key will be identical. - In this case, the first annotation written with the key will be included - in the audit event and all subsequent annotations with the same key - will be discarded. - - Required. - type: string - valueExpression: - description: |- - valueExpression represents the expression which is evaluated by CEL to - produce an audit annotation value. The expression must evaluate to either - a string or null value. If the expression evaluates to a string, the - audit annotation is included with the string value. If the expression - evaluates to null or empty string the audit annotation will be omitted. - The valueExpression may be no longer than 5kb in length. - If the result of the valueExpression is more than 10kb in length, it - will be truncated to 10kb. - - If multiple ValidatingAdmissionPolicyBinding resources match an - API request, then the valueExpression will be evaluated for - each binding. All unique values produced by the valueExpressions - will be joined together in a comma-separated list. - - Required. - type: string - required: - - key - - valueExpression - type: object - type: array - x-kubernetes-list-type: atomic - autogen: - description: AutogenConfiguration defines the configuration - for the generation controller. - properties: - podControllers: - description: PodControllers specifies whether to - generate a pod controllers rules. - properties: - controllers: - items: - type: string - type: array - type: object - validatingAdmissionPolicy: - description: ValidatingAdmissionPolicy specifies - whether to generate a Kubernetes ValidatingAdmissionPolicy. - properties: - enabled: - description: |- - Enabled specifies whether to generate a Kubernetes ValidatingAdmissionPolicy. - Optional. Defaults to "false" if not specified. - type: boolean - type: object - type: object - evaluation: - description: EvaluationConfiguration defines the configuration - for the policy evaluation. - properties: - admission: - description: Admission controls policy evaluation - during admission. - properties: - enabled: - default: true - description: |- - Enabled controls if rules are applied during admission. - Optional. Default value is "true". - type: boolean - type: object - background: - description: Background controls policy evaluation - during background scan. - properties: - enabled: - default: true - description: |- - Enabled controls if rules are applied to existing resources during a background scan. - Optional. Default value is "true". The value must be set to "false" if the policy rule - uses variables that are only available in the admission review request (e.g. user name). - type: boolean - type: object - mode: - description: |- - Mode is the mode of policy evaluation. - Allowed values are "Kubernetes" or "JSON". - Optional. Default value is "Kubernetes". - type: string - type: object - failurePolicy: - description: |- - failurePolicy defines how to handle failures for the admission policy. Failures can - occur from CEL expression parse errors, type check errors, runtime errors and invalid - or mis-configured policy definitions or bindings. - - failurePolicy does not define how validations that evaluate to false are handled. - - When failurePolicy is set to Fail, the validationActions field define how failures are enforced. - - Allowed values are Ignore or Fail. Defaults to Fail. - enum: - - Ignore - - Fail - type: string - matchConditions: - description: |- - MatchConditions is a list of conditions that must be met for a request to be validated. - Match conditions filter requests that have already been matched by the rules, - namespaceSelector, and objectSelector. An empty list of matchConditions matches all requests. - There are a maximum of 64 match conditions allowed. - - If a parameter object is provided, it can be accessed via the `params` handle in the same - manner as validation expressions. - - The exact matching logic is (in order): - 1. If ANY matchCondition evaluates to FALSE, the policy is skipped. - 2. If ALL matchConditions evaluate to TRUE, the policy is evaluated. - 3. If any matchCondition evaluates to an error (but none are FALSE): - - If failurePolicy=Fail, reject the request - - If failurePolicy=Ignore, the policy is skipped - items: - description: MatchCondition represents a condition - which must by fulfilled for a request to be sent - to a webhook. - properties: - expression: - description: |- - Expression represents the expression which will be evaluated by CEL. Must evaluate to bool. - CEL expressions have access to the contents of the AdmissionRequest and Authorizer, organized into CEL variables: - - 'object' - The object from the incoming request. The value is null for DELETE requests. - 'oldObject' - The existing object. The value is null for CREATE requests. - 'request' - Attributes of the admission request(/pkg/apis/admission/types.go#AdmissionRequest). - 'authorizer' - A CEL Authorizer. May be used to perform authorization checks for the principal (user or service account) of the request. - See https://pkg.go.dev/k8s.io/apiserver/pkg/cel/library#Authz - 'authorizer.requestResource' - A CEL ResourceCheck constructed from the 'authorizer' and configured with the - request resource. - Documentation on CEL: https://kubernetes.io/docs/reference/using-api/cel/ - - Required. - type: string - name: - description: |- - Name is an identifier for this match condition, used for strategic merging of MatchConditions, - as well as providing an identifier for logging purposes. A good name should be descriptive of - the associated expression. - Name must be a qualified name consisting of alphanumeric characters, '-', '_' or '.', and - must start and end with an alphanumeric character (e.g. 'MyName', or 'my.name', or - '123-abc', regex used for validation is '([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9]') with an - optional DNS subdomain prefix and '/' (e.g. 'example.com/MyName') - - Required. - type: string - required: - - expression - - name - type: object - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map - matchConstraints: - description: |- - MatchConstraints specifies what resources this policy is designed to validate. - The AdmissionPolicy cares about a request if it matches _all_ Constraints. - Required. - properties: - excludeResourceRules: - description: |- - ExcludeResourceRules describes what operations on what resources/subresources the ValidatingAdmissionPolicy should not care about. - The exclude rules take precedence over include rules (if a resource matches both, it is excluded) - items: - description: NamedRuleWithOperations is a tuple - of Operations and Resources with ResourceNames. - properties: - apiGroups: - description: |- - APIGroups is the API groups the resources belong to. '*' is all groups. - If '*' is present, the length of the slice must be one. - Required. - items: - type: string - type: array - x-kubernetes-list-type: atomic - apiVersions: - description: |- - APIVersions is the API versions the resources belong to. '*' is all versions. - If '*' is present, the length of the slice must be one. - Required. - items: - type: string - type: array - x-kubernetes-list-type: atomic - operations: - description: |- - Operations is the operations the admission hook cares about - CREATE, UPDATE, DELETE, CONNECT or * - for all of those operations and any future admission operations that are added. - If '*' is present, the length of the slice must be one. - Required. - items: - description: OperationType specifies an - operation for a request. - type: string - type: array - x-kubernetes-list-type: atomic - resourceNames: - description: ResourceNames is an optional - white list of names that the rule applies - to. An empty set means that everything - is allowed. - items: - type: string - type: array - x-kubernetes-list-type: atomic - resources: - description: |- - Resources is a list of resources this rule applies to. - - For example: - 'pods' means pods. - 'pods/log' means the log subresource of pods. - '*' means all resources, but not subresources. - 'pods/*' means all subresources of pods. - '*/scale' means all scale subresources. - '*/*' means all resources and their subresources. - - If wildcard is present, the validation rule will ensure resources do not - overlap with each other. - - Depending on the enclosing object, subresources might not be allowed. - Required. - items: - type: string - type: array - x-kubernetes-list-type: atomic - scope: - description: |- - scope specifies the scope of this rule. - Valid values are "Cluster", "Namespaced", and "*" - "Cluster" means that only cluster-scoped resources will match this rule. - Namespace API objects are cluster-scoped. - "Namespaced" means that only namespaced resources will match this rule. - "*" means that there are no scope restrictions. - Subresources match the scope of their parent resource. - Default is "*". - type: string - type: object - x-kubernetes-map-type: atomic - type: array - x-kubernetes-list-type: atomic - matchPolicy: - description: |- - matchPolicy defines how the "MatchResources" list is used to match incoming requests. - Allowed values are "Exact" or "Equivalent". - - - Exact: match a request only if it exactly matches a specified rule. - For example, if deployments can be modified via apps/v1, apps/v1beta1, and extensions/v1beta1, - but "rules" only included `apiGroups:["apps"], apiVersions:["v1"], resources: ["deployments"]`, - a request to apps/v1beta1 or extensions/v1beta1 would not be sent to the ValidatingAdmissionPolicy. - - - Equivalent: match a request if modifies a resource listed in rules, even via another API group or version. - For example, if deployments can be modified via apps/v1, apps/v1beta1, and extensions/v1beta1, - and "rules" only included `apiGroups:["apps"], apiVersions:["v1"], resources: ["deployments"]`, - a request to apps/v1beta1 or extensions/v1beta1 would be converted to apps/v1 and sent to the ValidatingAdmissionPolicy. - - Defaults to "Equivalent" - type: string - namespaceSelector: - description: |- - NamespaceSelector decides whether to run the admission control policy on an object based - on whether the namespace for that object matches the selector. If the - object itself is a namespace, the matching is performed on - object.metadata.labels. If the object is another cluster scoped resource, - it never skips the policy. - - For example, to run the webhook on any objects whose namespace is not - associated with "runlevel" of "0" or "1"; you will set the selector as - follows: - "namespaceSelector": { - "matchExpressions": [ - { - "key": "runlevel", - "operator": "NotIn", - "values": [ - "0", - "1" - ] - } - ] - } - - If instead you want to only run the policy on any objects whose - namespace is associated with the "environment" of "prod" or "staging"; - you will set the selector as follows: - "namespaceSelector": { - "matchExpressions": [ - { - "key": "environment", - "operator": "In", - "values": [ - "prod", - "staging" - ] - } - ] - } - - See - https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/ - for more examples of label selectors. - - Default to the empty LabelSelector, which matches everything. - properties: - matchExpressions: - description: matchExpressions is a list of label - selector requirements. The requirements are - ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key that - the selector applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - objectSelector: - description: |- - ObjectSelector decides whether to run the validation based on if the - object has matching labels. objectSelector is evaluated against both - the oldObject and newObject that would be sent to the cel validation, and - is considered to match if either object matches the selector. A null - object (oldObject in the case of create, or newObject in the case of - delete) or an object that cannot have labels (like a - DeploymentRollback or a PodProxyOptions object) is not considered to - match. - Use the object selector only if the webhook is opt-in, because end - users may skip the admission webhook by setting the labels. - Default to the empty LabelSelector, which matches everything. - properties: - matchExpressions: - description: matchExpressions is a list of label - selector requirements. The requirements are - ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key that - the selector applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - resourceRules: - description: |- - ResourceRules describes what operations on what resources/subresources the ValidatingAdmissionPolicy matches. - The policy cares about an operation if it matches _any_ Rule. - items: - description: NamedRuleWithOperations is a tuple - of Operations and Resources with ResourceNames. - properties: - apiGroups: - description: |- - APIGroups is the API groups the resources belong to. '*' is all groups. - If '*' is present, the length of the slice must be one. - Required. - items: - type: string - type: array - x-kubernetes-list-type: atomic - apiVersions: - description: |- - APIVersions is the API versions the resources belong to. '*' is all versions. - If '*' is present, the length of the slice must be one. - Required. - items: - type: string - type: array - x-kubernetes-list-type: atomic - operations: - description: |- - Operations is the operations the admission hook cares about - CREATE, UPDATE, DELETE, CONNECT or * - for all of those operations and any future admission operations that are added. - If '*' is present, the length of the slice must be one. - Required. - items: - description: OperationType specifies an - operation for a request. - type: string - type: array - x-kubernetes-list-type: atomic - resourceNames: - description: ResourceNames is an optional - white list of names that the rule applies - to. An empty set means that everything - is allowed. - items: - type: string - type: array - x-kubernetes-list-type: atomic - resources: - description: |- - Resources is a list of resources this rule applies to. - - For example: - 'pods' means pods. - 'pods/log' means the log subresource of pods. - '*' means all resources, but not subresources. - 'pods/*' means all subresources of pods. - '*/scale' means all scale subresources. - '*/*' means all resources and their subresources. - - If wildcard is present, the validation rule will ensure resources do not - overlap with each other. - - Depending on the enclosing object, subresources might not be allowed. - Required. - items: - type: string - type: array - x-kubernetes-list-type: atomic - scope: - description: |- - scope specifies the scope of this rule. - Valid values are "Cluster", "Namespaced", and "*" - "Cluster" means that only cluster-scoped resources will match this rule. - Namespace API objects are cluster-scoped. - "Namespaced" means that only namespaced resources will match this rule. - "*" means that there are no scope restrictions. - Subresources match the scope of their parent resource. - Default is "*". - type: string - type: object - x-kubernetes-map-type: atomic - type: array - x-kubernetes-list-type: atomic - type: object - x-kubernetes-map-type: atomic - validationActions: - description: |- - ValidationAction specifies the action to be taken when the matched resource violates the policy. - Required. - items: - description: ValidationAction specifies a policy enforcement - action. - enum: - - Deny - - Audit - - Warn - type: string - type: array - x-kubernetes-list-type: set - validations: - description: |- - Validations contain CEL expressions which is used to apply the validation. - Validations and AuditAnnotations may not both be empty; a minimum of one Validations or AuditAnnotations is - required. - items: - description: Validation specifies the CEL expression - which is used to apply the validation. - properties: - expression: - description: "Expression represents the expression - which will be evaluated by CEL.\nref: https://github.com/google/cel-spec\nCEL - expressions have access to the contents of the - API request/response, organized into CEL variables - as well as some other useful variables:\n\n- - 'object' - The object from the incoming request. - The value is null for DELETE requests.\n- 'oldObject' - - The existing object. The value is null for - CREATE requests.\n- 'request' - Attributes of - the API request([ref](/pkg/apis/admission/types.go#AdmissionRequest)).\n- - 'params' - Parameter resource referred to by - the policy binding being evaluated. Only populated - if the policy has a ParamKind.\n- 'namespaceObject' - - The namespace object that the incoming object - belongs to. The value is null for cluster-scoped - resources.\n- 'variables' - Map of composited - variables, from its name to its lazily evaluated - value.\n For example, a variable named 'foo' - can be accessed as 'variables.foo'.\n- 'authorizer' - - A CEL Authorizer. May be used to perform authorization - checks for the principal (user or service account) - of the request.\n See https://pkg.go.dev/k8s.io/apiserver/pkg/cel/library#Authz\n- - 'authorizer.requestResource' - A CEL ResourceCheck - constructed from the 'authorizer' and configured - with the\n request resource.\n\nThe `apiVersion`, - `kind`, `metadata.name` and `metadata.generateName` - are always accessible from the root of the\nobject. - No other metadata properties are accessible.\n\nOnly - property names of the form `[a-zA-Z_.-/][a-zA-Z0-9_.-/]*` - are accessible.\nAccessible property names are - escaped according to the following rules when - accessed in the expression:\n- '__' escapes - to '__underscores__'\n- '.' escapes to '__dot__'\n- - '-' escapes to '__dash__'\n- '/' escapes to - '__slash__'\n- Property names that exactly match - a CEL RESERVED keyword escape to '__{keyword}__'. - The keywords are:\n\t \"true\", \"false\", - \"null\", \"in\", \"as\", \"break\", \"const\", - \"continue\", \"else\", \"for\", \"function\", - \"if\",\n\t \"import\", \"let\", \"loop\", - \"package\", \"namespace\", \"return\".\nExamples:\n - \ - Expression accessing a property named \"namespace\": - {\"Expression\": \"object.__namespace__ > 0\"}\n - \ - Expression accessing a property named \"x-prop\": - {\"Expression\": \"object.x__dash__prop > 0\"}\n - \ - Expression accessing a property named \"redact__d\": - {\"Expression\": \"object.redact__underscores__d - > 0\"}\n\nEquality on arrays with list type - of 'set' or 'map' ignores element order, i.e. - [1, 2] == [2, 1].\nConcatenation on arrays with - x-kubernetes-list-type use the semantics of - the list type:\n - 'set': `X + Y` performs - a union where the array positions of all elements - in `X` are preserved and\n non-intersecting - elements in `Y` are appended, retaining their - partial order.\n - 'map': `X + Y` performs - a merge where the array positions of all keys - in `X` are preserved but the values\n are - overwritten by values in `Y` when the key sets - of `X` and `Y` intersect. Elements in `Y` with\n - \ non-intersecting keys are appended, retaining - their partial order.\nRequired." - type: string - message: - description: |- - Message represents the message displayed when validation fails. The message is required if the Expression contains - line breaks. The message must not contain line breaks. - If unset, the message is "failed rule: {Rule}". - e.g. "must be a URL with the host matching spec.host" - If the Expression contains line breaks. Message is required. - The message must not contain line breaks. - If unset, the message is "failed Expression: {Expression}". - type: string - messageExpression: - description: |- - messageExpression declares a CEL expression that evaluates to the validation failure message that is returned when this rule fails. - Since messageExpression is used as a failure message, it must evaluate to a string. - If both message and messageExpression are present on a validation, then messageExpression will be used if validation fails. - If messageExpression results in a runtime error, the runtime error is logged, and the validation failure message is produced - as if the messageExpression field were unset. If messageExpression evaluates to an empty string, a string with only spaces, or a string - that contains line breaks, then the validation failure message will also be produced as if the messageExpression field were unset, and - the fact that messageExpression produced an empty string/string with only spaces/string with line breaks will be logged. - messageExpression has access to all the same variables as the `expression` except for 'authorizer' and 'authorizer.requestResource'. - Example: - "object.x must be less than max ("+string(params.max)+")" - type: string - reason: - description: |- - Reason represents a machine-readable description of why this validation failed. - If this is the first validation in the list to fail, this reason, as well as the - corresponding HTTP response code, are used in the - HTTP response to the client. - The currently supported reasons are: "Unauthorized", "Forbidden", "Invalid", "RequestEntityTooLarge". - If not set, StatusReasonInvalid is used in the response to the client. - type: string - required: - - expression - type: object - type: array - x-kubernetes-list-type: atomic - variables: - description: |- - Variables contain definitions of variables that can be used in composition of other expressions. - Each variable is defined as a named CEL expression. - The variables defined here will be available under `variables` in other expressions of the policy - except MatchConditions because MatchConditions are evaluated before the rest of the policy. - - The expression of a variable can refer to other variables defined earlier in the list but not those after. - Thus, Variables must be sorted by the order of first appearance and acyclic. - items: - description: Variable is the definition of a variable - that is used for composition. A variable is defined - as a named expression. - properties: - expression: - description: |- - Expression is the expression that will be evaluated as the value of the variable. - The CEL expression has access to the same identifiers as the CEL expressions in Validation. - type: string - name: - description: |- - Name is the name of the variable. The name must be a valid CEL identifier and unique among all variables. - The variable can be accessed in other expressions through `variables` - For example, if name is "foo", the variable will be available as `variables.foo` - type: string - required: - - expression - - name - type: object - x-kubernetes-map-type: atomic - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map - webhookConfiguration: - description: WebhookConfiguration defines the configuration - for the webhook. - properties: - timeoutSeconds: - description: |- - TimeoutSeconds specifies the maximum time in seconds allowed to apply this policy. - After the configured time expires, the admission request may fail, or may simply ignore the policy results, - based on the failure policy. The default timeout is 10s, the value must be between 1 and 30 seconds. - format: int32 - type: integer - type: object - type: object - targets: - items: - properties: - group: - type: string - kind: - type: string - resource: - type: string - version: - type: string - required: - - kind - - resource - - version - type: object - type: array - required: - - spec - - targets - type: object - type: object - type: object - conditionStatus: - description: ConditionStatus is the shared status across all policy - types - properties: - conditions: - items: - description: Condition contains details for one aspect of the - current state of this API Resource. - properties: - lastTransitionTime: - description: |- - lastTransitionTime is the last time the condition transitioned from one status to another. - This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable. - format: date-time - type: string - message: - description: |- - message is a human readable message indicating details about the transition. - This may be an empty string. - maxLength: 32768 - type: string - observedGeneration: - description: |- - observedGeneration represents the .metadata.generation that the condition was set based upon. - For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date - with respect to the current state of the instance. - format: int64 - minimum: 0 - type: integer - reason: - description: |- - reason contains a programmatic identifier indicating the reason for the condition's last transition. - Producers of specific condition types may define expected values and meanings for this field, - and whether the values are considered a guaranteed API. - The value should be a CamelCase string. - This field may not be empty. - maxLength: 1024 - minLength: 1 - pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ - type: string - status: - description: status of the condition, one of True, False, - Unknown. - enum: - - "True" - - "False" - - Unknown - type: string - type: - description: type of condition in CamelCase or in foo.example.com/CamelCase. - maxLength: 316 - pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ - type: string - required: - - lastTransitionTime - - message - - reason - - status - - type - type: object - type: array - message: - description: |- - Message is a human readable message indicating details about the generation of ValidatingAdmissionPolicy/MutatingAdmissionPolicy - It is an empty string when ValidatingAdmissionPolicy/MutatingAdmissionPolicy is successfully generated. - type: string - ready: - description: |- - The ready of a policy is a high-level summary of where the policy is in its lifecycle. - The conditions array, the reason and message fields contain more detail about the policy's status. - type: boolean - type: object - generated: - description: Generated indicates whether a ValidatingAdmissionPolicy/MutatingAdmissionPolicy - is generated from the policy or not - type: boolean - type: object - required: - - spec - type: object - served: true - storage: true - subresources: - status: {} ---- -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - labels: - app.kubernetes.io/component: crds - app.kubernetes.io/instance: kyverno - app.kubernetes.io/managed-by: Helm - app.kubernetes.io/part-of: kyverno-crds - app.kubernetes.io/version: 3.5.1 - helm.sh/chart: crds-3.5.1 - annotations: - controller-gen.kubebuilder.io/version: v0.17.3 - name: clusterephemeralreports.reports.kyverno.io -spec: - group: reports.kyverno.io - names: - categories: - - kyverno - kind: ClusterEphemeralReport - listKind: ClusterEphemeralReportList - plural: clusterephemeralreports - shortNames: - - cephr - singular: clusterephemeralreport - scope: Cluster - versions: - - additionalPrinterColumns: - - jsonPath: .metadata.labels['audit\.kyverno\.io/source'] - name: Source - type: string - - jsonPath: .metadata.labels['audit\.kyverno\.io/resource\.group'] - name: Group - type: string - - jsonPath: .metadata.labels['audit\.kyverno\.io/resource\.kind'] - name: Kind - type: string - - jsonPath: .metadata.annotations['audit\.kyverno\.io/resource\.name'] - name: Owner - type: string - - jsonPath: .spec.summary.pass - name: Pass - type: integer - - jsonPath: .spec.summary.fail - name: Fail - type: integer - - jsonPath: .spec.summary.warn - name: Warn - type: integer - - jsonPath: .spec.summary.error - name: Error - type: integer - - jsonPath: .spec.summary.skip - name: Skip - type: integer - - jsonPath: .metadata.creationTimestamp - name: Age - type: date - - jsonPath: .metadata.labels['audit\.kyverno\.io/resource\.uid'] - name: Uid - type: string - - jsonPath: .metadata.labels['audit\.kyverno\.io/resource\.hash'] - name: Hash - priority: 1 - type: string - name: v1 - schema: - openAPIV3Schema: - description: ClusterEphemeralReport is the Schema for the ClusterEphemeralReports - API - properties: - apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - type: string - kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - metadata: - type: object - spec: - properties: - owner: - description: Owner is a reference to the report owner (e.g. a Deployment, - Namespace, or Node) - properties: - apiVersion: - description: API version of the referent. - type: string - blockOwnerDeletion: - description: |- - If true, AND if the owner has the "foregroundDeletion" finalizer, then - the owner cannot be deleted from the key-value store until this - reference is removed. - See https://kubernetes.io/docs/concepts/architecture/garbage-collection/#foreground-deletion - for how the garbage collector interacts with this field and enforces the foreground deletion. - Defaults to false. - To set this field, a user needs "delete" permission of the owner, - otherwise 422 (Unprocessable Entity) will be returned. - type: boolean - controller: - description: If true, this reference points to the managing controller. - type: boolean - kind: - description: |- - Kind of the referent. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - name: - description: |- - Name of the referent. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names#names - type: string - uid: - description: |- - UID of the referent. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names#uids - type: string - required: - - apiVersion - - kind - - name - - uid - type: object - x-kubernetes-map-type: atomic - results: - description: PolicyReportResult provides result details - items: - description: ReportResult provides the result for an individual - policy - properties: - category: - description: Category indicates policy category - type: string - message: - description: Description is a short user friendly message for - the policy rule - type: string - policy: - description: Policy is the name or identifier of the policy - type: string - properties: - additionalProperties: - type: string - description: Properties provides additional information for - the policy rule - type: object - resourceSelector: - description: |- - ResourceSelector is an optional label selector for checked Kubernetes resources. - For example, a policy result may apply to all pods that match a label. - Either a Subject or a ResourceSelector can be specified. If neither are provided, the - result is assumed to be for the policy report scope. - properties: - matchExpressions: - description: matchExpressions is a list of label selector - requirements. The requirements are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key that the selector - applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - resources: - description: Subjects is an optional reference to the checked - Kubernetes resources - items: - description: ObjectReference contains enough information to - let you inspect or modify the referred object. - properties: - apiVersion: - description: API version of the referent. - type: string - fieldPath: - description: |- - If referring to a piece of an object instead of an entire object, this string - should contain a valid JSON/Go field access statement, such as desiredState.manifest.containers[2]. - For example, if the object reference is to a container within a pod, this would take on a value like: - "spec.containers{name}" (where "name" refers to the name of the container that triggered - the event) or if no container name is specified "spec.containers[2]" (container with - index 2 in this pod). This syntax is chosen only to have some well-defined way of - referencing a part of an object. - type: string - kind: - description: |- - Kind of the referent. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - name: - description: |- - Name of the referent. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - type: string - namespace: - description: |- - Namespace of the referent. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/ - type: string - resourceVersion: - description: |- - Specific resourceVersion to which this reference is made, if any. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#concurrency-control-and-consistency - type: string - uid: - description: |- - UID of the referent. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#uids - type: string - type: object - x-kubernetes-map-type: atomic - type: array - result: - description: Result indicates the outcome of the policy rule - execution - enum: - - pass - - fail - - warn - - error - - skip - type: string - rule: - description: Rule is the name or identifier of the rule within - the policy - type: string - scored: - description: Scored indicates if this result is scored - type: boolean - severity: - description: Severity indicates policy check result criticality - enum: - - critical - - high - - low - - medium - - info - type: string - source: - description: |- - Source is an identifier for the policy engine that manages this report - If the Source is specified at this level, it will override the Source - field set at the Report level - type: string - timestamp: - description: Timestamp indicates the time the result was found - properties: - nanos: - description: |- - Non-negative fractions of a second at nanosecond resolution. Negative - second values with fractions must still have non-negative nanos values - that count forward in time. Must be from 0 to 999,999,999 - inclusive. This field may be limited in precision depending on context. - format: int32 - type: integer - seconds: - description: |- - Represents seconds of UTC time since Unix epoch - 1970-01-01T00:00:00Z. Must be from 0001-01-01T00:00:00Z to - 9999-12-31T23:59:59Z inclusive. - format: int64 - type: integer - required: - - nanos - - seconds - type: object - required: - - policy - type: object - type: array - summary: - description: PolicyReportSummary provides a summary of results - properties: - error: - description: Error provides the count of policies that could not - be evaluated - type: integer - fail: - description: Fail provides the count of policies whose requirements - were not met - type: integer - pass: - description: Pass provides the count of policies whose requirements - were met - type: integer - skip: - description: Skip indicates the count of policies that were not - selected for evaluation - type: integer - warn: - description: Warn provides the count of non-scored policies whose - requirements were not met - type: integer - type: object - required: - - owner - type: object - required: - - spec - type: object - served: true - storage: true - subresources: {} ---- -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - labels: - app.kubernetes.io/component: crds - app.kubernetes.io/instance: kyverno - app.kubernetes.io/managed-by: Helm - app.kubernetes.io/part-of: kyverno-crds - app.kubernetes.io/version: 3.5.1 - helm.sh/chart: crds-3.5.1 - annotations: - controller-gen.kubebuilder.io/version: v0.17.3 - name: ephemeralreports.reports.kyverno.io -spec: - group: reports.kyverno.io - names: - categories: - - kyverno - kind: EphemeralReport - listKind: EphemeralReportList - plural: ephemeralreports - shortNames: - - ephr - singular: ephemeralreport - scope: Namespaced - versions: - - additionalPrinterColumns: - - jsonPath: .metadata.labels['audit\.kyverno\.io/source'] - name: Source - type: string - - jsonPath: .metadata.labels['audit\.kyverno\.io/resource\.group'] - name: Group - type: string - - jsonPath: .metadata.labels['audit\.kyverno\.io/resource\.kind'] - name: Kind - type: string - - jsonPath: .metadata.annotations['audit\.kyverno\.io/resource\.name'] - name: Owner - type: string - - jsonPath: .spec.summary.pass - name: Pass - type: integer - - jsonPath: .spec.summary.fail - name: Fail - type: integer - - jsonPath: .spec.summary.warn - name: Warn - type: integer - - jsonPath: .spec.summary.error - name: Error - type: integer - - jsonPath: .spec.summary.skip - name: Skip - type: integer - - jsonPath: .metadata.creationTimestamp - name: Age - type: date - - jsonPath: .metadata.labels['audit\.kyverno\.io/resource\.uid'] - name: Uid - priority: 1 - type: string - - jsonPath: .metadata.labels['audit\.kyverno\.io/resource\.hash'] - name: Hash - priority: 1 - type: string - name: v1 - schema: - openAPIV3Schema: - description: EphemeralReport is the Schema for the EphemeralReports API - properties: - apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - type: string - kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - metadata: - type: object - spec: - properties: - owner: - description: Owner is a reference to the report owner (e.g. a Deployment, - Namespace, or Node) - properties: - apiVersion: - description: API version of the referent. - type: string - blockOwnerDeletion: - description: |- - If true, AND if the owner has the "foregroundDeletion" finalizer, then - the owner cannot be deleted from the key-value store until this - reference is removed. - See https://kubernetes.io/docs/concepts/architecture/garbage-collection/#foreground-deletion - for how the garbage collector interacts with this field and enforces the foreground deletion. - Defaults to false. - To set this field, a user needs "delete" permission of the owner, - otherwise 422 (Unprocessable Entity) will be returned. - type: boolean - controller: - description: If true, this reference points to the managing controller. - type: boolean - kind: - description: |- - Kind of the referent. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - name: - description: |- - Name of the referent. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names#names - type: string - uid: - description: |- - UID of the referent. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names#uids - type: string - required: - - apiVersion - - kind - - name - - uid - type: object - x-kubernetes-map-type: atomic - results: - description: PolicyReportResult provides result details - items: - description: ReportResult provides the result for an individual - policy - properties: - category: - description: Category indicates policy category - type: string - message: - description: Description is a short user friendly message for - the policy rule - type: string - policy: - description: Policy is the name or identifier of the policy - type: string - properties: - additionalProperties: - type: string - description: Properties provides additional information for - the policy rule - type: object - resourceSelector: - description: |- - ResourceSelector is an optional label selector for checked Kubernetes resources. - For example, a policy result may apply to all pods that match a label. - Either a Subject or a ResourceSelector can be specified. If neither are provided, the - result is assumed to be for the policy report scope. - properties: - matchExpressions: - description: matchExpressions is a list of label selector - requirements. The requirements are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key that the selector - applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - resources: - description: Subjects is an optional reference to the checked - Kubernetes resources - items: - description: ObjectReference contains enough information to - let you inspect or modify the referred object. - properties: - apiVersion: - description: API version of the referent. - type: string - fieldPath: - description: |- - If referring to a piece of an object instead of an entire object, this string - should contain a valid JSON/Go field access statement, such as desiredState.manifest.containers[2]. - For example, if the object reference is to a container within a pod, this would take on a value like: - "spec.containers{name}" (where "name" refers to the name of the container that triggered - the event) or if no container name is specified "spec.containers[2]" (container with - index 2 in this pod). This syntax is chosen only to have some well-defined way of - referencing a part of an object. - type: string - kind: - description: |- - Kind of the referent. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - name: - description: |- - Name of the referent. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - type: string - namespace: - description: |- - Namespace of the referent. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/ - type: string - resourceVersion: - description: |- - Specific resourceVersion to which this reference is made, if any. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#concurrency-control-and-consistency - type: string - uid: - description: |- - UID of the referent. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#uids - type: string - type: object - x-kubernetes-map-type: atomic - type: array - result: - description: Result indicates the outcome of the policy rule - execution - enum: - - pass - - fail - - warn - - error - - skip - type: string - rule: - description: Rule is the name or identifier of the rule within - the policy - type: string - scored: - description: Scored indicates if this result is scored - type: boolean - severity: - description: Severity indicates policy check result criticality - enum: - - critical - - high - - low - - medium - - info - type: string - source: - description: |- - Source is an identifier for the policy engine that manages this report - If the Source is specified at this level, it will override the Source - field set at the Report level - type: string - timestamp: - description: Timestamp indicates the time the result was found - properties: - nanos: - description: |- - Non-negative fractions of a second at nanosecond resolution. Negative - second values with fractions must still have non-negative nanos values - that count forward in time. Must be from 0 to 999,999,999 - inclusive. This field may be limited in precision depending on context. - format: int32 - type: integer - seconds: - description: |- - Represents seconds of UTC time since Unix epoch - 1970-01-01T00:00:00Z. Must be from 0001-01-01T00:00:00Z to - 9999-12-31T23:59:59Z inclusive. - format: int64 - type: integer - required: - - nanos - - seconds - type: object - required: - - policy - type: object - type: array - summary: - description: PolicyReportSummary provides a summary of results - properties: - error: - description: Error provides the count of policies that could not - be evaluated - type: integer - fail: - description: Fail provides the count of policies whose requirements - were not met - type: integer - pass: - description: Pass provides the count of policies whose requirements - were met - type: integer - skip: - description: Skip indicates the count of policies that were not - selected for evaluation - type: integer - warn: - description: Warn provides the count of non-scored policies whose - requirements were not met - type: integer - type: object - required: - - owner - type: object - required: - - spec - type: object - served: true - storage: true - subresources: {} ---- -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - labels: - app.kubernetes.io/component: crds - app.kubernetes.io/instance: kyverno - app.kubernetes.io/managed-by: Helm - app.kubernetes.io/part-of: kyverno-crds - app.kubernetes.io/version: 3.5.1 - helm.sh/chart: crds-3.5.1 - annotations: - controller-gen.kubebuilder.io/version: v0.17.3 - name: clusterpolicyreports.wgpolicyk8s.io -spec: - group: wgpolicyk8s.io - names: - kind: ClusterPolicyReport - listKind: ClusterPolicyReportList - plural: clusterpolicyreports - shortNames: - - cpolr - singular: clusterpolicyreport - scope: Cluster - versions: - - additionalPrinterColumns: - - jsonPath: .scope.kind - name: Kind - type: string - - jsonPath: .scope.name - name: Name - type: string - - jsonPath: .summary.pass - name: Pass - type: integer - - jsonPath: .summary.fail - name: Fail - type: integer - - jsonPath: .summary.warn - name: Warn - type: integer - - jsonPath: .summary.error - name: Error - type: integer - - jsonPath: .summary.skip - name: Skip - type: integer - - jsonPath: .metadata.creationTimestamp - name: Age - type: date - name: v1alpha2 - schema: - openAPIV3Schema: - description: ClusterPolicyReport is the Schema for the clusterpolicyreports - API - properties: - apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - type: string - kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - metadata: - type: object - results: - description: PolicyReportResult provides result details - items: - description: PolicyReportResult provides the result for an individual - policy - properties: - category: - description: Category indicates policy category - type: string - message: - description: Description is a short user friendly message for the - policy rule - type: string - policy: - description: Policy is the name or identifier of the policy - type: string - properties: - additionalProperties: - type: string - description: Properties provides additional information for the - policy rule - type: object - resourceSelector: - description: |- - SubjectSelector is an optional label selector for checked Kubernetes resources. - For example, a policy result may apply to all pods that match a label. - Either a Subject or a SubjectSelector can be specified. - If neither are provided, the result is assumed to be for the policy report scope. - properties: - matchExpressions: - description: matchExpressions is a list of label selector requirements. - The requirements are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key that the selector applies - to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - resources: - description: Subjects is an optional reference to the checked Kubernetes - resources - items: - description: ObjectReference contains enough information to let - you inspect or modify the referred object. - properties: - apiVersion: - description: API version of the referent. - type: string - fieldPath: - description: |- - If referring to a piece of an object instead of an entire object, this string - should contain a valid JSON/Go field access statement, such as desiredState.manifest.containers[2]. - For example, if the object reference is to a container within a pod, this would take on a value like: - "spec.containers{name}" (where "name" refers to the name of the container that triggered - the event) or if no container name is specified "spec.containers[2]" (container with - index 2 in this pod). This syntax is chosen only to have some well-defined way of - referencing a part of an object. - type: string - kind: - description: |- - Kind of the referent. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - name: - description: |- - Name of the referent. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - type: string - namespace: - description: |- - Namespace of the referent. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/ - type: string - resourceVersion: - description: |- - Specific resourceVersion to which this reference is made, if any. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#concurrency-control-and-consistency - type: string - uid: - description: |- - UID of the referent. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#uids - type: string - type: object - x-kubernetes-map-type: atomic - type: array - result: - description: Result indicates the outcome of the policy rule execution - enum: - - pass - - fail - - warn - - error - - skip - type: string - rule: - description: Rule is the name or identifier of the rule within the - policy - type: string - scored: - description: Scored indicates if this result is scored - type: boolean - severity: - description: Severity indicates policy check result criticality - enum: - - critical - - high - - low - - medium - - info - type: string - source: - description: Source is an identifier for the policy engine that - manages this report - type: string - timestamp: - description: Timestamp indicates the time the result was found - properties: - nanos: - description: |- - Non-negative fractions of a second at nanosecond resolution. Negative - second values with fractions must still have non-negative nanos values - that count forward in time. Must be from 0 to 999,999,999 - inclusive. This field may be limited in precision depending on context. - format: int32 - type: integer - seconds: - description: |- - Represents seconds of UTC time since Unix epoch - 1970-01-01T00:00:00Z. Must be from 0001-01-01T00:00:00Z to - 9999-12-31T23:59:59Z inclusive. - format: int64 - type: integer - required: - - nanos - - seconds - type: object - required: - - policy - type: object - type: array - scope: - description: Scope is an optional reference to the report scope (e.g. - a Deployment, Namespace, or Node) - properties: - apiVersion: - description: API version of the referent. - type: string - fieldPath: - description: |- - If referring to a piece of an object instead of an entire object, this string - should contain a valid JSON/Go field access statement, such as desiredState.manifest.containers[2]. - For example, if the object reference is to a container within a pod, this would take on a value like: - "spec.containers{name}" (where "name" refers to the name of the container that triggered - the event) or if no container name is specified "spec.containers[2]" (container with - index 2 in this pod). This syntax is chosen only to have some well-defined way of - referencing a part of an object. - type: string - kind: - description: |- - Kind of the referent. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - name: - description: |- - Name of the referent. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - type: string - namespace: - description: |- - Namespace of the referent. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/ - type: string - resourceVersion: - description: |- - Specific resourceVersion to which this reference is made, if any. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#concurrency-control-and-consistency - type: string - uid: - description: |- - UID of the referent. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#uids - type: string - type: object - x-kubernetes-map-type: atomic - scopeSelector: - description: |- - ScopeSelector is an optional selector for multiple scopes (e.g. Pods). - Either one of, or none of, but not both of, Scope or ScopeSelector should be specified. - properties: - matchExpressions: - description: matchExpressions is a list of label selector requirements. - The requirements are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key that the selector applies - to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - summary: - description: PolicyReportSummary provides a summary of results - properties: - error: - description: Error provides the count of policies that could not be - evaluated - type: integer - fail: - description: Fail provides the count of policies whose requirements - were not met - type: integer - pass: - description: Pass provides the count of policies whose requirements - were met - type: integer - skip: - description: Skip indicates the count of policies that were not selected - for evaluation - type: integer - warn: - description: Warn provides the count of non-scored policies whose - requirements were not met - type: integer - type: object - type: object - served: true - storage: true - subresources: {} ---- -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - labels: - app.kubernetes.io/component: crds - app.kubernetes.io/instance: kyverno - app.kubernetes.io/managed-by: Helm - app.kubernetes.io/part-of: kyverno-crds - app.kubernetes.io/version: 3.5.1 - helm.sh/chart: crds-3.5.1 - annotations: - controller-gen.kubebuilder.io/version: v0.17.3 - name: policyreports.wgpolicyk8s.io -spec: - group: wgpolicyk8s.io - names: - kind: PolicyReport - listKind: PolicyReportList - plural: policyreports - shortNames: - - polr - singular: policyreport - scope: Namespaced - versions: - - additionalPrinterColumns: - - jsonPath: .scope.kind - name: Kind - type: string - - jsonPath: .scope.name - name: Name - type: string - - jsonPath: .summary.pass - name: Pass - type: integer - - jsonPath: .summary.fail - name: Fail - type: integer - - jsonPath: .summary.warn - name: Warn - type: integer - - jsonPath: .summary.error - name: Error - type: integer - - jsonPath: .summary.skip - name: Skip - type: integer - - jsonPath: .metadata.creationTimestamp - name: Age - type: date - name: v1alpha2 - schema: - openAPIV3Schema: - description: PolicyReport is the Schema for the policyreports API - properties: - apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - type: string - kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - metadata: - type: object - results: - description: PolicyReportResult provides result details - items: - description: PolicyReportResult provides the result for an individual - policy - properties: - category: - description: Category indicates policy category - type: string - message: - description: Description is a short user friendly message for the - policy rule - type: string - policy: - description: Policy is the name or identifier of the policy - type: string - properties: - additionalProperties: - type: string - description: Properties provides additional information for the - policy rule - type: object - resourceSelector: - description: |- - SubjectSelector is an optional label selector for checked Kubernetes resources. - For example, a policy result may apply to all pods that match a label. - Either a Subject or a SubjectSelector can be specified. - If neither are provided, the result is assumed to be for the policy report scope. - properties: - matchExpressions: - description: matchExpressions is a list of label selector requirements. - The requirements are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key that the selector applies - to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - resources: - description: Subjects is an optional reference to the checked Kubernetes - resources - items: - description: ObjectReference contains enough information to let - you inspect or modify the referred object. - properties: - apiVersion: - description: API version of the referent. - type: string - fieldPath: - description: |- - If referring to a piece of an object instead of an entire object, this string - should contain a valid JSON/Go field access statement, such as desiredState.manifest.containers[2]. - For example, if the object reference is to a container within a pod, this would take on a value like: - "spec.containers{name}" (where "name" refers to the name of the container that triggered - the event) or if no container name is specified "spec.containers[2]" (container with - index 2 in this pod). This syntax is chosen only to have some well-defined way of - referencing a part of an object. - type: string - kind: - description: |- - Kind of the referent. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - name: - description: |- - Name of the referent. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - type: string - namespace: - description: |- - Namespace of the referent. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/ - type: string - resourceVersion: - description: |- - Specific resourceVersion to which this reference is made, if any. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#concurrency-control-and-consistency - type: string - uid: - description: |- - UID of the referent. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#uids - type: string - type: object - x-kubernetes-map-type: atomic - type: array - result: - description: Result indicates the outcome of the policy rule execution - enum: - - pass - - fail - - warn - - error - - skip - type: string - rule: - description: Rule is the name or identifier of the rule within the - policy - type: string - scored: - description: Scored indicates if this result is scored - type: boolean - severity: - description: Severity indicates policy check result criticality - enum: - - critical - - high - - low - - medium - - info - type: string - source: - description: Source is an identifier for the policy engine that - manages this report - type: string - timestamp: - description: Timestamp indicates the time the result was found - properties: - nanos: - description: |- - Non-negative fractions of a second at nanosecond resolution. Negative - second values with fractions must still have non-negative nanos values - that count forward in time. Must be from 0 to 999,999,999 - inclusive. This field may be limited in precision depending on context. - format: int32 - type: integer - seconds: - description: |- - Represents seconds of UTC time since Unix epoch - 1970-01-01T00:00:00Z. Must be from 0001-01-01T00:00:00Z to - 9999-12-31T23:59:59Z inclusive. - format: int64 - type: integer - required: - - nanos - - seconds - type: object - required: - - policy - type: object - type: array - scope: - description: Scope is an optional reference to the report scope (e.g. - a Deployment, Namespace, or Node) - properties: - apiVersion: - description: API version of the referent. - type: string - fieldPath: - description: |- - If referring to a piece of an object instead of an entire object, this string - should contain a valid JSON/Go field access statement, such as desiredState.manifest.containers[2]. - For example, if the object reference is to a container within a pod, this would take on a value like: - "spec.containers{name}" (where "name" refers to the name of the container that triggered - the event) or if no container name is specified "spec.containers[2]" (container with - index 2 in this pod). This syntax is chosen only to have some well-defined way of - referencing a part of an object. - type: string - kind: - description: |- - Kind of the referent. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - name: - description: |- - Name of the referent. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - type: string - namespace: - description: |- - Namespace of the referent. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/ - type: string - resourceVersion: - description: |- - Specific resourceVersion to which this reference is made, if any. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#concurrency-control-and-consistency - type: string - uid: - description: |- - UID of the referent. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#uids - type: string - type: object - x-kubernetes-map-type: atomic - scopeSelector: - description: |- - ScopeSelector is an optional selector for multiple scopes (e.g. Pods). - Either one of, or none of, but not both of, Scope or ScopeSelector should be specified. - properties: - matchExpressions: - description: matchExpressions is a list of label selector requirements. - The requirements are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key that the selector applies - to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - summary: - description: PolicyReportSummary provides a summary of results - properties: - error: - description: Error provides the count of policies that could not be - evaluated - type: integer - fail: - description: Fail provides the count of policies whose requirements - were not met - type: integer - pass: - description: Pass provides the count of policies whose requirements - were met - type: integer - skip: - description: Skip indicates the count of policies that were not selected - for evaluation - type: integer - warn: - description: Warn provides the count of non-scored policies whose - requirements were not met - type: integer - type: object - type: object - served: true - storage: true - subresources: {} ---- -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - name: kyverno:admission-controller - labels: - app.kubernetes.io/component: admission-controller - app.kubernetes.io/instance: kyverno - app.kubernetes.io/part-of: kyverno - app.kubernetes.io/version: v1.15.1 -aggregationRule: - clusterRoleSelectors: - - matchLabels: - rbac.kyverno.io/aggregate-to-admission-controller: "true" - - matchLabels: - app.kubernetes.io/component: admission-controller - app.kubernetes.io/instance: kyverno - app.kubernetes.io/part-of: kyverno ---- -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - name: kyverno:admission-controller:core - labels: - app.kubernetes.io/component: admission-controller - app.kubernetes.io/instance: kyverno - app.kubernetes.io/part-of: kyverno - app.kubernetes.io/version: v1.15.1 -rules: - - apiGroups: - - apiextensions.k8s.io - resources: - - customresourcedefinitions - verbs: - - get - - apiGroups: - - admissionregistration.k8s.io - resources: - - mutatingwebhookconfigurations - - validatingwebhookconfigurations - - validatingadmissionpolicies - - validatingadmissionpolicybindings - verbs: - - create - - delete - - get - - list - - patch - - update - - watch - - deletecollection - - apiGroups: - - rbac.authorization.k8s.io - resources: - - roles - - clusterroles - - rolebindings - - clusterrolebindings - verbs: - - get - - list - - watch - - apiGroups: - - kyverno.io - resources: - - policies - - policies/status - - clusterpolicies - - clusterpolicies/status - - updaterequests - - updaterequests/status - - globalcontextentries - - globalcontextentries/status - verbs: - - create - - delete - - get - - list - - patch - - update - - watch - - deletecollection - - apiGroups: - - kyverno.io - resources: - - policyexceptions - verbs: - - create - - get - - list - - patch - - update - - watch - - apiGroups: - - policies.kyverno.io - resources: - - validatingpolicies - - validatingpolicies/status - - imagevalidatingpolicies - - imagevalidatingpolicies/status - - generatingpolicies - - generatingpolicies/status - - mutatingpolicies - - mutatingpolicies/status - verbs: - - create - - delete - - get - - list - - patch - - update - - watch - - deletecollection - - apiGroups: - - policies.kyverno.io - resources: - - policyexceptions - verbs: - - create - - get - - list - - patch - - update - - watch - - apiGroups: - - reports.kyverno.io - resources: - - ephemeralreports - - clusterephemeralreports - verbs: - - create - - delete - - get - - list - - patch - - update - - watch - - deletecollection - - apiGroups: - - wgpolicyk8s.io - resources: - - policyreports - - policyreports/status - - clusterpolicyreports - - clusterpolicyreports/status - verbs: - - create - - delete - - get - - list - - patch - - update - - watch - - deletecollection - - apiGroups: - - '' - - events.k8s.io - resources: - - events - verbs: - - create - - update - - patch - - apiGroups: - - authorization.k8s.io - resources: - - subjectaccessreviews - verbs: - - create - - apiGroups: - - '' - resources: - - configmaps - - namespaces - verbs: - - get - - list - - watch - - apiGroups: - - coordination.k8s.io - resources: - - leases - verbs: - - create - - update - - patch - - get - - list - - watch ---- -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - name: kyverno:background-controller - labels: - app.kubernetes.io/component: background-controller - app.kubernetes.io/instance: kyverno - app.kubernetes.io/part-of: kyverno - app.kubernetes.io/version: v1.15.1 -aggregationRule: - clusterRoleSelectors: - - matchLabels: - rbac.kyverno.io/aggregate-to-background-controller: "true" - - matchLabels: - app.kubernetes.io/component: background-controller - app.kubernetes.io/instance: kyverno - app.kubernetes.io/part-of: kyverno ---- -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - name: kyverno:background-controller:core - labels: - app.kubernetes.io/component: background-controller - app.kubernetes.io/instance: kyverno - app.kubernetes.io/part-of: kyverno - app.kubernetes.io/version: v1.15.1 -rules: - - apiGroups: - - apiextensions.k8s.io - resources: - - customresourcedefinitions - verbs: - - get - - apiGroups: - - kyverno.io - resources: - - policies - - policies/status - - clusterpolicies - - clusterpolicies/status - - policyexceptions - - updaterequests - - updaterequests/status - - globalcontextentries - - globalcontextentries/status - verbs: - - create - - delete - - get - - list - - patch - - update - - watch - - deletecollection - - apiGroups: - - policies.kyverno.io - resources: - - generatingpolicies - - mutatingpolicies - - policyexceptions - verbs: - - create - - delete - - get - - list - - patch - - update - - watch - - deletecollection - - apiGroups: - - policies.kyverno.io - resources: - - policyexceptions - verbs: - - create - - get - - list - - patch - - update - - watch - - apiGroups: - - '' - resources: - - namespaces - - configmaps - verbs: - - get - - list - - watch - - apiGroups: - - '' - - events.k8s.io - resources: - - events - verbs: - - create - - get - - list - - patch - - update - - watch - - apiGroups: - - reports.kyverno.io - resources: - - ephemeralreports - - clusterephemeralreports - verbs: - - create - - delete - - get - - list - - patch - - update - - watch - - deletecollection - - apiGroups: - - networking.k8s.io - resources: - - ingresses - - ingressclasses - - networkpolicies - verbs: - - create - - update - - patch - - delete - - apiGroups: - - rbac.authorization.k8s.io - resources: - - rolebindings - - roles - verbs: - - create - - update - - patch - - delete - - apiGroups: - - "" - resources: - - configmaps - - resourcequotas - - limitranges - verbs: - - create - - update - - patch - - delete ---- -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - name: kyverno:cleanup-controller - labels: - app.kubernetes.io/component: cleanup-controller - app.kubernetes.io/instance: kyverno - app.kubernetes.io/part-of: kyverno - app.kubernetes.io/version: v1.15.1 -aggregationRule: - clusterRoleSelectors: - - matchLabels: - rbac.kyverno.io/aggregate-to-cleanup-controller: "true" - - matchLabels: - app.kubernetes.io/component: cleanup-controller - app.kubernetes.io/instance: kyverno - app.kubernetes.io/part-of: kyverno ---- -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - name: kyverno:cleanup-controller:core - labels: - app.kubernetes.io/component: cleanup-controller - app.kubernetes.io/instance: kyverno - app.kubernetes.io/part-of: kyverno - app.kubernetes.io/version: v1.15.1 -rules: - - apiGroups: - - apiextensions.k8s.io - resources: - - customresourcedefinitions - verbs: - - get - - apiGroups: - - admissionregistration.k8s.io - resources: - - validatingwebhookconfigurations - verbs: - - create - - delete - - get - - list - - update - - watch - - apiGroups: - - '' - resources: - - namespaces - verbs: - - get - - list - - watch - - apiGroups: - - kyverno.io - resources: - - clustercleanuppolicies - - cleanuppolicies - verbs: - - list - - watch - - apiGroups: - - policies.kyverno.io - resources: - - deletingpolicies - verbs: - - get - - list - - watch - - apiGroups: - - policies.kyverno.io - resources: - - deletingpolicies/status - verbs: - - update - - apiGroups: - - policies.kyverno.io - resources: - - policyexceptions - verbs: - - get - - list - - patch - - update - - watch - - apiGroups: - - kyverno.io - resources: - - globalcontextentries - - globalcontextentries/status - verbs: - - create - - delete - - get - - list - - patch - - update - - watch - - deletecollection - - apiGroups: - - kyverno.io - resources: - - clustercleanuppolicies/status - - cleanuppolicies/status - verbs: - - update - - apiGroups: - - '' - resources: - - configmaps - verbs: - - get - - list - - watch - - apiGroups: - - '' - - events.k8s.io - resources: - - events - verbs: - - create - - patch - - update - - apiGroups: - - authorization.k8s.io - resources: - - subjectaccessreviews - verbs: - - create ---- -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - name: kyverno:rbac:admin:policies - labels: - app.kubernetes.io/component: rbac - app.kubernetes.io/instance: kyverno - app.kubernetes.io/part-of: kyverno - app.kubernetes.io/version: v1.15.1 - rbac.authorization.k8s.io/aggregate-to-admin: "true" -rules: - - apiGroups: - - kyverno.io - resources: - - cleanuppolicies - - clustercleanuppolicies - - policies - - clusterpolicies - verbs: - - create - - delete - - get - - list - - patch - - update - - watch ---- -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - name: kyverno:rbac:view:policies - labels: - app.kubernetes.io/component: rbac - app.kubernetes.io/instance: kyverno - app.kubernetes.io/part-of: kyverno - app.kubernetes.io/version: v1.15.1 - rbac.authorization.k8s.io/aggregate-to-view: "true" -rules: - - apiGroups: - - kyverno.io - resources: - - cleanuppolicies - - clustercleanuppolicies - - policies - - clusterpolicies - verbs: - - get - - list - - watch ---- -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - name: kyverno:rbac:admin:policyreports - labels: - app.kubernetes.io/component: rbac - app.kubernetes.io/instance: kyverno - app.kubernetes.io/part-of: kyverno - app.kubernetes.io/version: v1.15.1 - rbac.authorization.k8s.io/aggregate-to-admin: "true" -rules: - - apiGroups: - - wgpolicyk8s.io - resources: - - policyreports - - clusterpolicyreports - verbs: - - create - - delete - - get - - list - - patch - - update - - watch ---- -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - name: kyverno:rbac:view:policyreports - labels: - app.kubernetes.io/component: rbac - app.kubernetes.io/instance: kyverno - app.kubernetes.io/part-of: kyverno - app.kubernetes.io/version: v1.15.1 - rbac.authorization.k8s.io/aggregate-to-view: "true" -rules: - - apiGroups: - - wgpolicyk8s.io - resources: - - policyreports - - clusterpolicyreports - verbs: - - get - - list - - watch ---- -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - name: kyverno:rbac:admin:reports - labels: - app.kubernetes.io/component: rbac - app.kubernetes.io/instance: kyverno - app.kubernetes.io/part-of: kyverno - app.kubernetes.io/version: v1.15.1 - rbac.authorization.k8s.io/aggregate-to-admin: "true" -rules: - - apiGroups: - - reports.kyverno.io - resources: - - ephemeralreports - - clusterephemeralreports - verbs: - - create - - delete - - get - - list - - patch - - update - - watch ---- -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - name: kyverno:rbac:view:reports - labels: - app.kubernetes.io/component: rbac - app.kubernetes.io/instance: kyverno - app.kubernetes.io/part-of: kyverno - app.kubernetes.io/version: v1.15.1 - rbac.authorization.k8s.io/aggregate-to-view: "true" -rules: - - apiGroups: - - reports.kyverno.io - resources: - - ephemeralreports - - clusterephemeralreports - verbs: - - get - - list - - watch ---- -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - name: kyverno:rbac:admin:updaterequests - labels: - app.kubernetes.io/component: rbac - app.kubernetes.io/instance: kyverno - app.kubernetes.io/part-of: kyverno - app.kubernetes.io/version: v1.15.1 - rbac.authorization.k8s.io/aggregate-to-admin: "true" -rules: - - apiGroups: - - kyverno.io - resources: - - updaterequests - verbs: - - create - - delete - - get - - list - - patch - - update - - watch ---- -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - name: kyverno:rbac:view:updaterequests - labels: - app.kubernetes.io/component: rbac - app.kubernetes.io/instance: kyverno - app.kubernetes.io/part-of: kyverno - app.kubernetes.io/version: v1.15.1 - rbac.authorization.k8s.io/aggregate-to-view: "true" -rules: - - apiGroups: - - kyverno.io - resources: - - updaterequests - verbs: - - get - - list - - watch ---- -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - name: kyverno:reports-controller - labels: - app.kubernetes.io/component: reports-controller - app.kubernetes.io/instance: kyverno - app.kubernetes.io/part-of: kyverno - app.kubernetes.io/version: v1.15.1 -aggregationRule: - clusterRoleSelectors: - - matchLabels: - rbac.kyverno.io/aggregate-to-reports-controller: "true" - - matchLabels: - app.kubernetes.io/component: reports-controller - app.kubernetes.io/instance: kyverno - app.kubernetes.io/part-of: kyverno ---- -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - name: kyverno:reports-controller:core - labels: - app.kubernetes.io/component: reports-controller - app.kubernetes.io/instance: kyverno - app.kubernetes.io/part-of: kyverno - app.kubernetes.io/version: v1.15.1 -rules: - - apiGroups: - - apiextensions.k8s.io - resources: - - customresourcedefinitions - verbs: - - get - - apiGroups: - - '' - resources: - - configmaps - - namespaces - verbs: - - get - - list - - watch - - apiGroups: - - kyverno.io - resources: - - globalcontextentries - - globalcontextentries/status - - policyexceptions - - policies - - clusterpolicies - verbs: - - create - - delete - - get - - list - - patch - - update - - watch - - deletecollection - - apiGroups: - - policies.kyverno.io - resources: - - validatingpolicies - - validatingpolicies/status - - imagevalidatingpolicies - - imagevalidatingpolicies/status - - generatingpolicies - - mutatingpolicies - verbs: - - create - - delete - - get - - list - - patch - - update - - watch - - deletecollection - - apiGroups: - - policies.kyverno.io - resources: - - policyexceptions - - policyexceptions/status - verbs: - - get - - list - - watch - - apiGroups: - - admissionregistration.k8s.io - resources: - - validatingadmissionpolicies - - validatingadmissionpolicybindings - verbs: - - get - - list - - watch - - apiGroups: - - reports.kyverno.io - resources: - - ephemeralreports - - clusterephemeralreports - verbs: - - create - - delete - - get - - list - - patch - - update - - watch - - deletecollection - - apiGroups: - - wgpolicyk8s.io - resources: - - policyreports - - policyreports/status - - clusterpolicyreports - - clusterpolicyreports/status - verbs: - - create - - delete - - get - - list - - patch - - update - - watch - - deletecollection - - apiGroups: - - openreports.io - resources: - - reports - - reports/status - - clusterreports - - clusterreports/status - verbs: - - create - - delete - - get - - list - - patch - - update - - watch - - deletecollection - - apiGroups: - - '' - - events.k8s.io - resources: - - events - verbs: - - create - - patch ---- -kind: ClusterRoleBinding -apiVersion: rbac.authorization.k8s.io/v1 -metadata: - name: kyverno:admission-controller - labels: - app.kubernetes.io/component: admission-controller - app.kubernetes.io/instance: kyverno - app.kubernetes.io/part-of: kyverno - app.kubernetes.io/version: v1.15.1 -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: ClusterRole - name: kyverno:admission-controller -subjects: - - kind: ServiceAccount - name: kyverno-admission-controller - namespace: kyverno ---- -kind: ClusterRoleBinding -apiVersion: rbac.authorization.k8s.io/v1 -metadata: - name: kyverno:admission-controller:view - labels: - app.kubernetes.io/component: admission-controller - app.kubernetes.io/instance: kyverno - app.kubernetes.io/part-of: kyverno - app.kubernetes.io/version: v1.15.1 -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: ClusterRole - name: view -subjects: - - kind: ServiceAccount - name: kyverno-admission-controller - namespace: kyverno ---- -kind: ClusterRoleBinding -apiVersion: rbac.authorization.k8s.io/v1 -metadata: - name: kyverno:background-controller - labels: - app.kubernetes.io/component: background-controller - app.kubernetes.io/instance: kyverno - app.kubernetes.io/part-of: kyverno - app.kubernetes.io/version: v1.15.1 -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: ClusterRole - name: kyverno:background-controller -subjects: -- kind: ServiceAccount - name: kyverno-background-controller - namespace: kyverno ---- -kind: ClusterRoleBinding -apiVersion: rbac.authorization.k8s.io/v1 -metadata: - name: kyverno:background-controller:view - labels: - app.kubernetes.io/component: background-controller - app.kubernetes.io/instance: kyverno - app.kubernetes.io/part-of: kyverno - app.kubernetes.io/version: v1.15.1 -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: ClusterRole - name: view -subjects: -- kind: ServiceAccount - name: kyverno-background-controller - namespace: kyverno ---- -kind: ClusterRoleBinding -apiVersion: rbac.authorization.k8s.io/v1 -metadata: - name: kyverno:cleanup-controller - labels: - app.kubernetes.io/component: cleanup-controller - app.kubernetes.io/instance: kyverno - app.kubernetes.io/part-of: kyverno - app.kubernetes.io/version: v1.15.1 -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: ClusterRole - name: kyverno:cleanup-controller -subjects: -- kind: ServiceAccount - name: kyverno-cleanup-controller - namespace: kyverno ---- -kind: ClusterRoleBinding -apiVersion: rbac.authorization.k8s.io/v1 -metadata: - name: kyverno:reports-controller - labels: - app.kubernetes.io/component: reports-controller - app.kubernetes.io/instance: kyverno - app.kubernetes.io/part-of: kyverno - app.kubernetes.io/version: v1.15.1 -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: ClusterRole - name: kyverno:reports-controller -subjects: -- kind: ServiceAccount - name: kyverno-reports-controller - namespace: kyverno ---- -kind: ClusterRoleBinding -apiVersion: rbac.authorization.k8s.io/v1 -metadata: - name: kyverno:reports-controller:view - labels: - app.kubernetes.io/component: reports-controller - app.kubernetes.io/instance: kyverno - app.kubernetes.io/part-of: kyverno - app.kubernetes.io/version: v1.15.1 -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: ClusterRole - name: view -subjects: -- kind: ServiceAccount - name: kyverno-reports-controller - namespace: kyverno ---- -apiVersion: rbac.authorization.k8s.io/v1 -kind: Role -metadata: - name: kyverno:admission-controller - namespace: kyverno - labels: - app.kubernetes.io/component: admission-controller - app.kubernetes.io/instance: kyverno - app.kubernetes.io/part-of: kyverno - app.kubernetes.io/version: v1.15.1 -rules: - - apiGroups: - - '' - resources: - - secrets - - serviceaccounts - verbs: - - get - - list - - watch - - patch - - create - - update - - delete - - apiGroups: - - '' - resources: - - configmaps - verbs: - - get - - list - - watch - resourceNames: - - kyverno - - kyverno-metrics - - apiGroups: - - coordination.k8s.io - resources: - - leases - verbs: - - create - - delete - - get - - patch - - update - # Allow update of Kyverno deployment annotations - - apiGroups: - - apps - resources: - - deployments - verbs: - - get - - list - - watch ---- -apiVersion: rbac.authorization.k8s.io/v1 -kind: Role -metadata: - name: kyverno:background-controller - labels: - app.kubernetes.io/component: background-controller - app.kubernetes.io/instance: kyverno - app.kubernetes.io/part-of: kyverno - app.kubernetes.io/version: v1.15.1 - namespace: kyverno -rules: - - apiGroups: - - '' - resources: - - configmaps - verbs: - - get - - list - - watch - resourceNames: - - kyverno - - kyverno-metrics - - apiGroups: - - coordination.k8s.io - resources: - - leases - verbs: - - create - - apiGroups: - - coordination.k8s.io - resources: - - leases - verbs: - - delete - - get - - patch - - update - resourceNames: - - kyverno-background-controller - - apiGroups: - - '' - resources: - - secrets - verbs: - - get - - list - - watch ---- -apiVersion: rbac.authorization.k8s.io/v1 -kind: Role -metadata: - name: kyverno:cleanup-controller - labels: - app.kubernetes.io/component: cleanup-controller - app.kubernetes.io/instance: kyverno - app.kubernetes.io/part-of: kyverno - app.kubernetes.io/version: v1.15.1 - namespace: kyverno -rules: - - apiGroups: - - '' - resources: - - secrets - verbs: - - create - - apiGroups: - - '' - resources: - - secrets - verbs: - - delete - - get - - list - - update - - watch - resourceNames: - - kyverno-cleanup-controller.kyverno.svc.kyverno-tls-ca - - kyverno-cleanup-controller.kyverno.svc.kyverno-tls-pair - - apiGroups: - - '' - resources: - - configmaps - verbs: - - get - - list - - watch - resourceNames: - - kyverno - - kyverno-metrics - - apiGroups: - - coordination.k8s.io - resources: - - leases - verbs: - - create - - apiGroups: - - coordination.k8s.io - resources: - - leases - verbs: - - delete - - get - - patch - - update - resourceNames: - - kyverno-cleanup-controller - - apiGroups: - - apps - resources: - - deployments - verbs: - - get - - list - - watch ---- -apiVersion: rbac.authorization.k8s.io/v1 -kind: Role -metadata: - name: kyverno:reports-controller - labels: - app.kubernetes.io/component: reports-controller - app.kubernetes.io/instance: kyverno - app.kubernetes.io/part-of: kyverno - app.kubernetes.io/version: v1.15.1 - namespace: kyverno -rules: - - apiGroups: - - '' - resources: - - configmaps - verbs: - - get - - list - - watch - resourceNames: - - kyverno - - kyverno-metrics - - apiGroups: - - '' - resources: - - secrets - verbs: - - get - - list - - watch - - apiGroups: - - coordination.k8s.io - resources: - - leases - verbs: - - create - - apiGroups: - - coordination.k8s.io - resources: - - leases - verbs: - - delete - - get - - patch - - update - resourceNames: - - kyverno-reports-controller ---- -kind: RoleBinding -apiVersion: rbac.authorization.k8s.io/v1 -metadata: - name: kyverno:admission-controller - namespace: kyverno - labels: - app.kubernetes.io/component: admission-controller - app.kubernetes.io/instance: kyverno - app.kubernetes.io/part-of: kyverno - app.kubernetes.io/version: v1.15.1 -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: Role - name: kyverno:admission-controller -subjects: - - kind: ServiceAccount - name: kyverno-admission-controller - namespace: kyverno ---- -kind: RoleBinding -apiVersion: rbac.authorization.k8s.io/v1 -metadata: - name: kyverno:background-controller - labels: - app.kubernetes.io/component: background-controller - app.kubernetes.io/instance: kyverno - app.kubernetes.io/part-of: kyverno - app.kubernetes.io/version: v1.15.1 - namespace: kyverno -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: Role - name: kyverno:background-controller -subjects: - - kind: ServiceAccount - name: kyverno-background-controller - namespace: kyverno ---- -kind: RoleBinding -apiVersion: rbac.authorization.k8s.io/v1 -metadata: - name: kyverno:cleanup-controller - labels: - app.kubernetes.io/component: cleanup-controller - app.kubernetes.io/instance: kyverno - app.kubernetes.io/part-of: kyverno - app.kubernetes.io/version: v1.15.1 - namespace: kyverno -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: Role - name: kyverno:cleanup-controller -subjects: - - kind: ServiceAccount - name: kyverno-cleanup-controller - namespace: kyverno ---- -kind: RoleBinding -apiVersion: rbac.authorization.k8s.io/v1 -metadata: - name: kyverno:reports-controller - labels: - app.kubernetes.io/component: reports-controller - app.kubernetes.io/instance: kyverno - app.kubernetes.io/part-of: kyverno - app.kubernetes.io/version: v1.15.1 - namespace: kyverno -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: Role - name: kyverno:reports-controller -subjects: - - kind: ServiceAccount - name: kyverno-reports-controller - namespace: kyverno ---- -apiVersion: v1 -kind: Service -metadata: - name: kyverno-svc - namespace: kyverno - labels: - app.kubernetes.io/component: admission-controller - app.kubernetes.io/instance: kyverno - app.kubernetes.io/part-of: kyverno - app.kubernetes.io/version: v1.15.1 -spec: - ports: - - port: 443 - targetPort: https - protocol: TCP - name: https - appProtocol: https - selector: - app.kubernetes.io/component: admission-controller - app.kubernetes.io/instance: kyverno - app.kubernetes.io/part-of: kyverno - type: ClusterIP ---- -apiVersion: v1 -kind: Service -metadata: - name: kyverno-svc-metrics - namespace: kyverno - labels: - app.kubernetes.io/component: admission-controller - app.kubernetes.io/instance: kyverno - app.kubernetes.io/part-of: kyverno - app.kubernetes.io/version: v1.15.1 -spec: - ports: - - port: 8000 - targetPort: 8000 - protocol: TCP - name: metrics-port - selector: - app.kubernetes.io/component: admission-controller - app.kubernetes.io/instance: kyverno - app.kubernetes.io/part-of: kyverno - type: ClusterIP ---- -apiVersion: v1 -kind: Service -metadata: - name: kyverno-background-controller-metrics - namespace: kyverno - labels: - app.kubernetes.io/component: background-controller - app.kubernetes.io/instance: kyverno - app.kubernetes.io/part-of: kyverno - app.kubernetes.io/version: v1.15.1 -spec: - ports: - - port: 8000 - targetPort: 8000 - protocol: TCP - name: metrics-port - selector: - app.kubernetes.io/component: background-controller - app.kubernetes.io/instance: kyverno - app.kubernetes.io/part-of: kyverno - type: ClusterIP ---- -apiVersion: v1 -kind: Service -metadata: - name: kyverno-cleanup-controller - namespace: kyverno - labels: - app.kubernetes.io/component: cleanup-controller - app.kubernetes.io/instance: kyverno - app.kubernetes.io/part-of: kyverno - app.kubernetes.io/version: v1.15.1 -spec: - ports: - - port: 443 - targetPort: https - protocol: TCP - name: https - appProtocol: https - selector: - app.kubernetes.io/component: cleanup-controller - app.kubernetes.io/instance: kyverno - app.kubernetes.io/part-of: kyverno - type: ClusterIP ---- -apiVersion: v1 -kind: Service -metadata: - name: kyverno-cleanup-controller-metrics - namespace: kyverno - labels: - app.kubernetes.io/component: cleanup-controller - app.kubernetes.io/instance: kyverno - app.kubernetes.io/part-of: kyverno - app.kubernetes.io/version: v1.15.1 -spec: - ports: - - port: 8000 - targetPort: 8000 - protocol: TCP - name: metrics-port - selector: - app.kubernetes.io/component: cleanup-controller - app.kubernetes.io/instance: kyverno - app.kubernetes.io/part-of: kyverno - type: ClusterIP ---- -apiVersion: v1 -kind: Service -metadata: - name: kyverno-reports-controller-metrics - namespace: kyverno - labels: - app.kubernetes.io/component: reports-controller - app.kubernetes.io/instance: kyverno - app.kubernetes.io/part-of: kyverno - app.kubernetes.io/version: v1.15.1 -spec: - ports: - - port: 8000 - targetPort: 8000 - protocol: TCP - name: metrics-port - selector: - app.kubernetes.io/component: reports-controller - app.kubernetes.io/instance: kyverno - app.kubernetes.io/part-of: kyverno - type: ClusterIP ---- -apiVersion: apps/v1 -kind: Deployment -metadata: - name: kyverno-admission-controller - namespace: kyverno - labels: - app.kubernetes.io/component: admission-controller - app.kubernetes.io/instance: kyverno - app.kubernetes.io/part-of: kyverno - app.kubernetes.io/version: v1.15.1 -spec: - replicas: - revisionHistoryLimit: 10 - strategy: - rollingUpdate: - maxSurge: 1 - maxUnavailable: 40% - type: RollingUpdate - selector: - matchLabels: - app.kubernetes.io/component: admission-controller - app.kubernetes.io/instance: kyverno - app.kubernetes.io/part-of: kyverno - template: - metadata: - labels: - app.kubernetes.io/component: admission-controller - app.kubernetes.io/instance: kyverno - app.kubernetes.io/part-of: kyverno - app.kubernetes.io/version: v1.15.1 - spec: - dnsPolicy: ClusterFirst - affinity: - podAntiAffinity: - preferredDuringSchedulingIgnoredDuringExecution: - - podAffinityTerm: - labelSelector: - matchExpressions: - - key: app.kubernetes.io/component - operator: In - values: - - admission-controller - topologyKey: kubernetes.io/hostname - weight: 1 - serviceAccountName: kyverno-admission-controller - automountServiceAccountToken: true - initContainers: - - name: kyverno-pre - image: "reg.kyverno.io/kyverno/kyvernopre:v1.15.1" - imagePullPolicy: IfNotPresent - args: - - --loggingFormat=text - - --v=2 - - --openreportsEnabled=false - resources: - limits: - cpu: 100m - memory: 256Mi - requests: - cpu: 10m - memory: 64Mi - securityContext: - allowPrivilegeEscalation: false - capabilities: - drop: - - ALL - privileged: false - readOnlyRootFilesystem: true - runAsNonRoot: true - seccompProfile: - type: RuntimeDefault - env: - - name: KYVERNO_SERVICEACCOUNT_NAME - value: kyverno-admission-controller - - name: KYVERNO_ROLE_NAME - value: kyverno:admission-controller - - name: INIT_CONFIG - value: kyverno - - name: METRICS_CONFIG - value: kyverno-metrics - - name: KYVERNO_NAMESPACE - valueFrom: - fieldRef: - fieldPath: metadata.namespace - - name: KYVERNO_POD_NAME - valueFrom: - fieldRef: - fieldPath: metadata.name - - name: KYVERNO_DEPLOYMENT - value: kyverno-admission-controller - - name: KYVERNO_SVC - value: kyverno-svc - containers: - - name: kyverno - image: "reg.kyverno.io/kyverno/kyverno:v1.15.1" - imagePullPolicy: IfNotPresent - args: - - --caSecretName=kyverno-svc.kyverno.svc.kyverno-tls-ca - - --tlsSecretName=kyverno-svc.kyverno.svc.kyverno-tls-pair - - --backgroundServiceAccountName=system:serviceaccount:kyverno:kyverno-background-controller - - --reportsServiceAccountName=system:serviceaccount:kyverno:kyverno-reports-controller - - --servicePort=443 - - --webhookServerPort=9443 - - --resyncPeriod=15m - - --crdWatcher=false - - --disableMetrics=false - - --otelConfig=prometheus - - --metricsPort=8000 - - --admissionReports=true - - --maxAdmissionReports=1000 - - --autoUpdateWebhooks=true - - --enableConfigMapCaching=true - - --controllerRuntimeMetricsAddress=:8080 - - --enableDeferredLoading=true - - --dumpPayload=false - - --forceFailurePolicyIgnore=false - - --generateValidatingAdmissionPolicy=true - - --generateMutatingAdmissionPolicy=false - - --dumpPatches=false - - --maxAPICallResponseLength=2000000 - - --loggingFormat=text - - --v=2 - - --omitEvents=PolicyApplied,PolicySkipped - - --enablePolicyException=false - - --protectManagedResources=false - - --allowInsecureRegistry=false - - --registryCredentialHelpers=default,google,amazon,azure,github - - --enableReporting=validate,mutate,mutateExisting,imageVerify,generate - - resources: - limits: - memory: 384Mi - requests: - cpu: 100m - memory: 128Mi - securityContext: - allowPrivilegeEscalation: false - capabilities: - drop: - - ALL - privileged: false - readOnlyRootFilesystem: true - runAsNonRoot: true - seccompProfile: - type: RuntimeDefault - ports: - - containerPort: 9443 - name: https - protocol: TCP - - containerPort: 8000 - name: metrics-port - protocol: TCP - - env: - - name: INIT_CONFIG - value: kyverno - - name: METRICS_CONFIG - value: kyverno-metrics - - name: KYVERNO_NAMESPACE - valueFrom: - fieldRef: - fieldPath: metadata.namespace - - name: KYVERNO_POD_NAME - valueFrom: - fieldRef: - fieldPath: metadata.name - - name: KYVERNO_SERVICEACCOUNT_NAME - value: kyverno-admission-controller - - name: KYVERNO_ROLE_NAME - value: kyverno:admission-controller - - name: KYVERNO_SVC - value: kyverno-svc - - name: TUF_ROOT - value: /.sigstore - - name: KYVERNO_DEPLOYMENT - value: kyverno-admission-controller - startupProbe: - failureThreshold: 20 - httpGet: - path: /health/liveness - port: 9443 - scheme: HTTPS - initialDelaySeconds: 2 - periodSeconds: 6 - livenessProbe: - failureThreshold: 2 - httpGet: - path: /health/liveness - port: 9443 - scheme: HTTPS - initialDelaySeconds: 15 - periodSeconds: 30 - successThreshold: 1 - timeoutSeconds: 5 - readinessProbe: - failureThreshold: 6 - httpGet: - path: /health/readiness - port: 9443 - scheme: HTTPS - initialDelaySeconds: 5 - periodSeconds: 10 - successThreshold: 1 - timeoutSeconds: 5 - volumeMounts: - - mountPath: /.sigstore - name: sigstore - volumes: - - name: sigstore - emptyDir: {} ---- -apiVersion: apps/v1 -kind: Deployment -metadata: - name: kyverno-background-controller - namespace: kyverno - labels: - app.kubernetes.io/component: background-controller - app.kubernetes.io/instance: kyverno - app.kubernetes.io/part-of: kyverno - app.kubernetes.io/version: v1.15.1 -spec: - replicas: - revisionHistoryLimit: 10 - strategy: - rollingUpdate: - maxSurge: 1 - maxUnavailable: 40% - type: RollingUpdate - selector: - matchLabels: - app.kubernetes.io/component: background-controller - app.kubernetes.io/instance: kyverno - app.kubernetes.io/part-of: kyverno - template: - metadata: - labels: - app.kubernetes.io/component: background-controller - app.kubernetes.io/instance: kyverno - app.kubernetes.io/part-of: kyverno - app.kubernetes.io/version: v1.15.1 - spec: - dnsPolicy: ClusterFirst - affinity: - podAntiAffinity: - preferredDuringSchedulingIgnoredDuringExecution: - - podAffinityTerm: - labelSelector: - matchExpressions: - - key: app.kubernetes.io/component - operator: In - values: - - background-controller - topologyKey: kubernetes.io/hostname - weight: 1 - serviceAccountName: kyverno-background-controller - automountServiceAccountToken: true - containers: - - name: controller - image: "reg.kyverno.io/kyverno/background-controller:v1.15.1" - imagePullPolicy: IfNotPresent - ports: - - containerPort: 9443 - name: https - protocol: TCP - - containerPort: 8000 - name: metrics - protocol: TCP - - args: - - --disableMetrics=false - - --otelConfig=prometheus - - --metricsPort=8000 - - --resyncPeriod=15m - - --enableConfigMapCaching=true - - --enableDeferredLoading=true - - --maxAPICallResponseLength=2000000 - - --loggingFormat=text - - --v=2 - - --omitEvents=PolicyApplied,PolicySkipped - - --enablePolicyException=false - - --enableReporting=validate,mutate,mutateExisting,imageVerify,generate - - env: - - name: KYVERNO_SERVICEACCOUNT_NAME - value: kyverno-background-controller - - name: KYVERNO_DEPLOYMENT - value: kyverno-background-controller - - name: INIT_CONFIG - value: kyverno - - name: METRICS_CONFIG - value: kyverno-metrics - - name: KYVERNO_POD_NAME - valueFrom: - fieldRef: - fieldPath: metadata.name - - name: KYVERNO_NAMESPACE - valueFrom: - fieldRef: - fieldPath: metadata.namespace - resources: - limits: - memory: 128Mi - requests: - cpu: 100m - memory: 64Mi - securityContext: - allowPrivilegeEscalation: false - capabilities: - drop: - - ALL - privileged: false - readOnlyRootFilesystem: true - runAsNonRoot: true - seccompProfile: - type: RuntimeDefault ---- -apiVersion: apps/v1 -kind: Deployment -metadata: - name: kyverno-cleanup-controller - namespace: kyverno - labels: - app.kubernetes.io/component: cleanup-controller - app.kubernetes.io/instance: kyverno - app.kubernetes.io/part-of: kyverno - app.kubernetes.io/version: v1.15.1 -spec: - replicas: - revisionHistoryLimit: 10 - strategy: - rollingUpdate: - maxSurge: 1 - maxUnavailable: 40% - type: RollingUpdate - selector: - matchLabels: - app.kubernetes.io/component: cleanup-controller - app.kubernetes.io/instance: kyverno - app.kubernetes.io/part-of: kyverno - template: - metadata: - labels: - app.kubernetes.io/component: cleanup-controller - app.kubernetes.io/instance: kyverno - app.kubernetes.io/part-of: kyverno - app.kubernetes.io/version: v1.15.1 - spec: - dnsPolicy: ClusterFirst - affinity: - podAntiAffinity: - preferredDuringSchedulingIgnoredDuringExecution: - - podAffinityTerm: - labelSelector: - matchExpressions: - - key: app.kubernetes.io/component - operator: In - values: - - cleanup-controller - topologyKey: kubernetes.io/hostname - weight: 1 - serviceAccountName: kyverno-cleanup-controller - automountServiceAccountToken: true - containers: - - name: controller - image: "reg.kyverno.io/kyverno/cleanup-controller:v1.15.1" - imagePullPolicy: IfNotPresent - ports: - - containerPort: 9443 - name: https - protocol: TCP - - containerPort: 8000 - name: metrics - protocol: TCP - - args: - - --caSecretName=kyverno-cleanup-controller.kyverno.svc.kyverno-tls-ca - - --tlsSecretName=kyverno-cleanup-controller.kyverno.svc.kyverno-tls-pair - - --servicePort=443 - - --cleanupServerPort=9443 - - --webhookServerPort=9443 - - --resyncPeriod=15m - - --disableMetrics=false - - --otelConfig=prometheus - - --metricsPort=8000 - - --enableDeferredLoading=true - - --dumpPayload=false - - --maxAPICallResponseLength=2000000 - - --loggingFormat=text - - --v=2 - - --protectManagedResources=false - - --ttlReconciliationInterval=1m - - env: - - name: KYVERNO_DEPLOYMENT - value: kyverno-cleanup-controller - - name: INIT_CONFIG - value: kyverno - - name: METRICS_CONFIG - value: kyverno-metrics - - name: KYVERNO_POD_NAME - valueFrom: - fieldRef: - fieldPath: metadata.name - - name: KYVERNO_SERVICEACCOUNT_NAME - value: kyverno-cleanup-controller - - name: KYVERNO_ROLE_NAME - value: kyverno:cleanup-controller - - name: KYVERNO_NAMESPACE - valueFrom: - fieldRef: - fieldPath: metadata.namespace - - name: KYVERNO_SVC - value: kyverno-cleanup-controller - resources: - limits: - memory: 128Mi - requests: - cpu: 100m - memory: 64Mi - securityContext: - allowPrivilegeEscalation: false - capabilities: - drop: - - ALL - privileged: false - readOnlyRootFilesystem: true - runAsNonRoot: true - seccompProfile: - type: RuntimeDefault - startupProbe: - failureThreshold: 20 - httpGet: - path: /health/liveness - port: 9443 - scheme: HTTPS - initialDelaySeconds: 2 - periodSeconds: 6 - livenessProbe: - failureThreshold: 2 - httpGet: - path: /health/liveness - port: 9443 - scheme: HTTPS - initialDelaySeconds: 15 - periodSeconds: 30 - successThreshold: 1 - timeoutSeconds: 5 - readinessProbe: - failureThreshold: 6 - httpGet: - path: /health/readiness - port: 9443 - scheme: HTTPS - initialDelaySeconds: 5 - periodSeconds: 10 - successThreshold: 1 - timeoutSeconds: 5 ---- -apiVersion: apps/v1 -kind: Deployment -metadata: - name: kyverno-reports-controller - namespace: kyverno - labels: - app.kubernetes.io/component: reports-controller - app.kubernetes.io/instance: kyverno - app.kubernetes.io/part-of: kyverno - app.kubernetes.io/version: v1.15.1 -spec: - replicas: - revisionHistoryLimit: 10 - strategy: - rollingUpdate: - maxSurge: 1 - maxUnavailable: 40% - type: RollingUpdate - selector: - matchLabels: - app.kubernetes.io/component: reports-controller - app.kubernetes.io/instance: kyverno - app.kubernetes.io/part-of: kyverno - template: - metadata: - labels: - app.kubernetes.io/component: reports-controller - app.kubernetes.io/instance: kyverno - app.kubernetes.io/part-of: kyverno - app.kubernetes.io/version: v1.15.1 - spec: - dnsPolicy: ClusterFirst - affinity: - podAntiAffinity: - preferredDuringSchedulingIgnoredDuringExecution: - - podAffinityTerm: - labelSelector: - matchExpressions: - - key: app.kubernetes.io/component - operator: In - values: - - reports-controller - topologyKey: kubernetes.io/hostname - weight: 1 - serviceAccountName: kyverno-reports-controller - automountServiceAccountToken: true - containers: - - name: controller - image: "reg.kyverno.io/kyverno/reports-controller:v1.15.1" - imagePullPolicy: IfNotPresent - ports: - - containerPort: 9443 - name: https - protocol: TCP - - containerPort: 8000 - name: metrics - protocol: TCP - - args: - - --disableMetrics=false - - --openreportsEnabled=false - - --otelConfig=prometheus - - --metricsPort=8000 - - --resyncPeriod=15m - - --admissionReports=true - - --aggregateReports=true - - --policyReports=true - - --validatingAdmissionPolicyReports=true - - --mutatingAdmissionPolicyReports=false - - --backgroundScan=true - - --backgroundScanWorkers=2 - - --backgroundScanInterval=1h - - --skipResourceFilters=true - - --enableConfigMapCaching=true - - --enableDeferredLoading=true - - --maxAPICallResponseLength=2000000 - - --loggingFormat=text - - --v=2 - - --omitEvents=PolicyApplied,PolicySkipped - - --enablePolicyException=false - - --allowInsecureRegistry=false - - --registryCredentialHelpers=default,google,amazon,azure,github - - --enableReporting=validate,mutate,mutateExisting,imageVerify,generate - env: - - name: KYVERNO_SERVICEACCOUNT_NAME - value: kyverno-reports-controller - - name: KYVERNO_DEPLOYMENT - value: kyverno-reports-controller - - name: INIT_CONFIG - value: kyverno - - name: METRICS_CONFIG - value: kyverno-metrics - - name: KYVERNO_POD_NAME - valueFrom: - fieldRef: - fieldPath: metadata.name - - name: KYVERNO_NAMESPACE - valueFrom: - fieldRef: - fieldPath: metadata.namespace - - name: TUF_ROOT - value: /.sigstore - resources: - limits: - memory: 128Mi - requests: - cpu: 100m - memory: 64Mi - securityContext: - allowPrivilegeEscalation: false - capabilities: - drop: - - ALL - privileged: false - readOnlyRootFilesystem: true - runAsNonRoot: true - seccompProfile: - type: RuntimeDefault - volumeMounts: - - mountPath: /.sigstore - name: sigstore - volumes: - - name: sigstore - emptyDir: {} diff --git a/carvel-packages/installer/bundle/config/ytt/config.yaml b/carvel-packages/installer/bundle/config/ytt/config.yaml deleted file mode 100644 index 6e5aba887..000000000 --- a/carvel-packages/installer/bundle/config/ytt/config.yaml +++ /dev/null @@ -1,51 +0,0 @@ -#@ load("@ytt:data", "data") -#@ load("@ytt:library", "library") -#@ load("@ytt:template", "template") -#@ load("@ytt:overlay", "overlay") -#@ load("@ytt:struct", "struct") -#@ load("@ytt:yaml", "yaml") -#@ load("functions/kapp-annotations.lib.yaml", "addKappAnnotations") - -#@ orderedPackagesList = [ -#@ "cert-manager", -#@ "contour", -#@ "external-dns", -#@ "certs", -#@ "kyverno", -#@ "kapp-controller", -#@ "educates" -#@ ] - -#@ def getOverlaysFromLibrary(): -#@ if hasattr(data.values.clusterInfrastructure, "provider"): -#@ infra = "infrastructure/" + data.values.clusterInfrastructure.provider -#@ return library.get(infra).with_data_values(data.values).eval() -#@ end -#@ end - -#@ overlayedValues = data.values -#@ for overlayToApply in getOverlaysFromLibrary(): -#@ overlayedValues = struct.encode(yaml.decode(yaml.encode(overlay.apply(overlayedValues, overlayToApply)))) -#@ end - -#! TODO: Here would be nice to calculate all the certificate specifics and then pass them to the overlayedValues - -#@ if data.values.debug: ---- #@ overlayedValues -#@ else: -#@ for name in orderedPackagesList: #! overlayedValues.clusterPackages: -#@ package = overlayedValues.clusterPackages[name] -#@ packagePath = "packages/" + name -#@ packageValues = package.settings -#@ if package.enabled: ---- #@ template.replace(overlay.apply(library.get(packagePath).with_data_values(packageValues).eval(), addKappAnnotations(name, overlayedValues, orderedPackagesList))) -#@ end -#@ end - -#@ allInfo = struct.make(config=data.values, values=overlayedValues) -#@ if overlayedValues.clusterPackages["educates"].enabled: ---- #@ template.replace(overlay.apply(library.get("config").with_data_values(allInfo).eval(), addKappAnnotations("educates", overlayedValues, orderedPackagesList))) -#@ else: ---- #@ template.replace(overlay.apply(library.get("config").with_data_values(allInfo).eval())) -#@ end -#@ end diff --git a/carvel-packages/installer/bundle/config/ytt/functions/kapp-annotations.lib.yaml b/carvel-packages/installer/bundle/config/ytt/functions/kapp-annotations.lib.yaml deleted file mode 100644 index e2f76a5ea..000000000 --- a/carvel-packages/installer/bundle/config/ytt/functions/kapp-annotations.lib.yaml +++ /dev/null @@ -1,49 +0,0 @@ -#@ load("@ytt:data", "data") -#@ load("@ytt:overlay", "overlay") - -#@ def addKappAnnotations(packageName, valuesToApply, orderedPackagesList): - -#@ activatedPackagesList = [] -#@ for name in orderedPackagesList: -#@ if name in valuesToApply.clusterPackages: -#@ package = valuesToApply.clusterPackages[name] -#@ if package.enabled == True: -#@ activatedPackagesList.append(name) -#@ end -#@ end -#@ end - -#@ index = activatedPackagesList.index(packageName) -#@ if index == 0: -#@ prev = None -#@ else: -#@ prev = activatedPackagesList[index - 1] -#@ end -#@ if index == len(activatedPackagesList) - 1: -#@ next = None -#@ else: -#@ next = activatedPackagesList[index + 1] -#@ end - -#@overlay/match by=lambda i,l,r: "metadata" in l,expects="0+" ---- -metadata: - #@overlay/match missing_ok=True - annotations: - #@overlay/match missing_ok=True - educates.dev/infra-provider: #@ data.values.clusterInfrastructure.provider - #@overlay/match missing_ok=True - kapp.k14s.io/disable-original: "" - #@overlay/match missing_ok=True - kapp.k14s.io/change-group.package: #@ "educates-installer/{}".format(packageName) - #@overlay/match missing_ok=True - kapp.k14s.io/change-group.global: #@ "educates-installer" - #@ if prev!=None: - #@overlay/match missing_ok=True - kapp.k14s.io/change-rule.insert: #@ "upsert after upserting educates-installer/{}".format(prev) - #@ end - #@ if next!=None: - #@overlay/match missing_ok=True - kapp.k14s.io/change-rule.delete: #@ "delete after deleting educates-installer/{}".format(next) - #@ end -#@ end diff --git a/carvel-packages/installer/bundle/config/ytt/schema-rules.star b/carvel-packages/installer/bundle/config/ytt/schema-rules.star deleted file mode 100644 index 5ea1c1a4c..000000000 --- a/carvel-packages/installer/bundle/config/ytt/schema-rules.star +++ /dev/null @@ -1,69 +0,0 @@ -load("@ytt:assert", "assert") - -def custom_requires_clusterPackages(val): - if val["clusterPackages"] == None: - return fail("clusterPackages must be defined when provider is custom") - end -end - -def custom_requires_one_enabled_Package(val): - for package in val["clusterPackages"]: - if val["clusterPackages"][package] != None and val["clusterPackages"][package]["enabled"] == True: - return True - end - end - fail("At least one package needs to be enabled for custom provider") -end - -validation_custom = [ - custom_requires_clusterPackages, - custom_requires_one_enabled_Package -] - -def validate_custom(val): - if val["clusterInfrastructure"]["provider"] == "custom": - for function in validation_custom: - function(val) - end - end - return True -end - -def validate_domain(val): - #! Domain not validated for custom infrastructure provider - if val["clusterInfrastructure"]["provider"] == "custom": - return True - end - - #! Domain provided at top level - if val["clusterIngress"] != None and \ - val["clusterIngress"]["domain"] != None: - return True - end - - #! Domain provided at clusterPackage level - val, err = assert.try_to(lambda: val["clusterPackages"]["educates"]["settings"]["clusterIngress"]["domain"]) - if val != None: - return True - end - - #! Domain is not required if educates is not enabled - enabled, err = assert.try_to(lambda: val["clusterPackages"]["educates"]["enabled"]) - if not enabled: - return True - end - - fail("clusterIngress.domain for educates needs to be provided") -end - -validation_functions = [ - validate_custom, - validate_domain -] - -def validate_all(val): - for function in validation_functions: - function(val) - end - return True -end diff --git a/carvel-packages/installer/bundle/config/ytt/values-schema.yaml b/carvel-packages/installer/bundle/config/ytt/values-schema.yaml deleted file mode 100644 index 61c3305fd..000000000 --- a/carvel-packages/installer/bundle/config/ytt/values-schema.yaml +++ /dev/null @@ -1,317 +0,0 @@ -#@ load("schema-rules.star", "validate_all") - -#@data/values-schema -#@schema/validation ("Error validating config", validate_all) ---- -debug: false -#@schema/nullable -clusterPackages: - #@schema/nullable - contour: - enabled: true - #@schema/nullable - #@schema/type any=True - settings: {} - #@schema/nullable - cert-manager: - enabled: false - #@schema/nullable - #@schema/type any=True - settings: {} - #@schema/nullable - external-dns: - enabled: false - #@schema/nullable - #@schema/type any=True - settings: {} - #@schema/nullable - certs: - enabled: false - #@schema/nullable - #@schema/type any=True - settings: {} - #@schema/nullable - kyverno: - enabled: true - #@schema/nullable - #@schema/type any=True - settings: {} - #@schema/nullable - kapp-controller: - enabled: false - #@schema/nullable - #@schema/type any=True - settings: {} - #@schema/nullable - educates: - enabled: true - #@schema/nullable - #@schema/type any=True - settings: {} -#@schema/title "Cluster Infrastructure" -#@schema/desc "Configuration for the cluster infrastructure" -clusterInfrastructure: - #! NOT IMPLEMENTED: "azure", "gke-autopilot" - #! TODO: Implement validators. e.g. when kind is selected, clusterIngress.domain is required. - #@schema/validation one_of=["eks", "gke", "kind", "custom", "vcluster", "generic", "minikube", "openshift"] - provider: "custom" - #@schema/nullable - #@schema/validation not_null=True, when=lambda _, ctx: ctx.root["clusterInfrastructure"]["provider"] == "eks" - #@schema/title "AWS specific configuration" - #@schema/desc "AWS specific configuration to use when provider is set to eks" - aws: - #@schema/title "AWS Region" - #@schema/desc "AWS Region where the cluster exists. This is needed for cert-manager's cluster issuer, when cert-manager is installed" - #@schema/validation ("region is required for aws based providers",lambda v: len(v) >= 1) - region: "" - #@schema/title "Route53 configuration" - #@schema/desc "Route53 configuration for the AWS account. This will be used by external-dns to manage DNS records" - #@schema/nullable - route53: - #@schema/title "Route53 HostedZone" - #@schema/desc "Route53 HostedZone to use. When not provided, external-dns will be provided with clusterIngress.domain" - #@schema/validation ("route53.hostedZone is required for aws based providers",lambda v: len(v) >= 1) - hostedZone: "" - #@schema/title "AWS IAM IRSA Roles" - #@schema/desc "AWS IAM IRSA Roles for external-dns and cert-manager" - irsaRoles: - #@schema/example "arn:aws:iam::MY_IAM:role/external-dns" - #@schema/validation ("irsaRole for external-dns is required for aws based providers",lambda v: len(v) >= 1) - external-dns: "" - #@schema/example "arn:aws:iam::MY_IAM:role/cert-manager" - #@schema/validation ("irsaRole for cert-manager is required for aws based providers",lambda v: len(v) >= 1) - cert-manager: "" - #@schema/nullable - #@schema/validation not_null=True, when=lambda _, ctx: ctx.root["clusterInfrastructure"]["provider"] == "gcp" - #@schema/title "GCP specific configuration" - #@schema/desc "GCP specific configuration to use when provider is set to gke" - gcp: - #@schema/title "GCP project" - #@schema/desc "GCP project where the cluster exists" - #@schema/validation ("project is required for gcp based providers",lambda v: len(v) >= 1) - project: "" - #@schema/title "CloudDNS configuration" - #@schema/desc "CloudDNS configuration for the GCP project. This will be used by external-dns to manage DNS records" - #@schema/nullable - cloudDNS: - #@schema/title "CloudDNS zone" - #@schema/desc "CloudDNS zone to use. When not provided, external-dns will be provided with clusterIngress.domain" - #@schema/validation ("cloudDNS.zone is required for gcp based providers",lambda v: len(v) >= 1) - zone: "" - #@schema/title "GCP IAM WorkloadIdentities" - #@schema/desc "GCP IAM WorkloadIdentities for external-dns and cert-manager" - workloadIdentity: - #@schema/example "external-dns@my-project.iam.gserviceaccount.com" - #@schema/validation ("workloadIdentity for external-dns is required for gcp based providers",lambda v: len(v) >= 1) - external-dns: "" - #@schema/example "cert-manager@my-project.iam.gserviceaccount.com" - #@schema/validation ("workloadIdentity for cert-manager is required for gcp based providers",lambda v: len(v) >= 1) - cert-manager: "" - #@schema/title "CA Certificate" - #@schema/desc "CA Certificates to inject to the cluster. When provider is set to kind it'll configure cert-manager to generate certs. CA Issuers must be configured with a certificate (tls.crt) and private key (tls.key) stored in the Kubernetes secret" - #@schema/nullable - caCertificateRef: - #@schema/validation min_len=1 - namespace: "" - #@schema/validation min_len=1 - name: "" -#!--------- educates installation schema -#@schema/nullable -#@schema/type any=True -localKindCluster: {} -#@schema/nullable -#@schema/type any=True -localDNSResolver: {} -#!--------- educates training platform schema -#! NOTE: https://github.com/jorgemoralespou/educates-training-platform/blob/develop/carvel-packages/training-platform/bundle/config/00-schema.yaml#L21C1-L33 -#! This is only so that the images generates are loaded from this registry. There's a pre-proccesing step that will generate a images file -#! so that this is not needed to be provided by the user. -#@schema/nullable -sessionManager: - clusterAdmin: true -#@schema/nullable -imageRegistry: - #@schema/nullable - #@schema/validation min_len=1 - host: "" - namespace: "" -#@schema/nullable -version: "" -#@schema/nullable -imageVersions: - - name: "" - image: "" -#@schema/nullable -clusterRuntime: - #@schema/nullable - class: "" -clusterIngress: - #@schema/nullable - domain: "" - #@schema/nullable - class: "" - #@schema/nullable - protocol: "" - #@schema/nullable - tlsCertificate: - #@schema/validation min_len=1 - tls.crt: "" - #@schema/validation min_len=1 - tls.key: "" - #@schema/nullable - tlsCertificateRef: - #@schema/validation min_len=1 - namespace: "" - #@schema/validation min_len=1 - name: "" - #! This seems to only be needed for provided certificates that are signed by a local CA, - #! which means that you need to provide the tlsCertificate as well - #@schema/nullable - caCertificate: - #@schema/validation min_len=1 - ca.crt: "" - #! This seems to only be needed for provided certificates that are signed by a local CA, - #! which means that you need to provide the tlsCertificate as well - #@schema/nullable - caCertificateRef: - #@schema/validation min_len=1 - namespace: "" - #@schema/validation min_len=1 - name: "" - #@schema/nullable - caNodeInjector: - enabled: false -#@schema/nullable -sessionCookies: - domain: "" -#@schema/nullable -clusterStorage: - #@schema/nullable - class: "" - #@schema/nullable - user: 0 - #@schema/nullable - group: 1 -#@schema/nullable -clusterSecrets: - pullSecretRefs: - - namespace: "" - name: "" -#! This element is not nullable so that kyverno is the default -clusterSecurity: - #@schema/validation one_of=["pod-security-policies", "pod-security-standards", "security-context-constraints", "kyverno", "none"] - policyEngine: "kyverno" -#! This element is not nullable so that kyverno is the default -workshopSecurity: - #@schema/validation one_of=["kyverno", "none"] - rulesEngine: "kyverno" -#@schema/nullable -trainingPortal: - #@schema/nullable - credentials: - #@schema/nullable - admin: - #@schema/validation min_len=1 - username: "educates" - #@schema/validation min_len=1 - password: "" - #@schema/nullable - robot: - #@schema/validation min_len=1 - username: "robot@educates" - #@schema/validation min_len=1 - password: "" - #@schema/nullable - clients: - robot: - #@schema/validation min_len=1 - id: "" - #@schema/validation min_len=1 - secret: "" -#@schema/nullable -dockerDaemon: - #@schema/nullable - networkMTU: 1400 - #@schema/nullable - proxyCache: - #@schema/validation min_len=1 - remoteURL: "" - #@schema/nullable - username: "" - #@schema/nullable - password: "" -#@schema/nullable -clusterNetwork: - #@schema/default ["169.254.169.254/32", "fd00:ec2::254/128"] - blockCIDRs: - - "" -#@schema/nullable -workshopAnalytics: - #@schema/nullable - google: - #@schema/validation min_len=1 - trackingId: "" - #@schema/nullable - clarity: - #@schema/validation min_len=1 - trackingId: "" - #@schema/nullable - amplitude: - #@schema/validation min_len=1 - trackingId: "" - #@schema/nullable - webhook: - #@schema/validation min_len=1 - url: "" -#@schema/nullable -websiteStyling: - #@schema/nullable - workshopDashboard: - #@schema/nullable - html: "" - #@schema/nullable - script: "" - #@schema/nullable - style: "" - #@schema/nullable - workshopInstructions: - #@schema/nullable - html: "" - #@schema/nullable - script: "" - #@schema/nullable - style: "" - #@schema/nullable - workshopStarted: - html: "" - #@schema/nullable - workshopFinished: - html: "" - #@schema/nullable - trainingPortal: - html: "" - #@schema/nullable - script: "" - #@schema/nullable - style: "" - #@schema/nullable - defaultTheme: "" - #@schema/nullable - themeDataRefs: - - name: "" - namespace: "" - #@schema/nullable - frameAncestors: - - "" -#@schema/nullable -imagePuller: - enabled: true - #@schema/default ["base-environment"] - prePullImages: - #@schema/validation min_len=1 - - "" -#@schema/nullable -lookupService: - enabled: false - #@schema/nullable - ingressPrefix: "educates-api" diff --git a/carvel-packages/installer/bundle/kbld/kbld-bundle.yaml b/carvel-packages/installer/bundle/kbld/kbld-bundle.yaml deleted file mode 100644 index 0672a1a0c..000000000 --- a/carvel-packages/installer/bundle/kbld/kbld-bundle.yaml +++ /dev/null @@ -1,29 +0,0 @@ ---- -apiVersion: kbld.k14s.io/v1alpha1 -minimumRequiredVersion: 0.30.0 -kind: Config -searchRules: - # - keyMatcher: - # name: educates-original-config.yaml - # updateStrategy: - # yaml: - # searchRules: - # - keyMatcher: - # name: image - - keyMatcher: - name: educates-processed-values.yaml - updateStrategy: - yaml: - searchRules: - - keyMatcher: - name: image - - keyMatcher: - name: educates-operator-config.yaml - updateStrategy: - yaml: - searchRules: - - keyMatcher: - name: image - # This rule replaces acmeresolver image in cert-manager deployment (after upstream descriptor has been modified by educates installer) - - keyMatcher: - name: acmesolver-image diff --git a/carvel-packages/installer/config/app.yaml b/carvel-packages/installer/config/app.yaml deleted file mode 100644 index fe222431c..000000000 --- a/carvel-packages/installer/config/app.yaml +++ /dev/null @@ -1,71 +0,0 @@ -#@ load("@ytt:data", "data") -#@ load("@ytt:yaml", "yaml") - -#@ def bundle_reference(): -#@ registry = data.values.imageRegistry.host -#@ if not registry or registry == "localhost:5001": -#@ registry = "registry.default.svc.cluster.local" -#@ end -#@ if data.values.imageRegistry.namespace: -#@ registry = "{}/{}".format(registry, data.values.imageRegistry.namespace) -#@ end -#@ return "{}/educates-installer:{}".format(registry, data.values.version) -#@ end - -#! This configmap provides interoperability between the kapp-controller installation and -#! the educates CLI installation, by preconfiguring the label kapp-controller's App will use to -#! be the same as the one used by the educates CLI. -#! The name of the configmap will be the same as the App, but with `.app` appended. -#! The `spec` needs `labelKey` and `labelValue` fields to be set. ---- -apiVersion: v1 -kind: ConfigMap -metadata: - labels: - kapp.k14s.io/is-app: "" - annotations: - kapp.k14s.io/app-changes-use-app-label: "" - name: installer.educates.dev.app - namespace: educates-installer -data: - spec: '{"labelKey":"installer","labelValue":"educates-installer.app"}' ---- -apiVersion: kappctrl.k14s.io/v1alpha1 -kind: App -metadata: - name: installer.educates.dev - namespace: educates-installer -spec: - serviceAccountName: educates-installer - syncPeriod: 87600h #! 10 years - fetch: - - imgpkgBundle: - image: #@ bundle_reference() - path: bundle - - inline: - paths: - disable-kapp-controller.yaml: | - clusterPackages: - kapp-controller: - enabled: false - path: values - template: - - ytt: - valuesFrom: - - path: "bundle/kbld/kbld-images.yaml" - - secretRef: - name: educates-installer - - path: values/disable-kapp-controller.yaml - paths: - - "bundle/kbld/kbld-bundle.yaml" - - "bundle/config/kapp" - - "bundle/config/ytt" - - kbld: - paths: - - "bundle/.imgpkg/images.yml" - - "-" - deploy: - - kapp: - rawOptions: - - "--app-changes-max-to-keep=0" - #! - "--diff-changes=true" diff --git a/carvel-packages/installer/config/images.yaml b/carvel-packages/installer/config/images.yaml deleted file mode 100644 index edc34af67..000000000 --- a/carvel-packages/installer/config/images.yaml +++ /dev/null @@ -1,61 +0,0 @@ -#@ load("@ytt:data", "data") - -#@ def image_reference(name): -#@ registry = data.values.imageRegistry.host -#@ if not registry: -#@ registry = "localhost:5001" -#@ end -#@ if data.values.imageRegistry.namespace: -#@ registry = "{}/{}".format(registry, data.values.imageRegistry.namespace) -#@ end -#@ return "{}/educates-{}:{}".format(registry, name, data.values.version) -#@ end - ---- -imageVersions: - - name: session-manager - image: #@ image_reference("session-manager") - - name: training-portal - image: #@ image_reference("training-portal") - - name: docker-registry - image: #@ image_reference("docker-registry") - - name: pause-container - image: #@ image_reference("pause-container") - - name: base-environment - image: #@ image_reference("base-environment") - - name: jdk8-environment - image: #@ image_reference("jdk8-environment") - - name: jdk11-environment - image: #@ image_reference("jdk11-environment") - - name: jdk17-environment - image: #@ image_reference("jdk17-environment") - - name: jdk21-environment - image: #@ image_reference("jdk21-environment") - - name: conda-environment - image: #@ image_reference("conda-environment") - - name: secrets-manager - image: #@ image_reference("secrets-manager") - - name: tunnel-manager - image: #@ image_reference("tunnel-manager") - - name: image-cache - image: #@ image_reference("image-cache") - - name: assets-server - image: #@ image_reference("assets-server") - - name: lookup-service - image: #@ image_reference("lookup-service") - - name: node-ca-injector - image: #@ image_reference("node-ca-injector") - - name: debian-base-image - image: "debian:sid-20230502-slim" - - name: docker-in-docker - image: "docker:27.5.1-dind" - - name: loftsh-kubernetes-v1.31 - image: "ghcr.io/loft-sh/kubernetes:v1.31.1" - - name: loftsh-kubernetes-v1.32 - image: "ghcr.io/loft-sh/kubernetes:v1.32.1" - - name: loftsh-kubernetes-v1.33 - image: "ghcr.io/loft-sh/kubernetes:v1.33.4" - - name: loftsh-kubernetes-v1.34 - image: "ghcr.io/loft-sh/kubernetes:v1.34.0" - - name: loftsh-vcluster - image: "ghcr.io/loft-sh/vcluster-oss:0.30.2" diff --git a/carvel-packages/installer/config/rbac.yaml b/carvel-packages/installer/config/rbac.yaml deleted file mode 100644 index 1a9f30535..000000000 --- a/carvel-packages/installer/config/rbac.yaml +++ /dev/null @@ -1,24 +0,0 @@ ---- -kind: Namespace -apiVersion: v1 -metadata: - name: educates-installer ---- -kind: ServiceAccount -apiVersion: v1 -metadata: - name: educates-installer - namespace: educates-installer ---- -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRoleBinding -metadata: - name: educates-installer -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: ClusterRole - name: cluster-admin -subjects: - - kind: ServiceAccount - name: educates-installer - namespace: educates-installer \ No newline at end of file diff --git a/carvel-packages/installer/config/schema.yaml b/carvel-packages/installer/config/schema.yaml deleted file mode 100644 index eeaf4555d..000000000 --- a/carvel-packages/installer/config/schema.yaml +++ /dev/null @@ -1,6 +0,0 @@ -#@data/values-schema ---- -version: latest -imageRegistry: - host: "localhost" - namespace: "" \ No newline at end of file diff --git a/carvel-packages/installer/kind-templates/kind-kyverno.yaml b/carvel-packages/installer/kind-templates/kind-kyverno.yaml deleted file mode 100644 index 7acc881cc..000000000 --- a/carvel-packages/installer/kind-templates/kind-kyverno.yaml +++ /dev/null @@ -1,26 +0,0 @@ -kind: Cluster -apiVersion: kind.x-k8s.io/v1alpha4 -name: test-educates -nodes: -- role: control-plane - kubeadmConfigPatches: - - | - kind: InitConfiguration - nodeRegistration: - kubeletExtraArgs: - node-labels: "ingress-ready=true" - extraPortMappings: - - containerPort: 80 - listenAddress: 192.168.50.50 - hostPort: 80 - protocol: TCP - - containerPort: 443 - listenAddress: 192.168.50.50 - hostPort: 443 - protocol: TCP -containerdConfigPatches: -- |- - [plugins."io.containerd.grpc.v1.cri".registry.mirrors."localhost:5001"] - endpoint = ["http://educates-registry:5000"] - [plugins."io.containerd.grpc.v1.cri".registry.mirrors."registry.default.svc.cluster.local"] - endpoint = ["http://educates-registry:5000"] diff --git a/carvel-packages/installer/kind-templates/kind-pod-security-policies.yaml b/carvel-packages/installer/kind-templates/kind-pod-security-policies.yaml deleted file mode 100644 index b4d9def11..000000000 --- a/carvel-packages/installer/kind-templates/kind-pod-security-policies.yaml +++ /dev/null @@ -1,32 +0,0 @@ -kind: Cluster -apiVersion: kind.x-k8s.io/v1alpha4 -nodes: - - role: control-plane - kubeadmConfigPatches: - - | - kind: InitConfiguration - nodeRegistration: - kubeletExtraArgs: - node-labels: "ingress-ready=true" - - | - kind: ClusterConfiguration - metadata: - name: config - apiServer: - extraArgs: - enable-admission-plugins: PodSecurityPolicy - extraPortMappings: - - containerPort: 80 - listenAddress: 192.168.50.50 - hostPort: 80 - protocol: TCP - - containerPort: 443 - listenAddress: 192.168.50.50 - hostPort: 443 - protocol: TCP -containerdConfigPatches: - - |- - [plugins."io.containerd.grpc.v1.cri".registry.mirrors."localhost:5001"] - endpoint = ["http://educates-registry:5000"] - [plugins."io.containerd.grpc.v1.cri".registry.mirrors."registry.default.svc.cluster.local"] - endpoint = ["http://educates-registry:5000"] diff --git a/carvel-packages/installer/kind-templates/kind-pod-security-standards.yaml b/carvel-packages/installer/kind-templates/kind-pod-security-standards.yaml deleted file mode 100644 index 69cc1b1f1..000000000 --- a/carvel-packages/installer/kind-templates/kind-pod-security-standards.yaml +++ /dev/null @@ -1,27 +0,0 @@ -kind: Cluster -apiVersion: kind.x-k8s.io/v1alpha4 -nodes: - - role: control-plane - kubeadmConfigPatches: - - | - kind: InitConfiguration - nodeRegistration: - kubeletExtraArgs: - node-labels: "ingress-ready=true" - extraPortMappings: - - containerPort: 80 - listenAddress: 192.168.50.50 - hostPort: 80 - protocol: TCP - - containerPort: 443 - listenAddress: 192.168.50.50 - hostPort: 443 - protocol: TCP -containerdConfigPatches: - - |- - [plugins."io.containerd.grpc.v1.cri".registry.mirrors."localhost:5001"] - endpoint = ["http://educates-registry:5000"] - [plugins."io.containerd.grpc.v1.cri".registry.mirrors."registry.default.svc.cluster.local"] - endpoint = ["http://educates-registry:5000"] -featureGates: - PodSecurity: true diff --git a/carvel-packages/installer/scenarios/README.md b/carvel-packages/installer/scenarios/README.md deleted file mode 100644 index 55a03156d..000000000 --- a/carvel-packages/installer/scenarios/README.md +++ /dev/null @@ -1,39 +0,0 @@ -# Scenarios - -There's some scenarios we want to cover and test. We can print the list of scenarios and the -test file by executing: - -``` -./test-scenarios.sh --help -``` - -We can run the scenarios by executing: - -``` -./test-scenarios.sh -``` - -If you want to see the processed config generated by each scenario: - -``` -./test-scenarios.sh --debug -``` - -If you want to see things `TODO` for an scenario: - -``` -./test-scenarios.sh --todo -``` - -**NOTE** Take into account that values are mock, so if you really want to test these scenarios into a cluster -make a copy and alter the values to your needs. - -**NOTE** You will need to have a cluster to test on the cluster - -## Scenarios implemented - -To get a list of implemented scenarios and their description run: - -``` -./test-scenarios.sh -h -``` diff --git a/carvel-packages/installer/scenarios/custom/test-custom-scenario-1/description.md b/carvel-packages/installer/scenarios/custom/test-custom-scenario-1/description.md deleted file mode 100644 index 8221c016d..000000000 --- a/carvel-packages/installer/scenarios/custom/test-custom-scenario-1/description.md +++ /dev/null @@ -1,4 +0,0 @@ -kind using provided domain and educates config with custom configuration -In this sccenario we provide some educates global config and not the one in the clusterPackages -Because for custom, only the configuration in clusterPackages is used, all `educates` global configuration -should be discarded. diff --git a/carvel-packages/installer/scenarios/custom/test-custom-scenario-1/expected.yaml b/carvel-packages/installer/scenarios/custom/test-custom-scenario-1/expected.yaml deleted file mode 100644 index ed9abc106..000000000 --- a/carvel-packages/installer/scenarios/custom/test-custom-scenario-1/expected.yaml +++ /dev/null @@ -1,25 +0,0 @@ -clusterPackages: - contour: - enabled: true - settings: {} - cert-manager: - enabled: true - settings: - serviceaccount: - annotations: - cert-manager.custom: "true" - external-dns: - enabled: false - settings: {} - certs: - enabled: false - settings: {} - kyverno: - enabled: false - settings: {} - kapp-controller: - enabled: false - settings: {} - educates: - enabled: true - settings: {} diff --git a/carvel-packages/installer/scenarios/custom/test-custom-scenario-1/values.yaml b/carvel-packages/installer/scenarios/custom/test-custom-scenario-1/values.yaml deleted file mode 100644 index f5ff87163..000000000 --- a/carvel-packages/installer/scenarios/custom/test-custom-scenario-1/values.yaml +++ /dev/null @@ -1,39 +0,0 @@ -clusterPackages: - contour: - enabled: true - settings: {} - cert-manager: - enabled: true - settings: - serviceaccount: - annotations: - cert-manager.custom: "true" - external-dns: - enabled: false - settings: - infraProvider: gcp - gcp: - args: - project: "PROJECT_ID" - certs: - enabled: false - settings: {} - kyverno: - enabled: false - settings: {} - kapp-controller: - enabled: false - settings: {} - educates: - enabled: true - settings: {} -clusterInfrastructure: - provider: custom -clusterIngress: - domain: "educates.example.com" -clusterSecurity: - policyEngine: none -workshopSecurity: - rulesEngine: none -sessionCookies: - domain: "educates.example.com" diff --git a/carvel-packages/installer/scenarios/custom/test-custom-scenario-2/description.md b/carvel-packages/installer/scenarios/custom/test-custom-scenario-2/description.md deleted file mode 100644 index f2719ccb0..000000000 --- a/carvel-packages/installer/scenarios/custom/test-custom-scenario-2/description.md +++ /dev/null @@ -1,3 +0,0 @@ -kind using provided domain with custom configuration -In this scenario we don't use any global `educates` config, but the one in the clusterPackages. -This configuration should be respected diff --git a/carvel-packages/installer/scenarios/custom/test-custom-scenario-2/expected.yaml b/carvel-packages/installer/scenarios/custom/test-custom-scenario-2/expected.yaml deleted file mode 100644 index ca3f57095..000000000 --- a/carvel-packages/installer/scenarios/custom/test-custom-scenario-2/expected.yaml +++ /dev/null @@ -1,29 +0,0 @@ -clusterPackages: - contour: - enabled: true - settings: {} - cert-manager: - enabled: true - settings: - serviceaccount: - annotations: - cert-manager.custom: "true" - external-dns: - enabled: false - settings: {} - certs: - enabled: false - settings: {} - kyverno: - enabled: true - settings: {} - kapp-controller: - enabled: false - settings: {} - educates: - enabled: true - settings: - clusterIngress: - domain: educates.example.com - sessionCookies: - domain: educates.example.com diff --git a/carvel-packages/installer/scenarios/custom/test-custom-scenario-2/values.yaml b/carvel-packages/installer/scenarios/custom/test-custom-scenario-2/values.yaml deleted file mode 100644 index e147ebf42..000000000 --- a/carvel-packages/installer/scenarios/custom/test-custom-scenario-2/values.yaml +++ /dev/null @@ -1,35 +0,0 @@ -clusterPackages: - contour: - enabled: true - settings: {} - cert-manager: - enabled: true - settings: - serviceaccount: - annotations: - cert-manager.custom: "true" - external-dns: - enabled: false - settings: - infraProvider: gcp - gcp: - args: - project: "PROJECT_ID" - certs: - enabled: false - settings: {} - kyverno: - enabled: true - settings: {} - kapp-controller: - enabled: false - settings: {} - educates: - enabled: true - settings: - clusterIngress: - domain: "educates.example.com" - sessionCookies: - domain: "educates.example.com" -clusterInfrastructure: - provider: "custom" diff --git a/carvel-packages/installer/scenarios/custom/test-custom-scenario-3/description.md b/carvel-packages/installer/scenarios/custom/test-custom-scenario-3/description.md deleted file mode 100644 index 01a89ff15..000000000 --- a/carvel-packages/installer/scenarios/custom/test-custom-scenario-3/description.md +++ /dev/null @@ -1,4 +0,0 @@ -kind using provided domain with custom configuration -In this scenario we don't use any global educates config, but the one in the clusterPackages. -We do not provide config for `kapp-controller` and `certs` so these packages will be `disabled` in -generated config. All the other `clusterPackages` configuration will be respected. diff --git a/carvel-packages/installer/scenarios/custom/test-custom-scenario-3/expected.yaml b/carvel-packages/installer/scenarios/custom/test-custom-scenario-3/expected.yaml deleted file mode 100644 index 1676ca2be..000000000 --- a/carvel-packages/installer/scenarios/custom/test-custom-scenario-3/expected.yaml +++ /dev/null @@ -1,32 +0,0 @@ -clusterPackages: - contour: - enabled: true - settings: - infraProvider: custom - contour: - replicas: 10 - cert-manager: - enabled: true - settings: - serviceaccount: - annotations: - cert-manager.custom: "true" - external-dns: - enabled: false - settings: {} - certs: - enabled: false - settings: {} - kyverno: - enabled: true - settings: {} - kapp-controller: - enabled: false - settings: {} - educates: - enabled: true - settings: - clusterIngress: - domain: educates.example.com - sessionCookies: - domain: educates.example.com diff --git a/carvel-packages/installer/scenarios/custom/test-custom-scenario-3/values.yaml b/carvel-packages/installer/scenarios/custom/test-custom-scenario-3/values.yaml deleted file mode 100644 index 146885467..000000000 --- a/carvel-packages/installer/scenarios/custom/test-custom-scenario-3/values.yaml +++ /dev/null @@ -1,32 +0,0 @@ -clusterPackages: - contour: - enabled: true - settings: - infraProvider: custom - contour: - replicas: 10 - cert-manager: - enabled: true - settings: - serviceaccount: - annotations: - cert-manager.custom: "true" - external-dns: - enabled: false - settings: - infraProvider: gcp - gcp: - args: - project: "PROJECT_ID" - kyverno: - enabled: true - settings: {} - educates: - enabled: true - settings: - clusterIngress: - domain: "educates.example.com" - sessionCookies: - domain: "educates.example.com" -clusterInfrastructure: - provider: "custom" diff --git a/carvel-packages/installer/scenarios/custom/test-custom-scenario-4/description.md b/carvel-packages/installer/scenarios/custom/test-custom-scenario-4/description.md deleted file mode 100644 index 618d93f1b..000000000 --- a/carvel-packages/installer/scenarios/custom/test-custom-scenario-4/description.md +++ /dev/null @@ -1,5 +0,0 @@ -kind using provided domain with custom configuration -In this scenario we don't use any global educates config, but the one in the clusterPackages. -We do not provide config for `kapp-controller` and `certs` so these packages will be `disabled` in -generated config. All the other `clusterPackages` configuration will be respected. -We also provide imageVersions configuration that should be kept. diff --git a/carvel-packages/installer/scenarios/custom/test-custom-scenario-4/expected.yaml b/carvel-packages/installer/scenarios/custom/test-custom-scenario-4/expected.yaml deleted file mode 100644 index 6d8e01d9f..000000000 --- a/carvel-packages/installer/scenarios/custom/test-custom-scenario-4/expected.yaml +++ /dev/null @@ -1,77 +0,0 @@ -clusterPackages: - contour: - enabled: true - settings: - infraProvider: custom - contour: - replicas: 10 - cert-manager: - enabled: true - settings: - serviceaccount: - annotations: - cert-manager.custom: "true" - external-dns: - enabled: false - settings: {} - certs: - enabled: false - settings: {} - kyverno: - enabled: true - settings: {} - kapp-controller: - enabled: false - settings: {} - educates: - enabled: true - settings: - clusterIngress: - domain: educates.example.com - imageVersions: - - image: ghcr.io/educates/educates-session-manager:3.1.0 - name: session-manager - - image: ghcr.io/educates/educates-training-portal:3.1.0 - name: training-portal - - image: ghcr.io/educates/educates-docker-registry:3.1.0 - name: docker-registry - - image: ghcr.io/educates/educates-pause-container:3.1.0 - name: pause-container - - image: ghcr.io/educates/educates-base-environment:3.1.0 - name: base-environment - - image: ghcr.io/educates/educates-jdk8-environment:3.1.0 - name: jdk8-environment - - image: ghcr.io/educates/educates-jdk11-environment:3.1.0 - name: jdk11-environment - - image: ghcr.io/educates/educates-jdk17-environment:3.1.0 - name: jdk17-environment - - image: ghcr.io/educates/educates-jdk21-environment:3.1.0 - name: jdk21-environment - - image: ghcr.io/educates/educates-conda-environment:3.1.0 - name: conda-environment - - image: ghcr.io/educates/educates-secrets-manager:3.1.0 - name: secrets-manager - - image: ghcr.io/educates/educates-tunnel-manager:3.1.0 - name: tunnel-manager - - image: ghcr.io/educates/educates-image-cache:3.1.0 - name: image-cache - - image: ghcr.io/educates/educates-assets-server:3.1.0 - name: assets-server - - image: ghcr.io/educates/educates-lookup-service:3.1.0 - name: lookup-service - - image: debian:sid-20230502-slim - name: debian-base-image - - image: docker:20.10.18-dind - name: docker-in-docker - - name: loftsh-kubernetes-v1.31 - image: "ghcr.io/loft-sh/kubernetes:v1.31.1" - - name: loftsh-kubernetes-v1.32 - image: "ghcr.io/loft-sh/kubernetes:v1.32.1" - - name: loftsh-kubernetes-v1.33 - image: "ghcr.io/loft-sh/kubernetes:v1.33.4" - - name: loftsh-kubernetes-v1.34 - image: "ghcr.io/loft-sh/kubernetes:v1.34.0" - - name: loftsh-vcluster - image: "ghcr.io/loft-sh/vcluster-oss:0.30.2" - sessionCookies: - domain: educates.example.com diff --git a/carvel-packages/installer/scenarios/custom/test-custom-scenario-4/values.yaml b/carvel-packages/installer/scenarios/custom/test-custom-scenario-4/values.yaml deleted file mode 100644 index 750bd233f..000000000 --- a/carvel-packages/installer/scenarios/custom/test-custom-scenario-4/values.yaml +++ /dev/null @@ -1,77 +0,0 @@ -clusterPackages: - contour: - enabled: true - settings: - infraProvider: custom - contour: - replicas: 10 - cert-manager: - enabled: true - settings: - serviceaccount: - annotations: - cert-manager.custom: "true" - external-dns: - enabled: false - settings: - infraProvider: gcp - gcp: - args: - project: "PROJECT_ID" - kyverno: - enabled: true - settings: {} - educates: - enabled: true - settings: - clusterIngress: - domain: "educates.example.com" - sessionCookies: - domain: "educates.example.com" -clusterInfrastructure: - provider: "custom" -imageVersions: -- name: session-manager - image: ghcr.io/educates/educates-session-manager:3.1.0 -- name: training-portal - image: ghcr.io/educates/educates-training-portal:3.1.0 -- name: docker-registry - image: ghcr.io/educates/educates-docker-registry:3.1.0 -- name: pause-container - image: ghcr.io/educates/educates-pause-container:3.1.0 -- name: base-environment - image: ghcr.io/educates/educates-base-environment:3.1.0 -- name: jdk8-environment - image: ghcr.io/educates/educates-jdk8-environment:3.1.0 -- name: jdk11-environment - image: ghcr.io/educates/educates-jdk11-environment:3.1.0 -- name: jdk17-environment - image: ghcr.io/educates/educates-jdk17-environment:3.1.0 -- name: jdk21-environment - image: ghcr.io/educates/educates-jdk21-environment:3.1.0 -- name: conda-environment - image: ghcr.io/educates/educates-conda-environment:3.1.0 -- name: secrets-manager - image: ghcr.io/educates/educates-secrets-manager:3.1.0 -- name: tunnel-manager - image: ghcr.io/educates/educates-tunnel-manager:3.1.0 -- name: image-cache - image: ghcr.io/educates/educates-image-cache:3.1.0 -- name: assets-server - image: ghcr.io/educates/educates-assets-server:3.1.0 -- name: lookup-service - image: ghcr.io/educates/educates-lookup-service:3.1.0 -- name: debian-base-image - image: debian:sid-20230502-slim -- name: docker-in-docker - image: docker:20.10.18-dind # 27.5.1-dind -- name: loftsh-kubernetes-v1.31 - image: "ghcr.io/loft-sh/kubernetes:v1.31.1" -- name: loftsh-kubernetes-v1.32 - image: "ghcr.io/loft-sh/kubernetes:v1.32.1" -- name: loftsh-kubernetes-v1.33 - image: "ghcr.io/loft-sh/kubernetes:v1.33.4" -- name: loftsh-kubernetes-v1.34 - image: "ghcr.io/loft-sh/kubernetes:v1.34.0" -- name: loftsh-vcluster - image: "ghcr.io/loft-sh/vcluster-oss:0.30.2" \ No newline at end of file diff --git a/carvel-packages/installer/scenarios/eks/test-eks-scenario-01/description.md b/carvel-packages/installer/scenarios/eks/test-eks-scenario-01/description.md deleted file mode 100644 index 8d52e0166..000000000 --- a/carvel-packages/installer/scenarios/eks/test-eks-scenario-01/description.md +++ /dev/null @@ -1 +0,0 @@ -eks integrating with Route53 to create DNS records and Let's Encrypt to generate wildcard diff --git a/carvel-packages/installer/scenarios/eks/test-eks-scenario-01/expected.yaml b/carvel-packages/installer/scenarios/eks/test-eks-scenario-01/expected.yaml deleted file mode 100644 index ef7e739d1..000000000 --- a/carvel-packages/installer/scenarios/eks/test-eks-scenario-01/expected.yaml +++ /dev/null @@ -1,59 +0,0 @@ -clusterPackages: - contour: - enabled: true - settings: - infraProvider: aws - configFileContents: - defaultHttpVersions: - - HTTP/1.1 - service: - type: LoadBalancer - externaldns: - domains: - - educates.example.com - cert-manager: - enabled: true - settings: - serviceaccount: - annotations: - eks.amazonaws.com/role-arn: arn:aws:iam::123456789012:role/cert-manager - external-dns: - enabled: true - settings: - infraProvider: aws - serviceaccount: - annotations: - eks.amazonaws.com/role-arn: arn:aws:iam::123456789012:role/external-dns - aws: - args: - domain_filter: example.com - policy: sync - txt_owner_id: educates.example.com - certs: - enabled: true - settings: - certProvider: acme-aws - domains: - - educates.example.com - acme: - aws: - certs: - region: eu-west-1 - kyverno: - enabled: true - settings: {} - kapp-controller: - enabled: false - settings: {} - educates: - enabled: true - settings: - clusterIngress: - tlsCertificateRef: - namespace: projectcontour - name: educateswildcard - domain: educates.example.com - clusterSecurity: - policyEngine: kyverno - workshopSecurity: - rulesEngine: kyverno diff --git a/carvel-packages/installer/scenarios/eks/test-eks-scenario-01/values.yaml b/carvel-packages/installer/scenarios/eks/test-eks-scenario-01/values.yaml deleted file mode 100644 index 708276843..000000000 --- a/carvel-packages/installer/scenarios/eks/test-eks-scenario-01/values.yaml +++ /dev/null @@ -1,13 +0,0 @@ -clusterInfrastructure: - provider: "eks" - aws: - region: "eu-west-1" - route53: - hostedZone: "example.com" - irsaRoles: - external-dns: "arn:aws:iam::123456789012:role/external-dns" - cert-manager: "arn:aws:iam::123456789012:role/cert-manager" -clusterSecurity: - policyEngine: "kyverno" -clusterIngress: - domain: "educates.example.com" diff --git a/carvel-packages/installer/scenarios/eks/test-eks-scenario-01b/description.md b/carvel-packages/installer/scenarios/eks/test-eks-scenario-01b/description.md deleted file mode 100644 index c805144ca..000000000 --- a/carvel-packages/installer/scenarios/eks/test-eks-scenario-01b/description.md +++ /dev/null @@ -1,2 +0,0 @@ -eks integrating with Route53 to create DNS records and Let's Encrypt to generate wildcard -No specific Route53 hostedZone provided, hence, using clusterIngress.domain diff --git a/carvel-packages/installer/scenarios/eks/test-eks-scenario-01b/expected.yaml b/carvel-packages/installer/scenarios/eks/test-eks-scenario-01b/expected.yaml deleted file mode 100644 index 00fffb51d..000000000 --- a/carvel-packages/installer/scenarios/eks/test-eks-scenario-01b/expected.yaml +++ /dev/null @@ -1,59 +0,0 @@ -clusterPackages: - contour: - enabled: true - settings: - infraProvider: aws - configFileContents: - defaultHttpVersions: - - HTTP/1.1 - service: - type: LoadBalancer - externaldns: - domains: - - educates.example.com - cert-manager: - enabled: true - settings: - serviceaccount: - annotations: - eks.amazonaws.com/role-arn: arn:aws:iam::123456789012:role/cert-manager - external-dns: - enabled: true - settings: - infraProvider: aws - serviceaccount: - annotations: - eks.amazonaws.com/role-arn: arn:aws:iam::123456789012:role/external-dns - aws: - args: - domain_filter: educates.example.com - policy: sync - txt_owner_id: educates.example.com - certs: - enabled: true - settings: - certProvider: acme-aws - domains: - - educates.example.com - acme: - aws: - certs: - region: eu-west-1 - kyverno: - enabled: true - settings: {} - kapp-controller: - enabled: false - settings: {} - educates: - enabled: true - settings: - clusterIngress: - tlsCertificateRef: - namespace: projectcontour - name: educateswildcard - domain: educates.example.com - clusterSecurity: - policyEngine: kyverno - workshopSecurity: - rulesEngine: kyverno diff --git a/carvel-packages/installer/scenarios/eks/test-eks-scenario-01b/values.yaml b/carvel-packages/installer/scenarios/eks/test-eks-scenario-01b/values.yaml deleted file mode 100644 index c30405eb1..000000000 --- a/carvel-packages/installer/scenarios/eks/test-eks-scenario-01b/values.yaml +++ /dev/null @@ -1,11 +0,0 @@ -clusterInfrastructure: - provider: "eks" - aws: - region: "eu-west-1" - irsaRoles: - external-dns: "arn:aws:iam::123456789012:role/external-dns" - cert-manager: "arn:aws:iam::123456789012:role/cert-manager" -clusterSecurity: - policyEngine: "kyverno" -clusterIngress: - domain: "educates.example.com" diff --git a/carvel-packages/installer/scenarios/eks/test-eks-scenario-02/description.md b/carvel-packages/installer/scenarios/eks/test-eks-scenario-02/description.md deleted file mode 100644 index e9edfadcc..000000000 --- a/carvel-packages/installer/scenarios/eks/test-eks-scenario-02/description.md +++ /dev/null @@ -1,2 +0,0 @@ -eks integrating with Route53 to create DNS records and Let's Encrypt to generate wildcard -We provide some custom configuration in clusterPackages that should be discarded. diff --git a/carvel-packages/installer/scenarios/eks/test-eks-scenario-02/expected.yaml b/carvel-packages/installer/scenarios/eks/test-eks-scenario-02/expected.yaml deleted file mode 100644 index ef7e739d1..000000000 --- a/carvel-packages/installer/scenarios/eks/test-eks-scenario-02/expected.yaml +++ /dev/null @@ -1,59 +0,0 @@ -clusterPackages: - contour: - enabled: true - settings: - infraProvider: aws - configFileContents: - defaultHttpVersions: - - HTTP/1.1 - service: - type: LoadBalancer - externaldns: - domains: - - educates.example.com - cert-manager: - enabled: true - settings: - serviceaccount: - annotations: - eks.amazonaws.com/role-arn: arn:aws:iam::123456789012:role/cert-manager - external-dns: - enabled: true - settings: - infraProvider: aws - serviceaccount: - annotations: - eks.amazonaws.com/role-arn: arn:aws:iam::123456789012:role/external-dns - aws: - args: - domain_filter: example.com - policy: sync - txt_owner_id: educates.example.com - certs: - enabled: true - settings: - certProvider: acme-aws - domains: - - educates.example.com - acme: - aws: - certs: - region: eu-west-1 - kyverno: - enabled: true - settings: {} - kapp-controller: - enabled: false - settings: {} - educates: - enabled: true - settings: - clusterIngress: - tlsCertificateRef: - namespace: projectcontour - name: educateswildcard - domain: educates.example.com - clusterSecurity: - policyEngine: kyverno - workshopSecurity: - rulesEngine: kyverno diff --git a/carvel-packages/installer/scenarios/eks/test-eks-scenario-02/values.yaml b/carvel-packages/installer/scenarios/eks/test-eks-scenario-02/values.yaml deleted file mode 100644 index 2d60041cd..000000000 --- a/carvel-packages/installer/scenarios/eks/test-eks-scenario-02/values.yaml +++ /dev/null @@ -1,53 +0,0 @@ -clusterInfrastructure: - provider: "eks" - aws: - region: "eu-west-1" - route53: - hostedZone: "example.com" - irsaRoles: - external-dns: "arn:aws:iam::123456789012:role/external-dns" - cert-manager: "arn:aws:iam::123456789012:role/cert-manager" -clusterPackages: - contour: - enabled: true - settings: - infraProvider: "aws" - configFileContents: - defaultHttpVersions: - - "HTTP/2" - service: - type: "ClsuterIP" - externaldns: - domains: - - "ERROR.educates.example.com" - cert-manager: - enabled: true - settings: - serviceaccount: - annotations: - eks.amazonaws.com/role-arn: "ERROR_role/cert-manager" - external-dns: - enabled: true - settings: - infraProvider: "aws" - serviceaccount: - annotations: - eks.amazonaws.com/role-arn: "ERROR_role/external-dns" - aws: - args: - domain_filter: "ERROR.educates.example.com" - txt_owner_id: "ERROR.educates" - certs: - enabled: true - settings: - certProvider: "acme" - domains: - - "ERROR.educates.example.com" - acme: - aws: - certs: - region: "eu-west-1" -clusterSecurity: - policyEngine: "kyverno" -clusterIngress: - domain: "educates.example.com" diff --git a/carvel-packages/installer/scenarios/eks/test-eks-scenario-03/description.md b/carvel-packages/installer/scenarios/eks/test-eks-scenario-03/description.md deleted file mode 100644 index e27d33b47..000000000 --- a/carvel-packages/installer/scenarios/eks/test-eks-scenario-03/description.md +++ /dev/null @@ -1,2 +0,0 @@ -eks integrating with Route53 to create DNS records and Let's Encrypt to generate wildcard -We disable some packages. diff --git a/carvel-packages/installer/scenarios/eks/test-eks-scenario-03/expected.yaml b/carvel-packages/installer/scenarios/eks/test-eks-scenario-03/expected.yaml deleted file mode 100644 index 0adf75f6f..000000000 --- a/carvel-packages/installer/scenarios/eks/test-eks-scenario-03/expected.yaml +++ /dev/null @@ -1,31 +0,0 @@ -clusterPackages: - contour: - enabled: false - settings: {} - cert-manager: - enabled: false - settings: {} - external-dns: - enabled: false - settings: {} - certs: - enabled: false - settings: {} - kyverno: - enabled: true - settings: {} - kapp-controller: - enabled: false - settings: {} - educates: - enabled: true - settings: - clusterIngress: - tlsCertificateRef: - namespace: projectcontour - name: educateswildcard - domain: educates.example.com - clusterSecurity: - policyEngine: kyverno - workshopSecurity: - rulesEngine: kyverno diff --git a/carvel-packages/installer/scenarios/eks/test-eks-scenario-03/values.yaml b/carvel-packages/installer/scenarios/eks/test-eks-scenario-03/values.yaml deleted file mode 100644 index 1483d2216..000000000 --- a/carvel-packages/installer/scenarios/eks/test-eks-scenario-03/values.yaml +++ /dev/null @@ -1,22 +0,0 @@ -clusterInfrastructure: - provider: "eks" - aws: - region: "eu-west-1" - route53: - hostedZone: "example.com" - irsaRoles: - external-dns: "arn:aws:iam::123456789012:role/external-dns" - cert-manager: "arn:aws:iam::123456789012:role/cert-manager" -clusterPackages: - contour: - enabled: false - cert-manager: - enabled: false - external-dns: - enabled: false - certs: - enabled: false -clusterSecurity: - policyEngine: "kyverno" -clusterIngress: - domain: "educates.example.com" diff --git a/carvel-packages/installer/scenarios/eks/test-eks-scenario-04/description.md b/carvel-packages/installer/scenarios/eks/test-eks-scenario-04/description.md deleted file mode 100644 index cfd1fb92d..000000000 --- a/carvel-packages/installer/scenarios/eks/test-eks-scenario-04/description.md +++ /dev/null @@ -1,2 +0,0 @@ -eks integrating with Route53 to create DNS records and Let's Encrypt to generate wildcard -We enable LookupService diff --git a/carvel-packages/installer/scenarios/eks/test-eks-scenario-04/expected.yaml b/carvel-packages/installer/scenarios/eks/test-eks-scenario-04/expected.yaml deleted file mode 100644 index b51e235a5..000000000 --- a/carvel-packages/installer/scenarios/eks/test-eks-scenario-04/expected.yaml +++ /dev/null @@ -1,61 +0,0 @@ -clusterPackages: - contour: - enabled: true - settings: - infraProvider: aws - configFileContents: - defaultHttpVersions: - - HTTP/1.1 - service: - type: LoadBalancer - externaldns: - domains: - - educates.example.com - cert-manager: - enabled: true - settings: - serviceaccount: - annotations: - eks.amazonaws.com/role-arn: arn:aws:iam::123456789012:role/cert-manager - external-dns: - enabled: true - settings: - infraProvider: aws - serviceaccount: - annotations: - eks.amazonaws.com/role-arn: arn:aws:iam::123456789012:role/external-dns - aws: - args: - domain_filter: example.com - policy: sync - txt_owner_id: educates.example.com - certs: - enabled: true - settings: - certProvider: acme-aws - domains: - - educates.example.com - acme: - aws: - certs: - region: eu-west-1 - kyverno: - enabled: true - settings: {} - kapp-controller: - enabled: false - settings: {} - educates: - enabled: true - settings: - clusterIngress: - tlsCertificateRef: - namespace: projectcontour - name: educateswildcard - domain: educates.example.com - clusterSecurity: - policyEngine: kyverno - workshopSecurity: - rulesEngine: kyverno - lookupService: - enabled: true diff --git a/carvel-packages/installer/scenarios/eks/test-eks-scenario-04/values.yaml b/carvel-packages/installer/scenarios/eks/test-eks-scenario-04/values.yaml deleted file mode 100644 index 1d60959b5..000000000 --- a/carvel-packages/installer/scenarios/eks/test-eks-scenario-04/values.yaml +++ /dev/null @@ -1,15 +0,0 @@ -clusterInfrastructure: - provider: "eks" - aws: - region: "eu-west-1" - route53: - hostedZone: "example.com" - irsaRoles: - external-dns: "arn:aws:iam::123456789012:role/external-dns" - cert-manager: "arn:aws:iam::123456789012:role/cert-manager" -clusterSecurity: - policyEngine: "kyverno" -clusterIngress: - domain: "educates.example.com" -lookupService: - enabled: true diff --git a/carvel-packages/installer/scenarios/eks/test-eks-scenario-04b/description.md b/carvel-packages/installer/scenarios/eks/test-eks-scenario-04b/description.md deleted file mode 100644 index 16e4b3112..000000000 --- a/carvel-packages/installer/scenarios/eks/test-eks-scenario-04b/description.md +++ /dev/null @@ -1,2 +0,0 @@ -eks integrating with Route53 to create DNS records and Let's Encrypt to generate wildcard -We enable LookupService with alternate ingressPrefix diff --git a/carvel-packages/installer/scenarios/eks/test-eks-scenario-04b/expected.yaml b/carvel-packages/installer/scenarios/eks/test-eks-scenario-04b/expected.yaml deleted file mode 100644 index 8b620bf3e..000000000 --- a/carvel-packages/installer/scenarios/eks/test-eks-scenario-04b/expected.yaml +++ /dev/null @@ -1,62 +0,0 @@ -clusterPackages: - contour: - enabled: true - settings: - infraProvider: aws - configFileContents: - defaultHttpVersions: - - HTTP/1.1 - service: - type: LoadBalancer - externaldns: - domains: - - educates.example.com - cert-manager: - enabled: true - settings: - serviceaccount: - annotations: - eks.amazonaws.com/role-arn: arn:aws:iam::123456789012:role/cert-manager - external-dns: - enabled: true - settings: - infraProvider: aws - serviceaccount: - annotations: - eks.amazonaws.com/role-arn: arn:aws:iam::123456789012:role/external-dns - aws: - args: - domain_filter: example.com - policy: sync - txt_owner_id: educates.example.com - certs: - enabled: true - settings: - certProvider: acme-aws - domains: - - educates.example.com - acme: - aws: - certs: - region: eu-west-1 - kyverno: - enabled: true - settings: {} - kapp-controller: - enabled: false - settings: {} - educates: - enabled: true - settings: - clusterIngress: - tlsCertificateRef: - namespace: projectcontour - name: educateswildcard - domain: educates.example.com - clusterSecurity: - policyEngine: kyverno - workshopSecurity: - rulesEngine: kyverno - lookupService: - enabled: true - ingressPrefix: ALTERNATE diff --git a/carvel-packages/installer/scenarios/eks/test-eks-scenario-04b/values.yaml b/carvel-packages/installer/scenarios/eks/test-eks-scenario-04b/values.yaml deleted file mode 100644 index e5a4dc714..000000000 --- a/carvel-packages/installer/scenarios/eks/test-eks-scenario-04b/values.yaml +++ /dev/null @@ -1,16 +0,0 @@ -clusterInfrastructure: - provider: "eks" - aws: - region: "eu-west-1" - route53: - hostedZone: "example.com" - irsaRoles: - external-dns: "arn:aws:iam::123456789012:role/external-dns" - cert-manager: "arn:aws:iam::123456789012:role/cert-manager" -clusterSecurity: - policyEngine: "kyverno" -clusterIngress: - domain: "educates.example.com" -lookupService: - enabled: true - ingressPrefix: ALTERNATE diff --git a/carvel-packages/installer/scenarios/eks/test-eks-scenario-04c/description.md b/carvel-packages/installer/scenarios/eks/test-eks-scenario-04c/description.md deleted file mode 100644 index f3c38bb69..000000000 --- a/carvel-packages/installer/scenarios/eks/test-eks-scenario-04c/description.md +++ /dev/null @@ -1,3 +0,0 @@ -eks integrating with Route53 to create DNS records and Let's Encrypt to generate wildcard -We enable LookupService with alternate ingressPrefix globally -We enable LookupService in clusterPackages with other ingressPrefix that should be discarded diff --git a/carvel-packages/installer/scenarios/eks/test-eks-scenario-04c/expected.yaml b/carvel-packages/installer/scenarios/eks/test-eks-scenario-04c/expected.yaml deleted file mode 100644 index 8b620bf3e..000000000 --- a/carvel-packages/installer/scenarios/eks/test-eks-scenario-04c/expected.yaml +++ /dev/null @@ -1,62 +0,0 @@ -clusterPackages: - contour: - enabled: true - settings: - infraProvider: aws - configFileContents: - defaultHttpVersions: - - HTTP/1.1 - service: - type: LoadBalancer - externaldns: - domains: - - educates.example.com - cert-manager: - enabled: true - settings: - serviceaccount: - annotations: - eks.amazonaws.com/role-arn: arn:aws:iam::123456789012:role/cert-manager - external-dns: - enabled: true - settings: - infraProvider: aws - serviceaccount: - annotations: - eks.amazonaws.com/role-arn: arn:aws:iam::123456789012:role/external-dns - aws: - args: - domain_filter: example.com - policy: sync - txt_owner_id: educates.example.com - certs: - enabled: true - settings: - certProvider: acme-aws - domains: - - educates.example.com - acme: - aws: - certs: - region: eu-west-1 - kyverno: - enabled: true - settings: {} - kapp-controller: - enabled: false - settings: {} - educates: - enabled: true - settings: - clusterIngress: - tlsCertificateRef: - namespace: projectcontour - name: educateswildcard - domain: educates.example.com - clusterSecurity: - policyEngine: kyverno - workshopSecurity: - rulesEngine: kyverno - lookupService: - enabled: true - ingressPrefix: ALTERNATE diff --git a/carvel-packages/installer/scenarios/eks/test-eks-scenario-04c/values.yaml b/carvel-packages/installer/scenarios/eks/test-eks-scenario-04c/values.yaml deleted file mode 100644 index 8d11157d9..000000000 --- a/carvel-packages/installer/scenarios/eks/test-eks-scenario-04c/values.yaml +++ /dev/null @@ -1,22 +0,0 @@ -clusterInfrastructure: - provider: "eks" - aws: - region: "eu-west-1" - route53: - hostedZone: "example.com" - irsaRoles: - external-dns: "arn:aws:iam::123456789012:role/external-dns" - cert-manager: "arn:aws:iam::123456789012:role/cert-manager" -clusterPackages: - educates: - settings: - lookupService: - enabled: true - ingressPrefix: THIS_NOT -clusterSecurity: - policyEngine: "kyverno" -clusterIngress: - domain: "educates.example.com" -lookupService: - enabled: true - ingressPrefix: ALTERNATE diff --git a/carvel-packages/installer/scenarios/eks/test-eks-scenario-04d/description.md b/carvel-packages/installer/scenarios/eks/test-eks-scenario-04d/description.md deleted file mode 100644 index cf6502638..000000000 --- a/carvel-packages/installer/scenarios/eks/test-eks-scenario-04d/description.md +++ /dev/null @@ -1,3 +0,0 @@ -eks integrating with Route53 to create DNS records and Let's Encrypt to generate wildcard -We enable LookupService with no ingressPrefix -We enable LookupService in clusterPackages with other ingressPrefix that should be REMAIN diff --git a/carvel-packages/installer/scenarios/eks/test-eks-scenario-04d/expected.yaml b/carvel-packages/installer/scenarios/eks/test-eks-scenario-04d/expected.yaml deleted file mode 100644 index 05be1f851..000000000 --- a/carvel-packages/installer/scenarios/eks/test-eks-scenario-04d/expected.yaml +++ /dev/null @@ -1,62 +0,0 @@ -clusterPackages: - contour: - enabled: true - settings: - infraProvider: aws - configFileContents: - defaultHttpVersions: - - HTTP/1.1 - service: - type: LoadBalancer - externaldns: - domains: - - educates.example.com - cert-manager: - enabled: true - settings: - serviceaccount: - annotations: - eks.amazonaws.com/role-arn: arn:aws:iam::123456789012:role/cert-manager - external-dns: - enabled: true - settings: - infraProvider: aws - serviceaccount: - annotations: - eks.amazonaws.com/role-arn: arn:aws:iam::123456789012:role/external-dns - aws: - args: - domain_filter: example.com - policy: sync - txt_owner_id: educates.example.com - certs: - enabled: true - settings: - certProvider: acme-aws - domains: - - educates.example.com - acme: - aws: - certs: - region: eu-west-1 - kyverno: - enabled: true - settings: {} - kapp-controller: - enabled: false - settings: {} - educates: - enabled: true - settings: - clusterIngress: - tlsCertificateRef: - namespace: projectcontour - name: educateswildcard - domain: educates.example.com - clusterSecurity: - policyEngine: kyverno - workshopSecurity: - rulesEngine: kyverno - lookupService: - enabled: true - ingressPrefix: THIS_SHOULD_STAY diff --git a/carvel-packages/installer/scenarios/eks/test-eks-scenario-04d/values.yaml b/carvel-packages/installer/scenarios/eks/test-eks-scenario-04d/values.yaml deleted file mode 100644 index 84b789f21..000000000 --- a/carvel-packages/installer/scenarios/eks/test-eks-scenario-04d/values.yaml +++ /dev/null @@ -1,21 +0,0 @@ -clusterInfrastructure: - provider: "eks" - aws: - region: "eu-west-1" - route53: - hostedZone: "example.com" - irsaRoles: - external-dns: "arn:aws:iam::123456789012:role/external-dns" - cert-manager: "arn:aws:iam::123456789012:role/cert-manager" -clusterPackages: - educates: - settings: - lookupService: - enabled: true - ingressPrefix: THIS_SHOULD_STAY -clusterSecurity: - policyEngine: "kyverno" -clusterIngress: - domain: "educates.example.com" -lookupService: - enabled: true diff --git a/carvel-packages/installer/scenarios/generic/README.md b/carvel-packages/installer/scenarios/generic/README.md deleted file mode 100644 index 8e4271a73..000000000 --- a/carvel-packages/installer/scenarios/generic/README.md +++ /dev/null @@ -1,3 +0,0 @@ -# generic -For generic contour will never be installed, educates can not be skipped and the rest of the packages can be -customised. diff --git a/carvel-packages/installer/scenarios/generic/test-generic-scenario-1/description.md b/carvel-packages/installer/scenarios/generic/test-generic-scenario-1/description.md deleted file mode 100644 index 8cb60ef36..000000000 --- a/carvel-packages/installer/scenarios/generic/test-generic-scenario-1/description.md +++ /dev/null @@ -1 +0,0 @@ -generic configuration with some overrides to see if they are set diff --git a/carvel-packages/installer/scenarios/generic/test-generic-scenario-1/expected.yaml b/carvel-packages/installer/scenarios/generic/test-generic-scenario-1/expected.yaml deleted file mode 100644 index 31cd99df0..000000000 --- a/carvel-packages/installer/scenarios/generic/test-generic-scenario-1/expected.yaml +++ /dev/null @@ -1,35 +0,0 @@ -clusterPackages: - contour: - enabled: false - settings: {} - cert-manager: - enabled: false - settings: {} - external-dns: - enabled: false - settings: {} - certs: - enabled: false - settings: {} - kyverno: - enabled: true - settings: {} - kapp-controller: - enabled: false - settings: {} - educates: - enabled: true - settings: - clusterIngress: - domain: educates.example.com - clusterSecurity: - policyEngine: kyverno - workshopSecurity: - rulesEngine: none - workshopAnalytics: - google: - trackingId: analytics - imagePuller: - enabled: true - prePullImages: - - b \ No newline at end of file diff --git a/carvel-packages/installer/scenarios/generic/test-generic-scenario-1/values.yaml b/carvel-packages/installer/scenarios/generic/test-generic-scenario-1/values.yaml deleted file mode 100644 index 4da98fa52..000000000 --- a/carvel-packages/installer/scenarios/generic/test-generic-scenario-1/values.yaml +++ /dev/null @@ -1,20 +0,0 @@ -clusterInfrastructure: - provider: "generic" -clusterPackages: - educates: - settings: - imagePuller: - enabled: true - prePullImages: - - "a" -imagePuller: - enabled: true - prePullImages: - - "b" -workshopSecurity: - rulesEngine: "none" -workshopAnalytics: - google: - trackingId: "analytics" -clusterIngress: - domain: "educates.example.com" diff --git a/carvel-packages/installer/scenarios/generic/test-generic-scenario-2/description.md b/carvel-packages/installer/scenarios/generic/test-generic-scenario-2/description.md deleted file mode 100644 index 2a2f668a7..000000000 --- a/carvel-packages/installer/scenarios/generic/test-generic-scenario-2/description.md +++ /dev/null @@ -1,3 +0,0 @@ -generic configuration with some overrides to see if they are set. -Since we are adding configuration for contour and this package -can not be enabled or customised, nothing will show for contour diff --git a/carvel-packages/installer/scenarios/generic/test-generic-scenario-2/expected.yaml b/carvel-packages/installer/scenarios/generic/test-generic-scenario-2/expected.yaml deleted file mode 100644 index 31cd99df0..000000000 --- a/carvel-packages/installer/scenarios/generic/test-generic-scenario-2/expected.yaml +++ /dev/null @@ -1,35 +0,0 @@ -clusterPackages: - contour: - enabled: false - settings: {} - cert-manager: - enabled: false - settings: {} - external-dns: - enabled: false - settings: {} - certs: - enabled: false - settings: {} - kyverno: - enabled: true - settings: {} - kapp-controller: - enabled: false - settings: {} - educates: - enabled: true - settings: - clusterIngress: - domain: educates.example.com - clusterSecurity: - policyEngine: kyverno - workshopSecurity: - rulesEngine: none - workshopAnalytics: - google: - trackingId: analytics - imagePuller: - enabled: true - prePullImages: - - b \ No newline at end of file diff --git a/carvel-packages/installer/scenarios/generic/test-generic-scenario-2/values.yaml b/carvel-packages/installer/scenarios/generic/test-generic-scenario-2/values.yaml deleted file mode 100644 index d3c9ee17c..000000000 --- a/carvel-packages/installer/scenarios/generic/test-generic-scenario-2/values.yaml +++ /dev/null @@ -1,24 +0,0 @@ -clusterInfrastructure: - provider: "generic" -clusterPackages: - contour: - enabled: true - settings: - infraProvider: "custom" - educates: - settings: - imagePuller: - enabled: true - prePullImages: - - "a" -imagePuller: - enabled: true - prePullImages: - - "b" -workshopSecurity: - rulesEngine: "none" -workshopAnalytics: - google: - trackingId: "analytics" -clusterIngress: - domain: "educates.example.com" diff --git a/carvel-packages/installer/scenarios/generic/test-generic-scenario-3/description.md b/carvel-packages/installer/scenarios/generic/test-generic-scenario-3/description.md deleted file mode 100644 index 2c29f1790..000000000 --- a/carvel-packages/installer/scenarios/generic/test-generic-scenario-3/description.md +++ /dev/null @@ -1,2 +0,0 @@ -generic configuration with some overrides to see if they are set -We disable kyverno, which is the only configurable package, so we disable. \ No newline at end of file diff --git a/carvel-packages/installer/scenarios/generic/test-generic-scenario-3/expected.yaml b/carvel-packages/installer/scenarios/generic/test-generic-scenario-3/expected.yaml deleted file mode 100644 index 03e183dbf..000000000 --- a/carvel-packages/installer/scenarios/generic/test-generic-scenario-3/expected.yaml +++ /dev/null @@ -1,35 +0,0 @@ -clusterPackages: - contour: - enabled: false - settings: {} - cert-manager: - enabled: false - settings: {} - external-dns: - enabled: false - settings: {} - certs: - enabled: false - settings: {} - kyverno: - enabled: false - settings: {} - kapp-controller: - enabled: false - settings: {} - educates: - enabled: true - settings: - clusterIngress: - domain: educates.example.com - clusterSecurity: - policyEngine: kyverno - workshopSecurity: - rulesEngine: none - workshopAnalytics: - google: - trackingId: analytics - imagePuller: - enabled: true - prePullImages: - - b \ No newline at end of file diff --git a/carvel-packages/installer/scenarios/generic/test-generic-scenario-3/values.yaml b/carvel-packages/installer/scenarios/generic/test-generic-scenario-3/values.yaml deleted file mode 100644 index a540f0251..000000000 --- a/carvel-packages/installer/scenarios/generic/test-generic-scenario-3/values.yaml +++ /dev/null @@ -1,22 +0,0 @@ -clusterInfrastructure: - provider: "generic" -clusterPackages: - kyverno: - enabled: false - educates: - settings: - imagePuller: - enabled: true - prePullImages: - - "a" -imagePuller: - enabled: true - prePullImages: - - "b" -workshopSecurity: - rulesEngine: "none" -workshopAnalytics: - google: - trackingId: "analytics" -clusterIngress: - domain: "educates.example.com" diff --git a/carvel-packages/installer/scenarios/generic/test-generic-scenario-4/description.md b/carvel-packages/installer/scenarios/generic/test-generic-scenario-4/description.md deleted file mode 100644 index c56bb1927..000000000 --- a/carvel-packages/installer/scenarios/generic/test-generic-scenario-4/description.md +++ /dev/null @@ -1,2 +0,0 @@ -generic configuration with some overrides to see if they are set -We disable educates, which can not be disabled, so will remain enabled. \ No newline at end of file diff --git a/carvel-packages/installer/scenarios/generic/test-generic-scenario-4/expected.yaml b/carvel-packages/installer/scenarios/generic/test-generic-scenario-4/expected.yaml deleted file mode 100644 index 31cd99df0..000000000 --- a/carvel-packages/installer/scenarios/generic/test-generic-scenario-4/expected.yaml +++ /dev/null @@ -1,35 +0,0 @@ -clusterPackages: - contour: - enabled: false - settings: {} - cert-manager: - enabled: false - settings: {} - external-dns: - enabled: false - settings: {} - certs: - enabled: false - settings: {} - kyverno: - enabled: true - settings: {} - kapp-controller: - enabled: false - settings: {} - educates: - enabled: true - settings: - clusterIngress: - domain: educates.example.com - clusterSecurity: - policyEngine: kyverno - workshopSecurity: - rulesEngine: none - workshopAnalytics: - google: - trackingId: analytics - imagePuller: - enabled: true - prePullImages: - - b \ No newline at end of file diff --git a/carvel-packages/installer/scenarios/generic/test-generic-scenario-4/values.yaml b/carvel-packages/installer/scenarios/generic/test-generic-scenario-4/values.yaml deleted file mode 100644 index d276cf186..000000000 --- a/carvel-packages/installer/scenarios/generic/test-generic-scenario-4/values.yaml +++ /dev/null @@ -1,21 +0,0 @@ -clusterInfrastructure: - provider: "generic" -clusterPackages: - educates: - enabled: false - settings: - imagePuller: - enabled: true - prePullImages: - - "a" -imagePuller: - enabled: true - prePullImages: - - "b" -workshopSecurity: - rulesEngine: "none" -workshopAnalytics: - google: - trackingId: "analytics" -clusterIngress: - domain: "educates.example.com" diff --git a/carvel-packages/installer/scenarios/gke/test-gke-scenario-01/description.md b/carvel-packages/installer/scenarios/gke/test-gke-scenario-01/description.md deleted file mode 100644 index 2c10c179f..000000000 --- a/carvel-packages/installer/scenarios/gke/test-gke-scenario-01/description.md +++ /dev/null @@ -1 +0,0 @@ -gke integrating with Cloud DNS to create DNS records and Let's Encrypt to generate wildcard diff --git a/carvel-packages/installer/scenarios/gke/test-gke-scenario-01/expected.yaml b/carvel-packages/installer/scenarios/gke/test-gke-scenario-01/expected.yaml deleted file mode 100644 index f588eab76..000000000 --- a/carvel-packages/installer/scenarios/gke/test-gke-scenario-01/expected.yaml +++ /dev/null @@ -1,59 +0,0 @@ -clusterPackages: - contour: - enabled: true - settings: - infraProvider: gcp - configFileContents: - defaultHttpVersions: - - HTTP/1.1 - service: - type: LoadBalancer - externaldns: - domains: - - educates.example.com - cert-manager: - enabled: true - settings: - serviceaccount: - annotations: - iam.gke.io/gcp-service-account: cert-manager@my-project.iam.gserviceaccount.com - external-dns: - enabled: true - settings: - infraProvider: gcp - serviceaccount: - annotations: - iam.gke.io/gcp-service-account: external-dns@my-project.iam.gserviceaccount.com - gcp: - args: - project: my-project - policy: sync - domain_filter: example.com - txt_owner_id: educates.example.com - certs: - enabled: true - settings: - certProvider: acme-gcp - domains: - - educates.example.com - acme: - gcp: - project: my-project - kyverno: - enabled: true - settings: {} - kapp-controller: - enabled: false - settings: {} - educates: - enabled: true - settings: - clusterIngress: - tlsCertificateRef: - namespace: projectcontour - name: educateswildcard - domain: educates.example.com - clusterSecurity: - policyEngine: kyverno - workshopSecurity: - rulesEngine: kyverno diff --git a/carvel-packages/installer/scenarios/gke/test-gke-scenario-01/values.yaml b/carvel-packages/installer/scenarios/gke/test-gke-scenario-01/values.yaml deleted file mode 100644 index 299f02846..000000000 --- a/carvel-packages/installer/scenarios/gke/test-gke-scenario-01/values.yaml +++ /dev/null @@ -1,13 +0,0 @@ -clusterInfrastructure: - provider: "gke" - gcp: - project: "my-project" - cloudDNS: - zone: "example.com" - workloadIdentity: - external-dns: "external-dns@my-project.iam.gserviceaccount.com" - cert-manager: "cert-manager@my-project.iam.gserviceaccount.com" -clusterSecurity: - policyEngine: "kyverno" -clusterIngress: - domain: "educates.example.com" diff --git a/carvel-packages/installer/scenarios/gke/test-gke-scenario-02/description.md b/carvel-packages/installer/scenarios/gke/test-gke-scenario-02/description.md deleted file mode 100644 index 42e5deb54..000000000 --- a/carvel-packages/installer/scenarios/gke/test-gke-scenario-02/description.md +++ /dev/null @@ -1,3 +0,0 @@ -gke integrating with Cloud DNS to create DNS records and Let's Encrypt to generate wildcard -We provide some custom configuration in clusterPackages that should be discarded. - diff --git a/carvel-packages/installer/scenarios/gke/test-gke-scenario-02/expected.yaml b/carvel-packages/installer/scenarios/gke/test-gke-scenario-02/expected.yaml deleted file mode 100644 index f588eab76..000000000 --- a/carvel-packages/installer/scenarios/gke/test-gke-scenario-02/expected.yaml +++ /dev/null @@ -1,59 +0,0 @@ -clusterPackages: - contour: - enabled: true - settings: - infraProvider: gcp - configFileContents: - defaultHttpVersions: - - HTTP/1.1 - service: - type: LoadBalancer - externaldns: - domains: - - educates.example.com - cert-manager: - enabled: true - settings: - serviceaccount: - annotations: - iam.gke.io/gcp-service-account: cert-manager@my-project.iam.gserviceaccount.com - external-dns: - enabled: true - settings: - infraProvider: gcp - serviceaccount: - annotations: - iam.gke.io/gcp-service-account: external-dns@my-project.iam.gserviceaccount.com - gcp: - args: - project: my-project - policy: sync - domain_filter: example.com - txt_owner_id: educates.example.com - certs: - enabled: true - settings: - certProvider: acme-gcp - domains: - - educates.example.com - acme: - gcp: - project: my-project - kyverno: - enabled: true - settings: {} - kapp-controller: - enabled: false - settings: {} - educates: - enabled: true - settings: - clusterIngress: - tlsCertificateRef: - namespace: projectcontour - name: educateswildcard - domain: educates.example.com - clusterSecurity: - policyEngine: kyverno - workshopSecurity: - rulesEngine: kyverno diff --git a/carvel-packages/installer/scenarios/gke/test-gke-scenario-02/values.yaml b/carvel-packages/installer/scenarios/gke/test-gke-scenario-02/values.yaml deleted file mode 100644 index 08406e678..000000000 --- a/carvel-packages/installer/scenarios/gke/test-gke-scenario-02/values.yaml +++ /dev/null @@ -1,54 +0,0 @@ -clusterInfrastructure: - provider: "gke" - gcp: - project: "my-project" - cloudDNS: - zone: "example.com" - workloadIdentity: - external-dns: "external-dns@my-project.iam.gserviceaccount.com" - cert-manager: "cert-manager@my-project.iam.gserviceaccount.com" -clusterPackages: - contour: - enabled: true - settings: - infraProvider: "aws" - configFileContents: - defaultHttpVersions: - - "HTTP/2" - service: - type: "ClsuterIP" - externaldns: - domains: - - "ERROR.educates.example.com" - cert-manager: - enabled: true - settings: - serviceaccount: - annotations: - iam.gke.io/gcp-service-account: "ERROR.cert-manager@my-project.iam.gserviceaccount.com" - external-dns: - enabled: true - settings: - infraProvider: gcp - serviceaccount: - annotations: - iam.gke.io/gcp-service-account: ERROR.external-dns@my-project.iam.gserviceaccount.com - gcp: - args: - project: my-project - domain_filter: example.com - txt_owner_id: educates - certs: - enabled: true - settings: - certProvider: acme-gcp - domains: - - ERROR.educates.example.com - acme: - gcp: - project: my-project -clusterSecurity: - policyEngine: "kyverno" -clusterIngress: - domain: "educates.example.com" - diff --git a/carvel-packages/installer/scenarios/gke/test-gke-scenario-03/description.md b/carvel-packages/installer/scenarios/gke/test-gke-scenario-03/description.md deleted file mode 100644 index be072ea15..000000000 --- a/carvel-packages/installer/scenarios/gke/test-gke-scenario-03/description.md +++ /dev/null @@ -1,2 +0,0 @@ -gke integrating with Cloud DNS to create DNS records and Let's Encrypt to generate wildcard -We disable some packages. diff --git a/carvel-packages/installer/scenarios/gke/test-gke-scenario-03/expected.yaml b/carvel-packages/installer/scenarios/gke/test-gke-scenario-03/expected.yaml deleted file mode 100644 index 0adf75f6f..000000000 --- a/carvel-packages/installer/scenarios/gke/test-gke-scenario-03/expected.yaml +++ /dev/null @@ -1,31 +0,0 @@ -clusterPackages: - contour: - enabled: false - settings: {} - cert-manager: - enabled: false - settings: {} - external-dns: - enabled: false - settings: {} - certs: - enabled: false - settings: {} - kyverno: - enabled: true - settings: {} - kapp-controller: - enabled: false - settings: {} - educates: - enabled: true - settings: - clusterIngress: - tlsCertificateRef: - namespace: projectcontour - name: educateswildcard - domain: educates.example.com - clusterSecurity: - policyEngine: kyverno - workshopSecurity: - rulesEngine: kyverno diff --git a/carvel-packages/installer/scenarios/gke/test-gke-scenario-03/values.yaml b/carvel-packages/installer/scenarios/gke/test-gke-scenario-03/values.yaml deleted file mode 100644 index f00b96b8a..000000000 --- a/carvel-packages/installer/scenarios/gke/test-gke-scenario-03/values.yaml +++ /dev/null @@ -1,22 +0,0 @@ -clusterInfrastructure: - provider: "gke" - gcp: - project: "my-project" - cloudDNS: - zone: "example.com" - workloadIdentity: - external-dns: "external-dns@my-project.iam.gserviceaccount.com" - cert-manager: "cert-manager@my-project.iam.gserviceaccount.com" -clusterPackages: - contour: - enabled: false - cert-manager: - enabled: false - external-dns: - enabled: false - certs: - enabled: false -clusterSecurity: - policyEngine: "kyverno" -clusterIngress: - domain: "educates.example.com" diff --git a/carvel-packages/installer/scenarios/gke/test-gke-scenario-04/description.md b/carvel-packages/installer/scenarios/gke/test-gke-scenario-04/description.md deleted file mode 100644 index d5998c859..000000000 --- a/carvel-packages/installer/scenarios/gke/test-gke-scenario-04/description.md +++ /dev/null @@ -1,2 +0,0 @@ -gke integrating with Cloud DNS to create DNS records and Let's Encrypt to generate wildcard -We enable LookupService diff --git a/carvel-packages/installer/scenarios/gke/test-gke-scenario-04/expected.yaml b/carvel-packages/installer/scenarios/gke/test-gke-scenario-04/expected.yaml deleted file mode 100644 index 1488f7e40..000000000 --- a/carvel-packages/installer/scenarios/gke/test-gke-scenario-04/expected.yaml +++ /dev/null @@ -1,61 +0,0 @@ -clusterPackages: - contour: - enabled: true - settings: - infraProvider: gcp - configFileContents: - defaultHttpVersions: - - HTTP/1.1 - service: - type: LoadBalancer - externaldns: - domains: - - educates.example.com - cert-manager: - enabled: true - settings: - serviceaccount: - annotations: - iam.gke.io/gcp-service-account: cert-manager@my-project.iam.gserviceaccount.com - external-dns: - enabled: true - settings: - infraProvider: gcp - serviceaccount: - annotations: - iam.gke.io/gcp-service-account: external-dns@my-project.iam.gserviceaccount.com - gcp: - args: - project: my-project - policy: sync - domain_filter: example.com - txt_owner_id: educates.example.com - certs: - enabled: true - settings: - certProvider: acme-gcp - domains: - - educates.example.com - acme: - gcp: - project: my-project - kyverno: - enabled: true - settings: {} - kapp-controller: - enabled: false - settings: {} - educates: - enabled: true - settings: - clusterIngress: - tlsCertificateRef: - namespace: projectcontour - name: educateswildcard - domain: educates.example.com - clusterSecurity: - policyEngine: kyverno - workshopSecurity: - rulesEngine: kyverno - lookupService: - enabled: true diff --git a/carvel-packages/installer/scenarios/gke/test-gke-scenario-04/values.yaml b/carvel-packages/installer/scenarios/gke/test-gke-scenario-04/values.yaml deleted file mode 100644 index cd0cc6995..000000000 --- a/carvel-packages/installer/scenarios/gke/test-gke-scenario-04/values.yaml +++ /dev/null @@ -1,15 +0,0 @@ -clusterInfrastructure: - provider: "gke" - gcp: - project: "my-project" - cloudDNS: - zone: "example.com" - workloadIdentity: - external-dns: "external-dns@my-project.iam.gserviceaccount.com" - cert-manager: "cert-manager@my-project.iam.gserviceaccount.com" -clusterSecurity: - policyEngine: "kyverno" -clusterIngress: - domain: "educates.example.com" -lookupService: - enabled: true diff --git a/carvel-packages/installer/scenarios/gke/test-gke-scenario-04b/description.md b/carvel-packages/installer/scenarios/gke/test-gke-scenario-04b/description.md deleted file mode 100644 index 6b66805ec..000000000 --- a/carvel-packages/installer/scenarios/gke/test-gke-scenario-04b/description.md +++ /dev/null @@ -1,2 +0,0 @@ -gke integrating with Cloud DNS to create DNS records and Let's Encrypt to generate wildcard -We enable LookupService with alternate ingressPrefix diff --git a/carvel-packages/installer/scenarios/gke/test-gke-scenario-04b/expected.yaml b/carvel-packages/installer/scenarios/gke/test-gke-scenario-04b/expected.yaml deleted file mode 100644 index bc6188dfc..000000000 --- a/carvel-packages/installer/scenarios/gke/test-gke-scenario-04b/expected.yaml +++ /dev/null @@ -1,62 +0,0 @@ -clusterPackages: - contour: - enabled: true - settings: - infraProvider: gcp - configFileContents: - defaultHttpVersions: - - HTTP/1.1 - service: - type: LoadBalancer - externaldns: - domains: - - educates.example.com - cert-manager: - enabled: true - settings: - serviceaccount: - annotations: - iam.gke.io/gcp-service-account: cert-manager@my-project.iam.gserviceaccount.com - external-dns: - enabled: true - settings: - infraProvider: gcp - serviceaccount: - annotations: - iam.gke.io/gcp-service-account: external-dns@my-project.iam.gserviceaccount.com - gcp: - args: - project: my-project - policy: sync - domain_filter: example.com - txt_owner_id: educates.example.com - certs: - enabled: true - settings: - certProvider: acme-gcp - domains: - - educates.example.com - acme: - gcp: - project: my-project - kyverno: - enabled: true - settings: {} - kapp-controller: - enabled: false - settings: {} - educates: - enabled: true - settings: - clusterIngress: - tlsCertificateRef: - namespace: projectcontour - name: educateswildcard - domain: educates.example.com - clusterSecurity: - policyEngine: kyverno - workshopSecurity: - rulesEngine: kyverno - lookupService: - enabled: true - ingressPrefix: ALTERNATE diff --git a/carvel-packages/installer/scenarios/gke/test-gke-scenario-04b/values.yaml b/carvel-packages/installer/scenarios/gke/test-gke-scenario-04b/values.yaml deleted file mode 100644 index ab77250d6..000000000 --- a/carvel-packages/installer/scenarios/gke/test-gke-scenario-04b/values.yaml +++ /dev/null @@ -1,16 +0,0 @@ -clusterInfrastructure: - provider: "gke" - gcp: - project: "my-project" - cloudDNS: - zone: "example.com" - workloadIdentity: - external-dns: "external-dns@my-project.iam.gserviceaccount.com" - cert-manager: "cert-manager@my-project.iam.gserviceaccount.com" -clusterSecurity: - policyEngine: "kyverno" -clusterIngress: - domain: "educates.example.com" -lookupService: - enabled: true - ingressPrefix: ALTERNATE diff --git a/carvel-packages/installer/scenarios/gke/test-gke-scenario-04c/description.md b/carvel-packages/installer/scenarios/gke/test-gke-scenario-04c/description.md deleted file mode 100644 index 2c06a3a79..000000000 --- a/carvel-packages/installer/scenarios/gke/test-gke-scenario-04c/description.md +++ /dev/null @@ -1,3 +0,0 @@ -gke integrating with Cloud DNS to create DNS records and Let's Encrypt to generate wildcard -We enable LookupService with alternate ingressPrefix globally -We enable LookupService in clusterPackages with other ingressPrefix that should be discarded diff --git a/carvel-packages/installer/scenarios/gke/test-gke-scenario-04c/expected.yaml b/carvel-packages/installer/scenarios/gke/test-gke-scenario-04c/expected.yaml deleted file mode 100644 index bc6188dfc..000000000 --- a/carvel-packages/installer/scenarios/gke/test-gke-scenario-04c/expected.yaml +++ /dev/null @@ -1,62 +0,0 @@ -clusterPackages: - contour: - enabled: true - settings: - infraProvider: gcp - configFileContents: - defaultHttpVersions: - - HTTP/1.1 - service: - type: LoadBalancer - externaldns: - domains: - - educates.example.com - cert-manager: - enabled: true - settings: - serviceaccount: - annotations: - iam.gke.io/gcp-service-account: cert-manager@my-project.iam.gserviceaccount.com - external-dns: - enabled: true - settings: - infraProvider: gcp - serviceaccount: - annotations: - iam.gke.io/gcp-service-account: external-dns@my-project.iam.gserviceaccount.com - gcp: - args: - project: my-project - policy: sync - domain_filter: example.com - txt_owner_id: educates.example.com - certs: - enabled: true - settings: - certProvider: acme-gcp - domains: - - educates.example.com - acme: - gcp: - project: my-project - kyverno: - enabled: true - settings: {} - kapp-controller: - enabled: false - settings: {} - educates: - enabled: true - settings: - clusterIngress: - tlsCertificateRef: - namespace: projectcontour - name: educateswildcard - domain: educates.example.com - clusterSecurity: - policyEngine: kyverno - workshopSecurity: - rulesEngine: kyverno - lookupService: - enabled: true - ingressPrefix: ALTERNATE diff --git a/carvel-packages/installer/scenarios/gke/test-gke-scenario-04c/values.yaml b/carvel-packages/installer/scenarios/gke/test-gke-scenario-04c/values.yaml deleted file mode 100644 index 5f9aeec75..000000000 --- a/carvel-packages/installer/scenarios/gke/test-gke-scenario-04c/values.yaml +++ /dev/null @@ -1,22 +0,0 @@ -clusterInfrastructure: - provider: "gke" - gcp: - project: "my-project" - cloudDNS: - zone: "example.com" - workloadIdentity: - external-dns: "external-dns@my-project.iam.gserviceaccount.com" - cert-manager: "cert-manager@my-project.iam.gserviceaccount.com" -clusterPackages: - educates: - settings: - lookupService: - enabled: true - ingressPrefix: THIS_NOT -clusterSecurity: - policyEngine: "kyverno" -clusterIngress: - domain: "educates.example.com" -lookupService: - enabled: true - ingressPrefix: ALTERNATE diff --git a/carvel-packages/installer/scenarios/gke/test-gke-scenario-04d/description.md b/carvel-packages/installer/scenarios/gke/test-gke-scenario-04d/description.md deleted file mode 100644 index f94ea1c40..000000000 --- a/carvel-packages/installer/scenarios/gke/test-gke-scenario-04d/description.md +++ /dev/null @@ -1,3 +0,0 @@ -gke integrating with Cloud DNS to create DNS records and Let's Encrypt to generate wildcard -We enable LookupService with no ingressPrefix -We enable LookupService in clusterPackages with other ingressPrefix that should be REMAIN diff --git a/carvel-packages/installer/scenarios/gke/test-gke-scenario-04d/expected.yaml b/carvel-packages/installer/scenarios/gke/test-gke-scenario-04d/expected.yaml deleted file mode 100644 index 04e8af0b9..000000000 --- a/carvel-packages/installer/scenarios/gke/test-gke-scenario-04d/expected.yaml +++ /dev/null @@ -1,62 +0,0 @@ -clusterPackages: - contour: - enabled: true - settings: - infraProvider: gcp - configFileContents: - defaultHttpVersions: - - HTTP/1.1 - service: - type: LoadBalancer - externaldns: - domains: - - educates.example.com - cert-manager: - enabled: true - settings: - serviceaccount: - annotations: - iam.gke.io/gcp-service-account: cert-manager@my-project.iam.gserviceaccount.com - external-dns: - enabled: true - settings: - infraProvider: gcp - serviceaccount: - annotations: - iam.gke.io/gcp-service-account: external-dns@my-project.iam.gserviceaccount.com - gcp: - args: - project: my-project - policy: sync - domain_filter: example.com - txt_owner_id: educates.example.com - certs: - enabled: true - settings: - certProvider: acme-gcp - domains: - - educates.example.com - acme: - gcp: - project: my-project - kyverno: - enabled: true - settings: {} - kapp-controller: - enabled: false - settings: {} - educates: - enabled: true - settings: - clusterIngress: - tlsCertificateRef: - namespace: projectcontour - name: educateswildcard - domain: educates.example.com - clusterSecurity: - policyEngine: kyverno - workshopSecurity: - rulesEngine: kyverno - lookupService: - enabled: true - ingressPrefix: THIS_SHOULD_STAY diff --git a/carvel-packages/installer/scenarios/gke/test-gke-scenario-04d/values.yaml b/carvel-packages/installer/scenarios/gke/test-gke-scenario-04d/values.yaml deleted file mode 100644 index e04ce4ee8..000000000 --- a/carvel-packages/installer/scenarios/gke/test-gke-scenario-04d/values.yaml +++ /dev/null @@ -1,21 +0,0 @@ -clusterInfrastructure: - provider: "gke" - gcp: - project: "my-project" - cloudDNS: - zone: "example.com" - workloadIdentity: - external-dns: "external-dns@my-project.iam.gserviceaccount.com" - cert-manager: "cert-manager@my-project.iam.gserviceaccount.com" -clusterPackages: - educates: - settings: - lookupService: - enabled: true - ingressPrefix: THIS_SHOULD_STAY -clusterSecurity: - policyEngine: "kyverno" -clusterIngress: - domain: "educates.example.com" -lookupService: - enabled: true diff --git a/carvel-packages/installer/scenarios/kind/test-kind-scenario-01/description.md b/carvel-packages/installer/scenarios/kind/test-kind-scenario-01/description.md deleted file mode 100644 index d7c7716a0..000000000 --- a/carvel-packages/installer/scenarios/kind/test-kind-scenario-01/description.md +++ /dev/null @@ -1 +0,0 @@ -kind using provided domain with http and kyverno clusterSecurityEngine diff --git a/carvel-packages/installer/scenarios/kind/test-kind-scenario-01/expected.yaml b/carvel-packages/installer/scenarios/kind/test-kind-scenario-01/expected.yaml deleted file mode 100644 index 7bd6528fc..000000000 --- a/carvel-packages/installer/scenarios/kind/test-kind-scenario-01/expected.yaml +++ /dev/null @@ -1,37 +0,0 @@ -clusterPackages: - contour: - enabled: true - settings: - infraProvider: kind - contour: - replicas: 1 - configFileContents: - defaultHttpVersions: - - HTTP/1.1 - service: - type: ClusterIP - useHostPorts: true - cert-manager: - enabled: false - settings: {} - external-dns: - enabled: false - settings: {} - certs: - enabled: false - settings: {} - kyverno: - enabled: true - settings: {} - kapp-controller: - enabled: false - settings: {} - educates: - enabled: true - settings: - clusterIngress: - domain: educates.example.com - clusterSecurity: - policyEngine: kyverno - workshopSecurity: - rulesEngine: kyverno diff --git a/carvel-packages/installer/scenarios/kind/test-kind-scenario-01/values.yaml b/carvel-packages/installer/scenarios/kind/test-kind-scenario-01/values.yaml deleted file mode 100644 index 8cd8f39c7..000000000 --- a/carvel-packages/installer/scenarios/kind/test-kind-scenario-01/values.yaml +++ /dev/null @@ -1,7 +0,0 @@ ---- -clusterInfrastructure: - provider: "kind" -clusterSecurity: - policyEngine: "kyverno" -clusterIngress: - domain: "educates.example.com" diff --git a/carvel-packages/installer/scenarios/kind/test-kind-scenario-01b/description.md b/carvel-packages/installer/scenarios/kind/test-kind-scenario-01b/description.md deleted file mode 100644 index 626d6107d..000000000 --- a/carvel-packages/installer/scenarios/kind/test-kind-scenario-01b/description.md +++ /dev/null @@ -1,3 +0,0 @@ -kind using provided domain with http and kyverno clusterSecurityEngine, -but with package kyverno disabled, -but even when clusterSecurity is kyverno, kyvernos should not be re-enabled diff --git a/carvel-packages/installer/scenarios/kind/test-kind-scenario-01b/expected.yaml b/carvel-packages/installer/scenarios/kind/test-kind-scenario-01b/expected.yaml deleted file mode 100644 index c96ce8233..000000000 --- a/carvel-packages/installer/scenarios/kind/test-kind-scenario-01b/expected.yaml +++ /dev/null @@ -1,37 +0,0 @@ -clusterPackages: - contour: - enabled: true - settings: - infraProvider: kind - contour: - replicas: 1 - configFileContents: - defaultHttpVersions: - - HTTP/1.1 - service: - type: ClusterIP - useHostPorts: true - cert-manager: - enabled: false - settings: {} - external-dns: - enabled: false - settings: {} - certs: - enabled: false - settings: {} - kyverno: - enabled: false - settings: {} - kapp-controller: - enabled: false - settings: {} - educates: - enabled: true - settings: - clusterIngress: - domain: educates.example.com - clusterSecurity: - policyEngine: kyverno - workshopSecurity: - rulesEngine: kyverno diff --git a/carvel-packages/installer/scenarios/kind/test-kind-scenario-01b/values.yaml b/carvel-packages/installer/scenarios/kind/test-kind-scenario-01b/values.yaml deleted file mode 100644 index 57c17728d..000000000 --- a/carvel-packages/installer/scenarios/kind/test-kind-scenario-01b/values.yaml +++ /dev/null @@ -1,9 +0,0 @@ -clusterPackages: - kyverno: - enabled: false -clusterInfrastructure: - provider: "kind" -clusterSecurity: - policyEngine: "kyverno" -clusterIngress: - domain: "educates.example.com" diff --git a/carvel-packages/installer/scenarios/kind/test-kind-scenario-01c/description.md b/carvel-packages/installer/scenarios/kind/test-kind-scenario-01c/description.md deleted file mode 100644 index e0b4679e2..000000000 --- a/carvel-packages/installer/scenarios/kind/test-kind-scenario-01c/description.md +++ /dev/null @@ -1,4 +0,0 @@ -kind using provided domain with http and kyverno clusterSecurityEngine, -but with package kyverno disabled, but even with clusterSecurity is kyverno, -kyverno should not be re-enabled - diff --git a/carvel-packages/installer/scenarios/kind/test-kind-scenario-01c/expected.yaml b/carvel-packages/installer/scenarios/kind/test-kind-scenario-01c/expected.yaml deleted file mode 100644 index 27d97363b..000000000 --- a/carvel-packages/installer/scenarios/kind/test-kind-scenario-01c/expected.yaml +++ /dev/null @@ -1,31 +0,0 @@ -clusterPackages: - contour: - enabled: true - settings: - infraProvider: kind - contour: - replicas: 1 - configFileContents: - defaultHttpVersions: - - HTTP/1.1 - service: - type: ClusterIP - useHostPorts: true - cert-manager: - enabled: false - settings: {} - external-dns: - enabled: false - settings: {} - certs: - enabled: false - settings: {} - kyverno: - enabled: false - settings: {} - kapp-controller: - enabled: false - settings: {} - educates: - enabled: false - settings: {} diff --git a/carvel-packages/installer/scenarios/kind/test-kind-scenario-01c/values.yaml b/carvel-packages/installer/scenarios/kind/test-kind-scenario-01c/values.yaml deleted file mode 100644 index 29a630be5..000000000 --- a/carvel-packages/installer/scenarios/kind/test-kind-scenario-01c/values.yaml +++ /dev/null @@ -1,11 +0,0 @@ -clusterPackages: - kyverno: - enabled: false - educates: - enabled: false -clusterInfrastructure: - provider: "kind" -clusterSecurity: - policyEngine: "kyverno" -clusterIngress: - domain: "educates.example.com" diff --git a/carvel-packages/installer/scenarios/kind/test-kind-scenario-01d/description.md b/carvel-packages/installer/scenarios/kind/test-kind-scenario-01d/description.md deleted file mode 100644 index 464762cf8..000000000 --- a/carvel-packages/installer/scenarios/kind/test-kind-scenario-01d/description.md +++ /dev/null @@ -1,2 +0,0 @@ -kind using provided domain with http and kyverno clusterSecurityEngine -With lookupService enabled \ No newline at end of file diff --git a/carvel-packages/installer/scenarios/kind/test-kind-scenario-01d/expected.yaml b/carvel-packages/installer/scenarios/kind/test-kind-scenario-01d/expected.yaml deleted file mode 100644 index 4f7203c54..000000000 --- a/carvel-packages/installer/scenarios/kind/test-kind-scenario-01d/expected.yaml +++ /dev/null @@ -1,39 +0,0 @@ -clusterPackages: - contour: - enabled: true - settings: - infraProvider: kind - contour: - replicas: 1 - configFileContents: - defaultHttpVersions: - - HTTP/1.1 - service: - type: ClusterIP - useHostPorts: true - cert-manager: - enabled: false - settings: {} - external-dns: - enabled: false - settings: {} - certs: - enabled: false - settings: {} - kyverno: - enabled: true - settings: {} - kapp-controller: - enabled: false - settings: {} - educates: - enabled: true - settings: - clusterIngress: - domain: educates.example.com - clusterSecurity: - policyEngine: kyverno - workshopSecurity: - rulesEngine: kyverno - lookupService: - enabled: true \ No newline at end of file diff --git a/carvel-packages/installer/scenarios/kind/test-kind-scenario-01d/values.yaml b/carvel-packages/installer/scenarios/kind/test-kind-scenario-01d/values.yaml deleted file mode 100644 index 558cfb221..000000000 --- a/carvel-packages/installer/scenarios/kind/test-kind-scenario-01d/values.yaml +++ /dev/null @@ -1,9 +0,0 @@ ---- -clusterInfrastructure: - provider: "kind" -clusterSecurity: - policyEngine: "kyverno" -clusterIngress: - domain: "educates.example.com" -lookupService: - enabled: true diff --git a/carvel-packages/installer/scenarios/kind/test-kind-scenario-01e/description.md b/carvel-packages/installer/scenarios/kind/test-kind-scenario-01e/description.md deleted file mode 100644 index 0b89d1d83..000000000 --- a/carvel-packages/installer/scenarios/kind/test-kind-scenario-01e/description.md +++ /dev/null @@ -1,2 +0,0 @@ -kind using provided domain with http and kyverno clusterSecurityEngine -With lookupService enabled with clusterPackages providing alternate ingressPrefix that should remain \ No newline at end of file diff --git a/carvel-packages/installer/scenarios/kind/test-kind-scenario-01e/expected.yaml b/carvel-packages/installer/scenarios/kind/test-kind-scenario-01e/expected.yaml deleted file mode 100644 index 56d82dc15..000000000 --- a/carvel-packages/installer/scenarios/kind/test-kind-scenario-01e/expected.yaml +++ /dev/null @@ -1,40 +0,0 @@ -clusterPackages: - contour: - enabled: true - settings: - infraProvider: kind - contour: - replicas: 1 - configFileContents: - defaultHttpVersions: - - HTTP/1.1 - service: - type: ClusterIP - useHostPorts: true - cert-manager: - enabled: false - settings: {} - external-dns: - enabled: false - settings: {} - certs: - enabled: false - settings: {} - kyverno: - enabled: true - settings: {} - kapp-controller: - enabled: false - settings: {} - educates: - enabled: true - settings: - clusterIngress: - domain: educates.example.com - clusterSecurity: - policyEngine: kyverno - workshopSecurity: - rulesEngine: kyverno - lookupService: - enabled: true - ingressPrefix: THIS_SHOULD_REMAIN diff --git a/carvel-packages/installer/scenarios/kind/test-kind-scenario-01e/values.yaml b/carvel-packages/installer/scenarios/kind/test-kind-scenario-01e/values.yaml deleted file mode 100644 index 5f2f3b7c0..000000000 --- a/carvel-packages/installer/scenarios/kind/test-kind-scenario-01e/values.yaml +++ /dev/null @@ -1,14 +0,0 @@ ---- -clusterInfrastructure: - provider: "kind" -clusterSecurity: - policyEngine: "kyverno" -clusterIngress: - domain: "educates.example.com" -lookupService: - enabled: true -clusterPackages: - educates: - settings: - lookupService: - ingressPrefix: THIS_SHOULD_REMAIN diff --git a/carvel-packages/installer/scenarios/kind/test-kind-scenario-01f/description.md b/carvel-packages/installer/scenarios/kind/test-kind-scenario-01f/description.md deleted file mode 100644 index 2fcadff10..000000000 --- a/carvel-packages/installer/scenarios/kind/test-kind-scenario-01f/description.md +++ /dev/null @@ -1,3 +0,0 @@ -kind using provided domain with http and kyverno clusterSecurityEngine -With lookupService enabled with ingressPrefix -and clusterPackages providing alternate ingressPrefix that should not prevail \ No newline at end of file diff --git a/carvel-packages/installer/scenarios/kind/test-kind-scenario-01f/expected.yaml b/carvel-packages/installer/scenarios/kind/test-kind-scenario-01f/expected.yaml deleted file mode 100644 index 56d82dc15..000000000 --- a/carvel-packages/installer/scenarios/kind/test-kind-scenario-01f/expected.yaml +++ /dev/null @@ -1,40 +0,0 @@ -clusterPackages: - contour: - enabled: true - settings: - infraProvider: kind - contour: - replicas: 1 - configFileContents: - defaultHttpVersions: - - HTTP/1.1 - service: - type: ClusterIP - useHostPorts: true - cert-manager: - enabled: false - settings: {} - external-dns: - enabled: false - settings: {} - certs: - enabled: false - settings: {} - kyverno: - enabled: true - settings: {} - kapp-controller: - enabled: false - settings: {} - educates: - enabled: true - settings: - clusterIngress: - domain: educates.example.com - clusterSecurity: - policyEngine: kyverno - workshopSecurity: - rulesEngine: kyverno - lookupService: - enabled: true - ingressPrefix: THIS_SHOULD_REMAIN diff --git a/carvel-packages/installer/scenarios/kind/test-kind-scenario-01f/values.yaml b/carvel-packages/installer/scenarios/kind/test-kind-scenario-01f/values.yaml deleted file mode 100644 index 84b3257d0..000000000 --- a/carvel-packages/installer/scenarios/kind/test-kind-scenario-01f/values.yaml +++ /dev/null @@ -1,15 +0,0 @@ ---- -clusterInfrastructure: - provider: "kind" -clusterSecurity: - policyEngine: "kyverno" -clusterIngress: - domain: "educates.example.com" -lookupService: - enabled: true - ingressPrefix: THIS_SHOULD_REMAIN -clusterPackages: - educates: - settings: - lookupService: - ingressPrefix: THIS_SHOULD_NOT diff --git a/carvel-packages/installer/scenarios/kind/test-kind-scenario-02/description.md b/carvel-packages/installer/scenarios/kind/test-kind-scenario-02/description.md deleted file mode 100644 index 6cf17296a..000000000 --- a/carvel-packages/installer/scenarios/kind/test-kind-scenario-02/description.md +++ /dev/null @@ -1,2 +0,0 @@ -kind using provided domain with http and pod-security-policies clusterSecurityEngine, -but since kyverno is by default enabled and here not disabled explicitly, it'll be enabled diff --git a/carvel-packages/installer/scenarios/kind/test-kind-scenario-02/expected.yaml b/carvel-packages/installer/scenarios/kind/test-kind-scenario-02/expected.yaml deleted file mode 100644 index ab1958a6a..000000000 --- a/carvel-packages/installer/scenarios/kind/test-kind-scenario-02/expected.yaml +++ /dev/null @@ -1,37 +0,0 @@ -clusterPackages: - contour: - enabled: true - settings: - infraProvider: kind - contour: - replicas: 1 - configFileContents: - defaultHttpVersions: - - HTTP/1.1 - service: - type: ClusterIP - useHostPorts: true - cert-manager: - enabled: false - settings: {} - external-dns: - enabled: false - settings: {} - certs: - enabled: false - settings: {} - kyverno: - enabled: true - settings: {} - kapp-controller: - enabled: false - settings: {} - educates: - enabled: true - settings: - clusterIngress: - domain: educates.example.com - clusterSecurity: - policyEngine: pod-security-policies - workshopSecurity: - rulesEngine: kyverno diff --git a/carvel-packages/installer/scenarios/kind/test-kind-scenario-02/values.yaml b/carvel-packages/installer/scenarios/kind/test-kind-scenario-02/values.yaml deleted file mode 100644 index 33ee98ce5..000000000 --- a/carvel-packages/installer/scenarios/kind/test-kind-scenario-02/values.yaml +++ /dev/null @@ -1,6 +0,0 @@ -clusterInfrastructure: - provider: "kind" -clusterSecurity: - policyEngine: "pod-security-policies" -clusterIngress: - domain: "educates.example.com" diff --git a/carvel-packages/installer/scenarios/kind/test-kind-scenario-02b/description.md b/carvel-packages/installer/scenarios/kind/test-kind-scenario-02b/description.md deleted file mode 100644 index ec1a71d10..000000000 --- a/carvel-packages/installer/scenarios/kind/test-kind-scenario-02b/description.md +++ /dev/null @@ -1,2 +0,0 @@ -kind using provided domain with http and pod-security-policies clusterSecurityEngine, -with kyverno disabled diff --git a/carvel-packages/installer/scenarios/kind/test-kind-scenario-02b/expected.yaml b/carvel-packages/installer/scenarios/kind/test-kind-scenario-02b/expected.yaml deleted file mode 100644 index 3409b5b82..000000000 --- a/carvel-packages/installer/scenarios/kind/test-kind-scenario-02b/expected.yaml +++ /dev/null @@ -1,37 +0,0 @@ -clusterPackages: - contour: - enabled: true - settings: - infraProvider: kind - contour: - replicas: 1 - configFileContents: - defaultHttpVersions: - - HTTP/1.1 - service: - type: ClusterIP - useHostPorts: true - cert-manager: - enabled: false - settings: {} - external-dns: - enabled: false - settings: {} - certs: - enabled: false - settings: {} - kyverno: - enabled: false - settings: {} - kapp-controller: - enabled: false - settings: {} - educates: - enabled: true - settings: - clusterIngress: - domain: educates.example.com - clusterSecurity: - policyEngine: pod-security-policies - workshopSecurity: - rulesEngine: kyverno diff --git a/carvel-packages/installer/scenarios/kind/test-kind-scenario-02b/values.yaml b/carvel-packages/installer/scenarios/kind/test-kind-scenario-02b/values.yaml deleted file mode 100644 index f480cd276..000000000 --- a/carvel-packages/installer/scenarios/kind/test-kind-scenario-02b/values.yaml +++ /dev/null @@ -1,9 +0,0 @@ -clusterPackages: - kyverno: - enabled: false -clusterInfrastructure: - provider: "kind" -clusterSecurity: - policyEngine: "pod-security-policies" -clusterIngress: - domain: "educates.example.com" diff --git a/carvel-packages/installer/scenarios/kind/test-kind-scenario-03/description.md b/carvel-packages/installer/scenarios/kind/test-kind-scenario-03/description.md deleted file mode 100644 index 33650776f..000000000 --- a/carvel-packages/installer/scenarios/kind/test-kind-scenario-03/description.md +++ /dev/null @@ -1 +0,0 @@ -kind with tlsCertificateRef for educates diff --git a/carvel-packages/installer/scenarios/kind/test-kind-scenario-03/expected.yaml b/carvel-packages/installer/scenarios/kind/test-kind-scenario-03/expected.yaml deleted file mode 100644 index f9249e157..000000000 --- a/carvel-packages/installer/scenarios/kind/test-kind-scenario-03/expected.yaml +++ /dev/null @@ -1,40 +0,0 @@ -clusterPackages: - contour: - enabled: true - settings: - infraProvider: kind - contour: - replicas: 1 - configFileContents: - defaultHttpVersions: - - HTTP/1.1 - service: - type: ClusterIP - useHostPorts: true - cert-manager: - enabled: false - settings: {} - external-dns: - enabled: false - settings: {} - certs: - enabled: false - settings: {} - kyverno: - enabled: true - settings: {} - kapp-controller: - enabled: false - settings: {} - educates: - enabled: true - settings: - clusterIngress: - domain: educates.example.com - tlsCertificateRef: - namespace: educates-secrets - name: educates-example-com-tls - clusterSecurity: - policyEngine: kyverno - workshopSecurity: - rulesEngine: kyverno diff --git a/carvel-packages/installer/scenarios/kind/test-kind-scenario-03/values.yaml b/carvel-packages/installer/scenarios/kind/test-kind-scenario-03/values.yaml deleted file mode 100644 index 3442e5a30..000000000 --- a/carvel-packages/installer/scenarios/kind/test-kind-scenario-03/values.yaml +++ /dev/null @@ -1,9 +0,0 @@ -clusterInfrastructure: - provider: "kind" -clusterSecurity: - policyEngine: "kyverno" -clusterIngress: - domain: "educates.example.com" - tlsCertificateRef: - namespace: "educates-secrets" - name: "educates-example-com-tls" diff --git a/carvel-packages/installer/scenarios/kind/test-kind-scenario-03b/description.md b/carvel-packages/installer/scenarios/kind/test-kind-scenario-03b/description.md deleted file mode 100644 index 3bfa468b5..000000000 --- a/carvel-packages/installer/scenarios/kind/test-kind-scenario-03b/description.md +++ /dev/null @@ -1 +0,0 @@ -kind with tlsCertificateRef for educates when they are in local secrets cache diff --git a/carvel-packages/installer/scenarios/kind/test-kind-scenario-03b/expected.yaml b/carvel-packages/installer/scenarios/kind/test-kind-scenario-03b/expected.yaml deleted file mode 100644 index eb742bdde..000000000 --- a/carvel-packages/installer/scenarios/kind/test-kind-scenario-03b/expected.yaml +++ /dev/null @@ -1,40 +0,0 @@ -clusterPackages: - contour: - enabled: true - settings: - infraProvider: kind - contour: - replicas: 1 - configFileContents: - defaultHttpVersions: - - HTTP/1.1 - service: - type: ClusterIP - useHostPorts: true - cert-manager: - enabled: false - settings: {} - external-dns: - enabled: false - settings: {} - certs: - enabled: false - settings: {} - kyverno: - enabled: true - settings: {} - kapp-controller: - enabled: false - settings: {} - educates: - enabled: true - settings: - clusterIngress: - domain: educates.example.com - tlsCertificateRef: - namespace: educates-secrets - name: educates-example-com-fromcache-tls - clusterSecurity: - policyEngine: kyverno - workshopSecurity: - rulesEngine: kyverno diff --git a/carvel-packages/installer/scenarios/kind/test-kind-scenario-03b/values.yaml b/carvel-packages/installer/scenarios/kind/test-kind-scenario-03b/values.yaml deleted file mode 100644 index 80cd90535..000000000 --- a/carvel-packages/installer/scenarios/kind/test-kind-scenario-03b/values.yaml +++ /dev/null @@ -1,9 +0,0 @@ -clusterInfrastructure: - provider: "kind" -clusterSecurity: - policyEngine: "kyverno" -clusterIngress: - domain: "educates.example.com" - tlsCertificateRef: - namespace: "educates-secrets" - name: "educates-example-com-fromcache-tls" diff --git a/carvel-packages/installer/scenarios/kind/test-kind-scenario-04/description.md b/carvel-packages/installer/scenarios/kind/test-kind-scenario-04/description.md deleted file mode 100644 index 8a2eb47d7..000000000 --- a/carvel-packages/installer/scenarios/kind/test-kind-scenario-04/description.md +++ /dev/null @@ -1 +0,0 @@ -kind with tlsCertificateRef and caCertificateRef for educates diff --git a/carvel-packages/installer/scenarios/kind/test-kind-scenario-04/expected.yaml b/carvel-packages/installer/scenarios/kind/test-kind-scenario-04/expected.yaml deleted file mode 100644 index 32b836bff..000000000 --- a/carvel-packages/installer/scenarios/kind/test-kind-scenario-04/expected.yaml +++ /dev/null @@ -1,43 +0,0 @@ -clusterPackages: - contour: - enabled: true - settings: - infraProvider: kind - contour: - replicas: 1 - configFileContents: - defaultHttpVersions: - - HTTP/1.1 - service: - type: ClusterIP - useHostPorts: true - cert-manager: - enabled: false - settings: {} - external-dns: - enabled: false - settings: {} - certs: - enabled: false - settings: {} - kyverno: - enabled: true - settings: {} - kapp-controller: - enabled: false - settings: {} - educates: - enabled: true - settings: - clusterIngress: - domain: educates.example.com - tlsCertificateRef: - namespace: educates-secrets - name: educates-example-com-tls - caCertificateRef: - namespace: educates-secrets - name: educates-example-com-ca - clusterSecurity: - policyEngine: kyverno - workshopSecurity: - rulesEngine: kyverno diff --git a/carvel-packages/installer/scenarios/kind/test-kind-scenario-04/values.yaml b/carvel-packages/installer/scenarios/kind/test-kind-scenario-04/values.yaml deleted file mode 100644 index 12a091d57..000000000 --- a/carvel-packages/installer/scenarios/kind/test-kind-scenario-04/values.yaml +++ /dev/null @@ -1,12 +0,0 @@ -clusterInfrastructure: - provider: "kind" -clusterSecurity: - policyEngine: "kyverno" -clusterIngress: - domain: "educates.example.com" - tlsCertificateRef: - namespace: "educates-secrets" - name: "educates-example-com-tls" - caCertificateRef: - namespace: "educates-secrets" - name: "educates-example-com-ca" diff --git a/carvel-packages/installer/scenarios/kind/test-kind-scenario-04b/description.md b/carvel-packages/installer/scenarios/kind/test-kind-scenario-04b/description.md deleted file mode 100644 index d31ef88a1..000000000 --- a/carvel-packages/installer/scenarios/kind/test-kind-scenario-04b/description.md +++ /dev/null @@ -1 +0,0 @@ -kind with tlsCertificateRef and caCertificateRef for educates when they are in local secrets cache diff --git a/carvel-packages/installer/scenarios/kind/test-kind-scenario-04b/expected.yaml b/carvel-packages/installer/scenarios/kind/test-kind-scenario-04b/expected.yaml deleted file mode 100644 index dca194adf..000000000 --- a/carvel-packages/installer/scenarios/kind/test-kind-scenario-04b/expected.yaml +++ /dev/null @@ -1,43 +0,0 @@ -clusterPackages: - contour: - enabled: true - settings: - infraProvider: kind - contour: - replicas: 1 - configFileContents: - defaultHttpVersions: - - HTTP/1.1 - service: - type: ClusterIP - useHostPorts: true - cert-manager: - enabled: false - settings: {} - external-dns: - enabled: false - settings: {} - certs: - enabled: false - settings: {} - kyverno: - enabled: true - settings: {} - kapp-controller: - enabled: false - settings: {} - educates: - enabled: true - settings: - clusterIngress: - domain: educates.example.com - tlsCertificateRef: - namespace: educates-secrets - name: educates-example-com-fromcache-tls - caCertificateRef: - namespace: educates-secrets - name: educates-example-com-fromcache-ca - clusterSecurity: - policyEngine: kyverno - workshopSecurity: - rulesEngine: kyverno diff --git a/carvel-packages/installer/scenarios/kind/test-kind-scenario-04b/values.yaml b/carvel-packages/installer/scenarios/kind/test-kind-scenario-04b/values.yaml deleted file mode 100644 index e41122a03..000000000 --- a/carvel-packages/installer/scenarios/kind/test-kind-scenario-04b/values.yaml +++ /dev/null @@ -1,12 +0,0 @@ -clusterInfrastructure: - provider: "kind" -clusterSecurity: - policyEngine: "kyverno" -clusterIngress: - domain: "educates.example.com" - tlsCertificateRef: - namespace: "educates-secrets" - name: "educates-example-com-fromcache-tls" - caCertificateRef: - namespace: "educates-secrets" - name: "educates-example-com-fromcache-ca" diff --git a/carvel-packages/installer/scenarios/kind/test-kind-scenario-05/description.md b/carvel-packages/installer/scenarios/kind/test-kind-scenario-05/description.md deleted file mode 100644 index 6d9726c7f..000000000 --- a/carvel-packages/installer/scenarios/kind/test-kind-scenario-05/description.md +++ /dev/null @@ -1 +0,0 @@ -kind with tlsCertificate for educates diff --git a/carvel-packages/installer/scenarios/kind/test-kind-scenario-05/expected.yaml b/carvel-packages/installer/scenarios/kind/test-kind-scenario-05/expected.yaml deleted file mode 100644 index 05024d28e..000000000 --- a/carvel-packages/installer/scenarios/kind/test-kind-scenario-05/expected.yaml +++ /dev/null @@ -1,46 +0,0 @@ -clusterPackages: - contour: - enabled: true - settings: - infraProvider: kind - contour: - replicas: 1 - configFileContents: - defaultHttpVersions: - - HTTP/1.1 - service: - type: ClusterIP - useHostPorts: true - cert-manager: - enabled: false - settings: {} - external-dns: - enabled: false - settings: {} - certs: - enabled: false - settings: {} - kyverno: - enabled: true - settings: {} - kapp-controller: - enabled: false - settings: {} - educates: - enabled: true - settings: - clusterIngress: - domain: educates.example.com - tlsCertificate: - tls.crt: | - -----BEGIN CERTIFICATE----- - "TLS_CRT" - -----END CERTIFICATE----- - tls.key: | - -----BEGIN CERTIFICATE----- - "TLS_KEY" - -----END CERTIFICATE----- - clusterSecurity: - policyEngine: kyverno - workshopSecurity: - rulesEngine: kyverno diff --git a/carvel-packages/installer/scenarios/kind/test-kind-scenario-05/values.yaml b/carvel-packages/installer/scenarios/kind/test-kind-scenario-05/values.yaml deleted file mode 100644 index b6bd2ed51..000000000 --- a/carvel-packages/installer/scenarios/kind/test-kind-scenario-05/values.yaml +++ /dev/null @@ -1,15 +0,0 @@ -clusterInfrastructure: - provider: "kind" -clusterSecurity: - policyEngine: "kyverno" -clusterIngress: - domain: "educates.example.com" - tlsCertificate: - tls.crt: | - -----BEGIN CERTIFICATE----- - "TLS_CRT" - -----END CERTIFICATE----- - tls.key: | - -----BEGIN CERTIFICATE----- - "TLS_KEY" - -----END CERTIFICATE----- diff --git a/carvel-packages/installer/scenarios/kind/test-kind-scenario-06/description.md b/carvel-packages/installer/scenarios/kind/test-kind-scenario-06/description.md deleted file mode 100644 index 7f946ee89..000000000 --- a/carvel-packages/installer/scenarios/kind/test-kind-scenario-06/description.md +++ /dev/null @@ -1 +0,0 @@ -kind with tlsCertificate and caCertificate for educates diff --git a/carvel-packages/installer/scenarios/kind/test-kind-scenario-06/expected.yaml b/carvel-packages/installer/scenarios/kind/test-kind-scenario-06/expected.yaml deleted file mode 100644 index a70d8e221..000000000 --- a/carvel-packages/installer/scenarios/kind/test-kind-scenario-06/expected.yaml +++ /dev/null @@ -1,51 +0,0 @@ -clusterPackages: - contour: - enabled: true - settings: - infraProvider: kind - contour: - replicas: 1 - configFileContents: - defaultHttpVersions: - - HTTP/1.1 - service: - type: ClusterIP - useHostPorts: true - cert-manager: - enabled: false - settings: {} - external-dns: - enabled: false - settings: {} - certs: - enabled: false - settings: {} - kyverno: - enabled: true - settings: {} - kapp-controller: - enabled: false - settings: {} - educates: - enabled: true - settings: - clusterIngress: - domain: educates.example.com - tlsCertificate: - tls.crt: | - -----BEGIN CERTIFICATE----- - "TLS_CRT" - -----END CERTIFICATE----- - tls.key: | - -----BEGIN CERTIFICATE----- - "TLS_KEY" - -----END CERTIFICATE----- - caCertificate: - ca.crt: | - -----BEGIN CERTIFICATE----- - "CA_CRT" - -----END CERTIFICATE----- - clusterSecurity: - policyEngine: kyverno - workshopSecurity: - rulesEngine: kyverno diff --git a/carvel-packages/installer/scenarios/kind/test-kind-scenario-06/values.yaml b/carvel-packages/installer/scenarios/kind/test-kind-scenario-06/values.yaml deleted file mode 100644 index 6b5ef49ad..000000000 --- a/carvel-packages/installer/scenarios/kind/test-kind-scenario-06/values.yaml +++ /dev/null @@ -1,20 +0,0 @@ -clusterInfrastructure: - provider: "kind" -clusterSecurity: - policyEngine: "kyverno" -clusterIngress: - domain: "educates.example.com" - tlsCertificate: - tls.crt: | - -----BEGIN CERTIFICATE----- - "TLS_CRT" - -----END CERTIFICATE----- - tls.key: | - -----BEGIN CERTIFICATE----- - "TLS_KEY" - -----END CERTIFICATE----- - caCertificate: - ca.crt: | - -----BEGIN CERTIFICATE----- - "CA_CRT" - -----END CERTIFICATE----- diff --git a/carvel-packages/installer/scenarios/kind/test-kind-scenario-07/description.md b/carvel-packages/installer/scenarios/kind/test-kind-scenario-07/description.md deleted file mode 100644 index 3bc5fe6ad..000000000 --- a/carvel-packages/installer/scenarios/kind/test-kind-scenario-07/description.md +++ /dev/null @@ -1 +0,0 @@ -kind with infrastructure.caCertificateRef and cert-manager enabled diff --git a/carvel-packages/installer/scenarios/kind/test-kind-scenario-07/expected.yaml b/carvel-packages/installer/scenarios/kind/test-kind-scenario-07/expected.yaml deleted file mode 100644 index 96a197e5f..000000000 --- a/carvel-packages/installer/scenarios/kind/test-kind-scenario-07/expected.yaml +++ /dev/null @@ -1,52 +0,0 @@ -clusterPackages: - contour: - enabled: true - settings: - infraProvider: kind - contour: - replicas: 1 - configFileContents: - defaultHttpVersions: - - HTTP/1.1 - service: - type: ClusterIP - useHostPorts: true - cert-manager: - enabled: true - settings: - clusterResourceNamespace: educates-secrets - external-dns: - enabled: false - settings: {} - certs: - enabled: true - settings: - domains: - - educates.example.com - certProvider: local - local: - caCertificateRef: - name: educates-example-com-ca - namespace: educates-secrets - wildcardCertificateNamespace: educates-secrets - certmanagerClusterResourceNamespace: educates-secrets - kyverno: - enabled: true - settings: {} - kapp-controller: - enabled: false - settings: {} - educates: - enabled: true - settings: - clusterIngress: - domain: educates.example.com - caCertificateRef: - namespace: educates-secrets - name: educates-example-com-ca - caNodeInjector: - enabled: true - clusterSecurity: - policyEngine: kyverno - workshopSecurity: - rulesEngine: kyverno diff --git a/carvel-packages/installer/scenarios/kind/test-kind-scenario-07/values.yaml b/carvel-packages/installer/scenarios/kind/test-kind-scenario-07/values.yaml deleted file mode 100644 index 2d4ddd2d1..000000000 --- a/carvel-packages/installer/scenarios/kind/test-kind-scenario-07/values.yaml +++ /dev/null @@ -1,9 +0,0 @@ -clusterInfrastructure: - provider: "kind" - caCertificateRef: - name: "educates-example-com-ca" - namespace: "educates-secrets" -clusterSecurity: - policyEngine: "kyverno" -clusterIngress: - domain: "educates.example.com" diff --git a/carvel-packages/installer/scenarios/kind/test-kind-scenario-07b/description.md b/carvel-packages/installer/scenarios/kind/test-kind-scenario-07b/description.md deleted file mode 100644 index 0c11936ba..000000000 --- a/carvel-packages/installer/scenarios/kind/test-kind-scenario-07b/description.md +++ /dev/null @@ -1,2 +0,0 @@ -kind with infrastructure.caCertificateRef and cert-manager enabled when they are in local secrets cache -TODO: When pushing the local secrets in cache we need to configure educates to use the secret generated by cert-manager's wildcard cluster issuer diff --git a/carvel-packages/installer/scenarios/kind/test-kind-scenario-07b/expected.yaml b/carvel-packages/installer/scenarios/kind/test-kind-scenario-07b/expected.yaml deleted file mode 100644 index 7eee50292..000000000 --- a/carvel-packages/installer/scenarios/kind/test-kind-scenario-07b/expected.yaml +++ /dev/null @@ -1,52 +0,0 @@ -clusterPackages: - contour: - enabled: true - settings: - infraProvider: kind - contour: - replicas: 1 - configFileContents: - defaultHttpVersions: - - HTTP/1.1 - service: - type: ClusterIP - useHostPorts: true - cert-manager: - enabled: true - settings: - clusterResourceNamespace: educates-secrets - external-dns: - enabled: false - settings: {} - certs: - enabled: true - settings: - domains: - - educates.example.com - certProvider: local - local: - caCertificateRef: - name: educates-example-com-fromcache-ca - namespace: educates-secrets - wildcardCertificateNamespace: educates-secrets - certmanagerClusterResourceNamespace: educates-secrets - kyverno: - enabled: true - settings: {} - kapp-controller: - enabled: false - settings: {} - educates: - enabled: true - settings: - clusterIngress: - domain: educates.example.com - caCertificateRef: - namespace: educates-secrets - name: educates-example-com-fromcache-ca - caNodeInjector: - enabled: true - clusterSecurity: - policyEngine: kyverno - workshopSecurity: - rulesEngine: kyverno diff --git a/carvel-packages/installer/scenarios/kind/test-kind-scenario-07b/values.yaml b/carvel-packages/installer/scenarios/kind/test-kind-scenario-07b/values.yaml deleted file mode 100644 index 87b59949b..000000000 --- a/carvel-packages/installer/scenarios/kind/test-kind-scenario-07b/values.yaml +++ /dev/null @@ -1,9 +0,0 @@ -clusterInfrastructure: - provider: "kind" - caCertificateRef: - name: "educates-example-com-fromcache-ca" - namespace: "educates-secrets" -clusterSecurity: - policyEngine: "kyverno" -clusterIngress: - domain: "educates.example.com" diff --git a/carvel-packages/installer/scenarios/kind/test-kind-scenario-07c/description.md b/carvel-packages/installer/scenarios/kind/test-kind-scenario-07c/description.md deleted file mode 100644 index 24904d59b..000000000 --- a/carvel-packages/installer/scenarios/kind/test-kind-scenario-07c/description.md +++ /dev/null @@ -1,3 +0,0 @@ -kind with infrastructure.caCertificateRef and cert-manager enabled when they are in local secrets cache -and educates explicitly disabled -TODO: When pushing the local secrets in cache we need to configure educates to use the secret generated by cert-manager's wildcard cluster issuer diff --git a/carvel-packages/installer/scenarios/kind/test-kind-scenario-07c/expected.yaml b/carvel-packages/installer/scenarios/kind/test-kind-scenario-07c/expected.yaml deleted file mode 100644 index 1ac6069dc..000000000 --- a/carvel-packages/installer/scenarios/kind/test-kind-scenario-07c/expected.yaml +++ /dev/null @@ -1,41 +0,0 @@ -clusterPackages: - contour: - enabled: true - settings: - infraProvider: kind - contour: - replicas: 1 - configFileContents: - defaultHttpVersions: - - HTTP/1.1 - service: - type: ClusterIP - useHostPorts: true - cert-manager: - enabled: true - settings: - clusterResourceNamespace: educates-secrets - external-dns: - enabled: false - settings: {} - certs: - enabled: true - settings: - domains: - - educates.example.com - certProvider: local - local: - caCertificateRef: - name: educates-example-com-fromcache-ca - namespace: educates-secrets - wildcardCertificateNamespace: educates-secrets - certmanagerClusterResourceNamespace: educates-secrets - kyverno: - enabled: true - settings: {} - kapp-controller: - enabled: false - settings: {} - educates: - enabled: false - settings: {} \ No newline at end of file diff --git a/carvel-packages/installer/scenarios/kind/test-kind-scenario-07c/values.yaml b/carvel-packages/installer/scenarios/kind/test-kind-scenario-07c/values.yaml deleted file mode 100644 index 2b20073ab..000000000 --- a/carvel-packages/installer/scenarios/kind/test-kind-scenario-07c/values.yaml +++ /dev/null @@ -1,12 +0,0 @@ -clusterInfrastructure: - provider: "kind" - caCertificateRef: - name: "educates-example-com-fromcache-ca" - namespace: "educates-secrets" -clusterPackages: - educates: - enabled: false -clusterSecurity: - policyEngine: "kyverno" -clusterIngress: - domain: "educates.example.com" diff --git a/carvel-packages/installer/scenarios/kind/test-kind-scenario-08/description.md b/carvel-packages/installer/scenarios/kind/test-kind-scenario-08/description.md deleted file mode 100644 index edaf25663..000000000 --- a/carvel-packages/installer/scenarios/kind/test-kind-scenario-08/description.md +++ /dev/null @@ -1 +0,0 @@ -kind with without educates diff --git a/carvel-packages/installer/scenarios/kind/test-kind-scenario-08/expected.yaml b/carvel-packages/installer/scenarios/kind/test-kind-scenario-08/expected.yaml deleted file mode 100644 index a418e5ed6..000000000 --- a/carvel-packages/installer/scenarios/kind/test-kind-scenario-08/expected.yaml +++ /dev/null @@ -1,31 +0,0 @@ -clusterPackages: - contour: - enabled: true - settings: - infraProvider: kind - contour: - replicas: 1 - configFileContents: - defaultHttpVersions: - - HTTP/1.1 - service: - type: ClusterIP - useHostPorts: true - cert-manager: - enabled: false - settings: {} - external-dns: - enabled: false - settings: {} - certs: - enabled: false - settings: {} - kyverno: - enabled: true - settings: {} - kapp-controller: - enabled: false - settings: {} - educates: - enabled: false - settings: {} diff --git a/carvel-packages/installer/scenarios/kind/test-kind-scenario-08/values.yaml b/carvel-packages/installer/scenarios/kind/test-kind-scenario-08/values.yaml deleted file mode 100644 index 3f5336d1b..000000000 --- a/carvel-packages/installer/scenarios/kind/test-kind-scenario-08/values.yaml +++ /dev/null @@ -1,9 +0,0 @@ -clusterPackages: - educates: - enabled: false -clusterInfrastructure: - provider: "kind" -clusterSecurity: - policyEngine: "kyverno" -clusterIngress: - domain: "educates.example.com" diff --git a/carvel-packages/installer/scenarios/kind/test-kind-scenario-08b/description.md b/carvel-packages/installer/scenarios/kind/test-kind-scenario-08b/description.md deleted file mode 100644 index 636f542c8..000000000 --- a/carvel-packages/installer/scenarios/kind/test-kind-scenario-08b/description.md +++ /dev/null @@ -1 +0,0 @@ -kind without educates and without using a clusterSecurity policy engine diff --git a/carvel-packages/installer/scenarios/kind/test-kind-scenario-08b/expected.yaml b/carvel-packages/installer/scenarios/kind/test-kind-scenario-08b/expected.yaml deleted file mode 100644 index a418e5ed6..000000000 --- a/carvel-packages/installer/scenarios/kind/test-kind-scenario-08b/expected.yaml +++ /dev/null @@ -1,31 +0,0 @@ -clusterPackages: - contour: - enabled: true - settings: - infraProvider: kind - contour: - replicas: 1 - configFileContents: - defaultHttpVersions: - - HTTP/1.1 - service: - type: ClusterIP - useHostPorts: true - cert-manager: - enabled: false - settings: {} - external-dns: - enabled: false - settings: {} - certs: - enabled: false - settings: {} - kyverno: - enabled: true - settings: {} - kapp-controller: - enabled: false - settings: {} - educates: - enabled: false - settings: {} diff --git a/carvel-packages/installer/scenarios/kind/test-kind-scenario-08b/values.yaml b/carvel-packages/installer/scenarios/kind/test-kind-scenario-08b/values.yaml deleted file mode 100644 index 2ce8b0365..000000000 --- a/carvel-packages/installer/scenarios/kind/test-kind-scenario-08b/values.yaml +++ /dev/null @@ -1,9 +0,0 @@ -clusterPackages: - educates: - enabled: false -clusterInfrastructure: - provider: "kind" -clusterSecurity: - policyEngine: "none" -clusterIngress: - domain: "educates.example.com" diff --git a/carvel-packages/installer/scenarios/kind/test-kind-scenario-08c/description.md b/carvel-packages/installer/scenarios/kind/test-kind-scenario-08c/description.md deleted file mode 100644 index dd4fe389b..000000000 --- a/carvel-packages/installer/scenarios/kind/test-kind-scenario-08c/description.md +++ /dev/null @@ -1,2 +0,0 @@ -kind without educates package without using a clusterSecurity policy engine -but with tls certificate provided for the domain diff --git a/carvel-packages/installer/scenarios/kind/test-kind-scenario-08c/expected.yaml b/carvel-packages/installer/scenarios/kind/test-kind-scenario-08c/expected.yaml deleted file mode 100644 index a418e5ed6..000000000 --- a/carvel-packages/installer/scenarios/kind/test-kind-scenario-08c/expected.yaml +++ /dev/null @@ -1,31 +0,0 @@ -clusterPackages: - contour: - enabled: true - settings: - infraProvider: kind - contour: - replicas: 1 - configFileContents: - defaultHttpVersions: - - HTTP/1.1 - service: - type: ClusterIP - useHostPorts: true - cert-manager: - enabled: false - settings: {} - external-dns: - enabled: false - settings: {} - certs: - enabled: false - settings: {} - kyverno: - enabled: true - settings: {} - kapp-controller: - enabled: false - settings: {} - educates: - enabled: false - settings: {} diff --git a/carvel-packages/installer/scenarios/kind/test-kind-scenario-08c/values.yaml b/carvel-packages/installer/scenarios/kind/test-kind-scenario-08c/values.yaml deleted file mode 100644 index 9a8e46857..000000000 --- a/carvel-packages/installer/scenarios/kind/test-kind-scenario-08c/values.yaml +++ /dev/null @@ -1,18 +0,0 @@ -clusterPackages: - educates: - enabled: false -clusterInfrastructure: - provider: "kind" -clusterSecurity: - policyEngine: "none" -clusterIngress: - domain: "educates.example.com" - tlsCertificate: - tls.crt: | - -----BEGIN CERTIFICATE----- - "TLS_CRT" - -----END CERTIFICATE----- - tls.key: | - -----BEGIN CERTIFICATE----- - "TLS_KEY" - -----END CERTIFICATE----- diff --git a/carvel-packages/installer/scenarios/kind/test-kind-scenario-08d/description.md b/carvel-packages/installer/scenarios/kind/test-kind-scenario-08d/description.md deleted file mode 100644 index e8a11f29d..000000000 --- a/carvel-packages/installer/scenarios/kind/test-kind-scenario-08d/description.md +++ /dev/null @@ -1,2 +0,0 @@ -kind without educates package and kyverno package and using kyverno clusterSecurity policy engine. -This should not re-enable kyverno since educates is disabled. diff --git a/carvel-packages/installer/scenarios/kind/test-kind-scenario-08d/expected.yaml b/carvel-packages/installer/scenarios/kind/test-kind-scenario-08d/expected.yaml deleted file mode 100644 index 27d97363b..000000000 --- a/carvel-packages/installer/scenarios/kind/test-kind-scenario-08d/expected.yaml +++ /dev/null @@ -1,31 +0,0 @@ -clusterPackages: - contour: - enabled: true - settings: - infraProvider: kind - contour: - replicas: 1 - configFileContents: - defaultHttpVersions: - - HTTP/1.1 - service: - type: ClusterIP - useHostPorts: true - cert-manager: - enabled: false - settings: {} - external-dns: - enabled: false - settings: {} - certs: - enabled: false - settings: {} - kyverno: - enabled: false - settings: {} - kapp-controller: - enabled: false - settings: {} - educates: - enabled: false - settings: {} diff --git a/carvel-packages/installer/scenarios/kind/test-kind-scenario-08d/values.yaml b/carvel-packages/installer/scenarios/kind/test-kind-scenario-08d/values.yaml deleted file mode 100644 index 46528dcac..000000000 --- a/carvel-packages/installer/scenarios/kind/test-kind-scenario-08d/values.yaml +++ /dev/null @@ -1,20 +0,0 @@ -clusterPackages: - kyverno: - enabled: false - educates: - enabled: false -clusterInfrastructure: - provider: "kind" -clusterSecurity: - policyEngine: "kyverno" -clusterIngress: - domain: "educates.example.com" - tlsCertificate: - tls.crt: | - -----BEGIN CERTIFICATE----- - "TLS_CRT" - -----END CERTIFICATE----- - tls.key: | - -----BEGIN CERTIFICATE----- - "TLS_KEY" - -----END CERTIFICATE----- diff --git a/carvel-packages/installer/scenarios/kind/test-kind-scenario-09/description.md b/carvel-packages/installer/scenarios/kind/test-kind-scenario-09/description.md deleted file mode 100644 index 29b7e3ba0..000000000 --- a/carvel-packages/installer/scenarios/kind/test-kind-scenario-09/description.md +++ /dev/null @@ -1 +0,0 @@ -kind with imageRegistry with no namespace defined diff --git a/carvel-packages/installer/scenarios/kind/test-kind-scenario-09/expected.yaml b/carvel-packages/installer/scenarios/kind/test-kind-scenario-09/expected.yaml deleted file mode 100644 index 778d0eea7..000000000 --- a/carvel-packages/installer/scenarios/kind/test-kind-scenario-09/expected.yaml +++ /dev/null @@ -1,40 +0,0 @@ -clusterPackages: - contour: - enabled: true - settings: - infraProvider: kind - contour: - replicas: 1 - configFileContents: - defaultHttpVersions: - - HTTP/1.1 - service: - type: ClusterIP - useHostPorts: true - cert-manager: - enabled: false - settings: {} - external-dns: - enabled: false - settings: {} - certs: - enabled: false - settings: {} - kyverno: - enabled: true - settings: {} - kapp-controller: - enabled: false - settings: {} - educates: - enabled: true - settings: - imageRegistry: - namespace: "" - host: kind-registry - clusterIngress: - domain: educates.example.com - clusterSecurity: - policyEngine: kyverno - workshopSecurity: - rulesEngine: kyverno \ No newline at end of file diff --git a/carvel-packages/installer/scenarios/kind/test-kind-scenario-09/values.yaml b/carvel-packages/installer/scenarios/kind/test-kind-scenario-09/values.yaml deleted file mode 100644 index 37d5915d9..000000000 --- a/carvel-packages/installer/scenarios/kind/test-kind-scenario-09/values.yaml +++ /dev/null @@ -1,6 +0,0 @@ -clusterInfrastructure: - provider: "kind" -imageRegistry: - host: "kind-registry" -clusterIngress: - domain: "educates.example.com" \ No newline at end of file diff --git a/carvel-packages/installer/scenarios/kind/test-kind-scenario-09b/description.md b/carvel-packages/installer/scenarios/kind/test-kind-scenario-09b/description.md deleted file mode 100644 index f23985daf..000000000 --- a/carvel-packages/installer/scenarios/kind/test-kind-scenario-09b/description.md +++ /dev/null @@ -1 +0,0 @@ -kind with imageRegistry with namespace defined diff --git a/carvel-packages/installer/scenarios/kind/test-kind-scenario-09b/expected.yaml b/carvel-packages/installer/scenarios/kind/test-kind-scenario-09b/expected.yaml deleted file mode 100644 index 552ce2acd..000000000 --- a/carvel-packages/installer/scenarios/kind/test-kind-scenario-09b/expected.yaml +++ /dev/null @@ -1,40 +0,0 @@ -clusterPackages: - contour: - enabled: true - settings: - infraProvider: kind - contour: - replicas: 1 - configFileContents: - defaultHttpVersions: - - HTTP/1.1 - service: - type: ClusterIP - useHostPorts: true - cert-manager: - enabled: false - settings: {} - external-dns: - enabled: false - settings: {} - certs: - enabled: false - settings: {} - kyverno: - enabled: true - settings: {} - kapp-controller: - enabled: false - settings: {} - educates: - enabled: true - settings: - imageRegistry: - namespace: educates - host: kind-registry - clusterIngress: - domain: educates.example.com - clusterSecurity: - policyEngine: kyverno - workshopSecurity: - rulesEngine: kyverno \ No newline at end of file diff --git a/carvel-packages/installer/scenarios/kind/test-kind-scenario-09b/values.yaml b/carvel-packages/installer/scenarios/kind/test-kind-scenario-09b/values.yaml deleted file mode 100644 index 250f9274b..000000000 --- a/carvel-packages/installer/scenarios/kind/test-kind-scenario-09b/values.yaml +++ /dev/null @@ -1,7 +0,0 @@ -clusterInfrastructure: - provider: "kind" -imageRegistry: - host: "kind-registry" - namespace: "educates" -clusterIngress: - domain: "educates.example.com" \ No newline at end of file diff --git a/carvel-packages/installer/scenarios/kind/test-kind-scenario-10/description.md b/carvel-packages/installer/scenarios/kind/test-kind-scenario-10/description.md deleted file mode 100644 index ec652ab9d..000000000 --- a/carvel-packages/installer/scenarios/kind/test-kind-scenario-10/description.md +++ /dev/null @@ -1 +0,0 @@ -kind with imagePuller disabled diff --git a/carvel-packages/installer/scenarios/kind/test-kind-scenario-10/expected.yaml b/carvel-packages/installer/scenarios/kind/test-kind-scenario-10/expected.yaml deleted file mode 100644 index 473d53409..000000000 --- a/carvel-packages/installer/scenarios/kind/test-kind-scenario-10/expected.yaml +++ /dev/null @@ -1,41 +0,0 @@ -clusterPackages: - contour: - enabled: true - settings: - infraProvider: kind - contour: - replicas: 1 - configFileContents: - defaultHttpVersions: - - HTTP/1.1 - service: - type: ClusterIP - useHostPorts: true - cert-manager: - enabled: false - settings: {} - external-dns: - enabled: false - settings: {} - certs: - enabled: false - settings: {} - kyverno: - enabled: true - settings: {} - kapp-controller: - enabled: false - settings: {} - educates: - enabled: true - settings: - clusterIngress: - domain: educates.example.com - clusterSecurity: - policyEngine: kyverno - workshopSecurity: - rulesEngine: kyverno - imagePuller: - enabled: false - prePullImages: - - base-environment \ No newline at end of file diff --git a/carvel-packages/installer/scenarios/kind/test-kind-scenario-10/values.yaml b/carvel-packages/installer/scenarios/kind/test-kind-scenario-10/values.yaml deleted file mode 100644 index c598d42b6..000000000 --- a/carvel-packages/installer/scenarios/kind/test-kind-scenario-10/values.yaml +++ /dev/null @@ -1,6 +0,0 @@ -clusterInfrastructure: - provider: "kind" -clusterIngress: - domain: "educates.example.com" -imagePuller: - enabled: false \ No newline at end of file diff --git a/carvel-packages/installer/scenarios/kind/test-kind-scenario-10b/description.md b/carvel-packages/installer/scenarios/kind/test-kind-scenario-10b/description.md deleted file mode 100644 index 441f2e57e..000000000 --- a/carvel-packages/installer/scenarios/kind/test-kind-scenario-10b/description.md +++ /dev/null @@ -1 +0,0 @@ -kind with imagePuller enabled diff --git a/carvel-packages/installer/scenarios/kind/test-kind-scenario-10b/expected.yaml b/carvel-packages/installer/scenarios/kind/test-kind-scenario-10b/expected.yaml deleted file mode 100644 index 30423cc99..000000000 --- a/carvel-packages/installer/scenarios/kind/test-kind-scenario-10b/expected.yaml +++ /dev/null @@ -1,41 +0,0 @@ -clusterPackages: - contour: - enabled: true - settings: - infraProvider: kind - contour: - replicas: 1 - configFileContents: - defaultHttpVersions: - - HTTP/1.1 - service: - type: ClusterIP - useHostPorts: true - cert-manager: - enabled: false - settings: {} - external-dns: - enabled: false - settings: {} - certs: - enabled: false - settings: {} - kyverno: - enabled: true - settings: {} - kapp-controller: - enabled: false - settings: {} - educates: - enabled: true - settings: - clusterIngress: - domain: educates.example.com - clusterSecurity: - policyEngine: kyverno - workshopSecurity: - rulesEngine: kyverno - imagePuller: - enabled: true - prePullImages: - - base-environment \ No newline at end of file diff --git a/carvel-packages/installer/scenarios/kind/test-kind-scenario-10b/values.yaml b/carvel-packages/installer/scenarios/kind/test-kind-scenario-10b/values.yaml deleted file mode 100644 index 3da5fcb8a..000000000 --- a/carvel-packages/installer/scenarios/kind/test-kind-scenario-10b/values.yaml +++ /dev/null @@ -1,6 +0,0 @@ -clusterInfrastructure: - provider: "kind" -imagePuller: - enabled: true -clusterIngress: - domain: "educates.example.com" \ No newline at end of file diff --git a/carvel-packages/installer/scenarios/kind/test-kind-scenario-10c/description.md b/carvel-packages/installer/scenarios/kind/test-kind-scenario-10c/description.md deleted file mode 100644 index 69d3971b5..000000000 --- a/carvel-packages/installer/scenarios/kind/test-kind-scenario-10c/description.md +++ /dev/null @@ -1 +0,0 @@ -kind with imagePuller enabled and prePullImage provided diff --git a/carvel-packages/installer/scenarios/kind/test-kind-scenario-10c/expected.yaml b/carvel-packages/installer/scenarios/kind/test-kind-scenario-10c/expected.yaml deleted file mode 100644 index f72366cd7..000000000 --- a/carvel-packages/installer/scenarios/kind/test-kind-scenario-10c/expected.yaml +++ /dev/null @@ -1,41 +0,0 @@ -clusterPackages: - contour: - enabled: true - settings: - infraProvider: kind - contour: - replicas: 1 - configFileContents: - defaultHttpVersions: - - HTTP/1.1 - service: - type: ClusterIP - useHostPorts: true - cert-manager: - enabled: false - settings: {} - external-dns: - enabled: false - settings: {} - certs: - enabled: false - settings: {} - kyverno: - enabled: true - settings: {} - kapp-controller: - enabled: false - settings: {} - educates: - enabled: true - settings: - clusterIngress: - domain: educates.example.com - clusterSecurity: - policyEngine: kyverno - workshopSecurity: - rulesEngine: kyverno - imagePuller: - enabled: true - prePullImages: - - jdk17-environment \ No newline at end of file diff --git a/carvel-packages/installer/scenarios/kind/test-kind-scenario-10c/values.yaml b/carvel-packages/installer/scenarios/kind/test-kind-scenario-10c/values.yaml deleted file mode 100644 index 7de29a216..000000000 --- a/carvel-packages/installer/scenarios/kind/test-kind-scenario-10c/values.yaml +++ /dev/null @@ -1,8 +0,0 @@ -clusterInfrastructure: - provider: "kind" -imagePuller: - enabled: true - prePullImages: - - "jdk17-environment" -clusterIngress: - domain: "educates.example.com" \ No newline at end of file diff --git a/carvel-packages/installer/scenarios/kind/test-kind-scenario-11/description.md b/carvel-packages/installer/scenarios/kind/test-kind-scenario-11/description.md deleted file mode 100644 index 30f7f0ccd..000000000 --- a/carvel-packages/installer/scenarios/kind/test-kind-scenario-11/description.md +++ /dev/null @@ -1 +0,0 @@ -kind with kapp-controller enabled diff --git a/carvel-packages/installer/scenarios/kind/test-kind-scenario-11/expected.yaml b/carvel-packages/installer/scenarios/kind/test-kind-scenario-11/expected.yaml deleted file mode 100644 index 88dd76633..000000000 --- a/carvel-packages/installer/scenarios/kind/test-kind-scenario-11/expected.yaml +++ /dev/null @@ -1,37 +0,0 @@ -clusterPackages: - contour: - enabled: true - settings: - infraProvider: kind - contour: - replicas: 1 - configFileContents: - defaultHttpVersions: - - HTTP/1.1 - service: - type: ClusterIP - useHostPorts: true - cert-manager: - enabled: false - settings: {} - external-dns: - enabled: false - settings: {} - certs: - enabled: false - settings: {} - kyverno: - enabled: true - settings: {} - kapp-controller: - enabled: true - settings: {} - educates: - enabled: true - settings: - clusterIngress: - domain: educates.example.com - clusterSecurity: - policyEngine: kyverno - workshopSecurity: - rulesEngine: kyverno \ No newline at end of file diff --git a/carvel-packages/installer/scenarios/kind/test-kind-scenario-11/values.yaml b/carvel-packages/installer/scenarios/kind/test-kind-scenario-11/values.yaml deleted file mode 100644 index 536f2bd23..000000000 --- a/carvel-packages/installer/scenarios/kind/test-kind-scenario-11/values.yaml +++ /dev/null @@ -1,7 +0,0 @@ -clusterInfrastructure: - provider: "kind" -clusterIngress: - domain: "educates.example.com" -clusterPackages: - kapp-controller: - enabled: true diff --git a/carvel-packages/installer/scenarios/kind/test-kind-scenario-12/description.md b/carvel-packages/installer/scenarios/kind/test-kind-scenario-12/description.md deleted file mode 100644 index 1b58b3af6..000000000 --- a/carvel-packages/installer/scenarios/kind/test-kind-scenario-12/description.md +++ /dev/null @@ -1 +0,0 @@ -kind with educates mixture of top-level values and clusterPackage values diff --git a/carvel-packages/installer/scenarios/kind/test-kind-scenario-12/expected.yaml b/carvel-packages/installer/scenarios/kind/test-kind-scenario-12/expected.yaml deleted file mode 100644 index ad3e4cd06..000000000 --- a/carvel-packages/installer/scenarios/kind/test-kind-scenario-12/expected.yaml +++ /dev/null @@ -1,38 +0,0 @@ -clusterPackages: - contour: - enabled: true - settings: - infraProvider: kind - contour: - replicas: 1 - configFileContents: - defaultHttpVersions: - - HTTP/1.1 - service: - type: ClusterIP - useHostPorts: true - cert-manager: - enabled: false - settings: {} - external-dns: - enabled: false - settings: {} - certs: - enabled: false - settings: {} - kyverno: - enabled: true - settings: {} - kapp-controller: - enabled: false - settings: {} - educates: - enabled: true - settings: - clusterIngress: - domain: educates.example.com - class: clusterIngressClass - clusterSecurity: - policyEngine: kyverno - workshopSecurity: - rulesEngine: kyverno \ No newline at end of file diff --git a/carvel-packages/installer/scenarios/kind/test-kind-scenario-12/values.yaml b/carvel-packages/installer/scenarios/kind/test-kind-scenario-12/values.yaml deleted file mode 100644 index 22e8b2abf..000000000 --- a/carvel-packages/installer/scenarios/kind/test-kind-scenario-12/values.yaml +++ /dev/null @@ -1,9 +0,0 @@ -clusterInfrastructure: - provider: "kind" -clusterPackages: - educates: - settings: - clusterIngress: - domain: "educates.example.com" -clusterIngress: - class: "clusterIngressClass" diff --git a/carvel-packages/installer/scenarios/kind/test-kind-scenario-12b/description.md b/carvel-packages/installer/scenarios/kind/test-kind-scenario-12b/description.md deleted file mode 100644 index b1fa96a47..000000000 --- a/carvel-packages/installer/scenarios/kind/test-kind-scenario-12b/description.md +++ /dev/null @@ -1,2 +0,0 @@ -kind with educates mixture of top-level values and clusterPackage values. -Top level values are the ones to remain in case both are provided diff --git a/carvel-packages/installer/scenarios/kind/test-kind-scenario-12b/expected.yaml b/carvel-packages/installer/scenarios/kind/test-kind-scenario-12b/expected.yaml deleted file mode 100644 index fd0176993..000000000 --- a/carvel-packages/installer/scenarios/kind/test-kind-scenario-12b/expected.yaml +++ /dev/null @@ -1,37 +0,0 @@ -clusterPackages: - contour: - enabled: true - settings: - infraProvider: kind - contour: - replicas: 1 - configFileContents: - defaultHttpVersions: - - HTTP/1.1 - service: - type: ClusterIP - useHostPorts: true - cert-manager: - enabled: false - settings: {} - external-dns: - enabled: false - settings: {} - certs: - enabled: false - settings: {} - kyverno: - enabled: true - settings: {} - kapp-controller: - enabled: false - settings: {} - educates: - enabled: true - settings: - clusterIngress: - domain: THIS.domain.should.remain - clusterSecurity: - policyEngine: kyverno - workshopSecurity: - rulesEngine: kyverno \ No newline at end of file diff --git a/carvel-packages/installer/scenarios/kind/test-kind-scenario-12b/values.yaml b/carvel-packages/installer/scenarios/kind/test-kind-scenario-12b/values.yaml deleted file mode 100644 index d556a468e..000000000 --- a/carvel-packages/installer/scenarios/kind/test-kind-scenario-12b/values.yaml +++ /dev/null @@ -1,10 +0,0 @@ -clusterInfrastructure: - provider: "kind" -clusterPackages: - educates: - enabled: true - settings: - clusterIngress: - domain: "educates.example.com" -clusterIngress: - domain: "THIS.domain.should.remain" diff --git a/carvel-packages/installer/scenarios/kind/test-kind-scenario-12c/description.md b/carvel-packages/installer/scenarios/kind/test-kind-scenario-12c/description.md deleted file mode 100644 index b1fa96a47..000000000 --- a/carvel-packages/installer/scenarios/kind/test-kind-scenario-12c/description.md +++ /dev/null @@ -1,2 +0,0 @@ -kind with educates mixture of top-level values and clusterPackage values. -Top level values are the ones to remain in case both are provided diff --git a/carvel-packages/installer/scenarios/kind/test-kind-scenario-12c/expected.yaml b/carvel-packages/installer/scenarios/kind/test-kind-scenario-12c/expected.yaml deleted file mode 100644 index de47fb62f..000000000 --- a/carvel-packages/installer/scenarios/kind/test-kind-scenario-12c/expected.yaml +++ /dev/null @@ -1,40 +0,0 @@ -clusterPackages: - contour: - enabled: true - settings: - infraProvider: kind - contour: - replicas: 1 - configFileContents: - defaultHttpVersions: - - HTTP/1.1 - service: - type: ClusterIP - useHostPorts: true - cert-manager: - enabled: false - settings: {} - external-dns: - enabled: false - settings: {} - certs: - enabled: false - settings: {} - kyverno: - enabled: true - settings: {} - kapp-controller: - enabled: false - settings: {} - educates: - enabled: true - settings: - clusterIngress: - domain: THIS.domain.should.remain - clusterSecurity: - policyEngine: kyverno - workshopSecurity: - rulesEngine: kyverno - lookupService: - enabled: true - ingressPrefix: THIS_SHOULD_REMAIN diff --git a/carvel-packages/installer/scenarios/kind/test-kind-scenario-12c/values.yaml b/carvel-packages/installer/scenarios/kind/test-kind-scenario-12c/values.yaml deleted file mode 100644 index 479eadea2..000000000 --- a/carvel-packages/installer/scenarios/kind/test-kind-scenario-12c/values.yaml +++ /dev/null @@ -1,16 +0,0 @@ -clusterInfrastructure: - provider: "kind" -clusterPackages: - educates: - enabled: true - settings: - clusterIngress: - domain: "educates.example.com" - lookupService: - enabled: false - ingressPrefix: "THIS_SHOULD_GO_AWAY" -clusterIngress: - domain: "THIS.domain.should.remain" -lookupService: - enabled: true - ingressPrefix: "THIS_SHOULD_REMAIN" diff --git a/carvel-packages/installer/scenarios/kind/test-kind-scenario-13/description.md b/carvel-packages/installer/scenarios/kind/test-kind-scenario-13/description.md deleted file mode 100644 index 60a69097e..000000000 --- a/carvel-packages/installer/scenarios/kind/test-kind-scenario-13/description.md +++ /dev/null @@ -1,2 +0,0 @@ -kind using customized contour config and kapp-controller enabled -(Contour config would be defaulted and provided will not be used) diff --git a/carvel-packages/installer/scenarios/kind/test-kind-scenario-13/expected.yaml b/carvel-packages/installer/scenarios/kind/test-kind-scenario-13/expected.yaml deleted file mode 100644 index 896da4938..000000000 --- a/carvel-packages/installer/scenarios/kind/test-kind-scenario-13/expected.yaml +++ /dev/null @@ -1,37 +0,0 @@ -clusterPackages: - contour: - enabled: true - settings: - infraProvider: kind - contour: - replicas: 1 - configFileContents: - defaultHttpVersions: - - HTTP/1.1 - service: - type: ClusterIP - useHostPorts: true - cert-manager: - enabled: false - settings: {} - external-dns: - enabled: false - settings: {} - certs: - enabled: false - settings: {} - kyverno: - enabled: true - settings: {} - kapp-controller: - enabled: true - settings: {} - educates: - enabled: true - settings: - clusterIngress: - domain: educates.example.com - clusterSecurity: - policyEngine: kyverno - workshopSecurity: - rulesEngine: kyverno diff --git a/carvel-packages/installer/scenarios/kind/test-kind-scenario-13/values.yaml b/carvel-packages/installer/scenarios/kind/test-kind-scenario-13/values.yaml deleted file mode 100644 index c4c50749f..000000000 --- a/carvel-packages/installer/scenarios/kind/test-kind-scenario-13/values.yaml +++ /dev/null @@ -1,16 +0,0 @@ ---- -clusterInfrastructure: - provider: "kind" -clusterPackages: - contour: - enabled: true - settings: - configFileContents: - defaultHttpVersions: - - "HTTP/1.1" - kapp-controller: - enabled: true -clusterSecurity: - policyEngine: "kyverno" -clusterIngress: - domain: "educates.example.com" diff --git a/carvel-packages/installer/scenarios/minica/educates.example.com/cert.pem b/carvel-packages/installer/scenarios/minica/educates.example.com/cert.pem deleted file mode 100644 index e9a895a98..000000000 --- a/carvel-packages/installer/scenarios/minica/educates.example.com/cert.pem +++ /dev/null @@ -1,20 +0,0 @@ ------BEGIN CERTIFICATE----- -MIIDQzCCAiugAwIBAgIILFi6lR0CxhowDQYJKoZIhvcNAQELBQAwIDEeMBwGA1UE -AxMVbWluaWNhIHJvb3QgY2EgMWEzZGQyMB4XDTI0MDMwNTE2MDk0NVoXDTI2MDQw -NDE1MDk0NVowHzEdMBsGA1UEAxMUZWR1Y2F0ZXMuZXhhbXBsZS5jb20wggEiMA0G -CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC0aQ2Cb8DNpRXPqObdK9NeNCJMpTsN -efjIwCBu6pBj4hWpcqea75Y1z0dIz8fM0Zec/SNUyFbcUOEAEkf56MrKKy+gmQWI -TUp+EzfyL2vwmpPedBiYSbM6LFo+0kDBvek65PbTD7ZFKcM/6D2+EJG1ibjjQIPV -lmLd7311r8JRCzBVOrq41I5KaPOZ4D8VvMOPyXJlMk2YC5T8YHuBhTgwPa9mbJel -rHQVJHfZ725VTDtDVxepSwNDV49CciahbMvErdnxEOxmGELz+P79P4EgustyZoY2 -CyLWddYduxMQNIVxOrfqnfYA5dSxdpYGUhlDcLN2O30rzQbDOxEKhsL1AgMBAAGj -gYEwfzAOBgNVHQ8BAf8EBAMCBaAwHQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsGAQUF -BwMCMAwGA1UdEwEB/wQCMAAwHwYDVR0jBBgwFoAUNVdfc/wUzJvMF5o5jwbLuWq6 -vkgwHwYDVR0RBBgwFoIUZWR1Y2F0ZXMuZXhhbXBsZS5jb20wDQYJKoZIhvcNAQEL -BQADggEBAG98NSBc3MEyr6V3g5QhXOl7vDoNiGOP5i6EGxnoUQ5qLjcdY9ANdSmr -y465GPgHwV6G99SJWbXXaW2+qDOiGYsAJax+uSEoj6UOr586AgDQdNnckbuSxbGi -jLD8ET4CCUn9EWlbaPoqgyQNOPKldfxHgHIPPSuxob7SVkd8iky1VKeYXgt94hyv -bktxDu3vE9AHKMk+oUxqCsRKm282lJiLuEKafXOw+TCISgGbpkEGvzc0xjJDN5Ff -/Qm3v9GUcXZmW3JJqKexdgfeTslriSX/u2wFKdmpx1fMTLtL7PN34aVdIBE9GXuc -+F9t3cbiIdO8937Ztw09QkeUO4X1BoU= ------END CERTIFICATE----- diff --git a/carvel-packages/installer/scenarios/minica/educates.example.com/key.pem b/carvel-packages/installer/scenarios/minica/educates.example.com/key.pem deleted file mode 100644 index b0b74e4a7..000000000 --- a/carvel-packages/installer/scenarios/minica/educates.example.com/key.pem +++ /dev/null @@ -1,27 +0,0 @@ ------BEGIN RSA PRIVATE KEY----- -MIIEowIBAAKCAQEAtGkNgm/AzaUVz6jm3SvTXjQiTKU7DXn4yMAgbuqQY+IVqXKn -mu+WNc9HSM/HzNGXnP0jVMhW3FDhABJH+ejKyisvoJkFiE1KfhM38i9r8JqT3nQY -mEmzOixaPtJAwb3pOuT20w+2RSnDP+g9vhCRtYm440CD1ZZi3e99da/CUQswVTq6 -uNSOSmjzmeA/FbzDj8lyZTJNmAuU/GB7gYU4MD2vZmyXpax0FSR32e9uVUw7Q1cX -qUsDQ1ePQnImoWzLxK3Z8RDsZhhC8/j+/T+BILrLcmaGNgsi1nXWHbsTEDSFcTq3 -6p32AOXUsXaWBlIZQ3Czdjt9K80GwzsRCobC9QIDAQABAoIBADpe0vQk3CitBQWP -DEL67wRHseFChHyzvf6VyuiYE+d9Oqz8X6YNZng6fEHemDJ4jalJbaj8uL3HnUS8 -pXUCELqghmRbniKffz6TUUKWfUH3gWgz/9El50snFnvE4xbMLy3S7tkS+FIgVP/U -UEWybrJhwOQl94GfipVr6xesqh42CUFfjvVT7fgH0fc0zyTIzJ0f4Ice5EWXdfr4 -Tpx7DHPLNN6Iu8OqzstpVPPTfLSjGbWyNWTShU2J1yDXpjr0ICrh2rg5NC2Nqprr -w3L7/+vW8GyhLLssczGNomlvnamYC0oUpHiyfj1eLw6gnir/VX/EA759FeUav1h+ -nqugmgECgYEAy0Q51sp0RrFI3CH8junVYb4ri5j3mAlG8PhfiQ5Y1dDaJ/xBIQpR -PnMO8+9klk8+CMyxdep0WZtXeyiR2179E57v7RUEgt1w/mMrfwMkoVlPgjBdTiHw -wfiYujeExGnbIHw80U6xz+Y5NVAGxpGEe+dTund46ImwMFFUKq6vP9UCgYEA4zba -7aCXAP6de+F44mzPXRx29Scfk3UIA6d+08ZD5D7wrkT3CbOqL8+rv+4cV/MghSGO -XZ218V7MfmjNIgjLcBtJR2Ioj+StWc6ve0Jn6hE5ZYOx46iWzN+XnbiyJAp84P7Y -J0HFuHs02fMwMv4IekMH7EOROIMykGGagsB+JqECgYADRnYoH9r/yJuD8IhBRUNK -7+WDulNC/+NEvrvLWY/U4iihvE7QWXo1p2T2SUU1ptE5ExNI8x4s03P1aBHxlvY8 -+rKi/1OzSB4p+y8YPNS6RNYjIuRd/e4DMh5D4eEhyRLe0yGnvbzfvLXvRfrV+EJK -PM/8kTBBjvZn0OeqSGZKgQKBgCao+8E49NiPeh5M8/OazgGqyTbXTFEbtZxhkHva -HU0lxG/yfhIhhtCRxkhm7F2umZbtabrWDdIe7i6ICHdFBdByZBqIQhyRrUk9mLAh -UWsLOTfjm43/7oC3fqWwemcVfcAOvJqZX1oPZKO89DOI88pRw3RY3sm90QmuActD -k3NhAoGBAJoKkNRqeJl+Ro6SF3zVvNRM6Uoxaa0M/ldNBCbbnoP7j6zjQPvsk7tZ -wjcTW/vsjFNEOqCz97cIi3r35Fs9VDnK1B81t8JbeJa8YWFh/uDOnxJ1ksZvbFBu -rmWfy2CyMb8TDteetPXsM0dPQYGZTI23ej6JVeav3DrUGSj2ZBhd ------END RSA PRIVATE KEY----- diff --git a/carvel-packages/installer/scenarios/minica/minica-key.pem b/carvel-packages/installer/scenarios/minica/minica-key.pem deleted file mode 100644 index 50cd25e58..000000000 --- a/carvel-packages/installer/scenarios/minica/minica-key.pem +++ /dev/null @@ -1,27 +0,0 @@ ------BEGIN RSA PRIVATE KEY----- -MIIEpAIBAAKCAQEA14Bevn0LLETBt6k6TMysdb9ioFy6qh43gE6KIQQ2iFaMUlhf -tJ4tMbTBTPUPLRTha/9Mtrx3G67qVjjBGVP9CdZHq+lc8qW/EOUDy6zq75/22RjQ -4aiGNZQSrcK6s1B6RfASqFqfvNjMWcKvkip7hs2zlmndkObWF820VjSTrNQXVGPW -IYDXBgdv/7T30RAdJRliIg88SJWFZgO57obCaFI1LSWsSfvA70pPm8w1fqKxAlVb -jbV0htkdN1l+uE13cnCkxrHoI40+1eJR0ef5335JiyZub4LqdelzvTH1RYpmc1K8 -r9BCbrua+tpzQYyW6ye/9MwB81KaXYGfa3QOLwIDAQABAoIBAEouxm6MXOxAPu8a -Mhd93WArIahSQ2+MN07TunjjGmKUaHlwMoHacXRK5L+5HCBIr9Cdcar19YpyC/ji -UJaHcvOP79wd2QEuTTdjnoreW4Fhb3gMMtt7R7fp4QQvpFVVvsGUgtexWouHldDQ -U9/c/+jHpqqAhuT6kXhgN1P1hWBYgBHVhy57akl5jeSbBwq/Oy0Kj8CyvtWTEP7R -JB+GKSv2A+bY/KoI/rZxnDfozdZa8STH4vpsG8VRbMkkC3SsrybjeP3YxzcbyS3F -6UV9UHxIZmeHjK27cdpSgzz91BZmkGcFZ8gdBMCXKgGaW+LRT93vyfvi2puKLBY5 -8IxDIAECgYEA2s3LsmVrHIb+qyO/amFe41PSqx1CzGZHAuuCm5pWiku8FipbR5lh -qZeHJ8mycsK7FXJpj0aJgLFjW1Kh0bv/UIB8SbC42yClfYXRgH/ly+Fp0FgJFZ6H -rIirNcVN5Ws91/KPVop3HMViqWmtLyQhSSqnZ+U0mOd+zaPdZCrxaa8CgYEA/CLa -q38NGH0s0Nzyg+38sA43IxnUy0vFieawp2Y6SbLtdARHRFZ72lhNp+TtCBl9fcoZ -do4sEFKWO5m5QfKXGI+zW8wOx9aSDi+TpIbzCtergEgEbOja7csPbVx2kZ7O1vkS -ZC1ITC3uysuW9nBsi082LXF9AqoX+tZCeaNrQ4ECgYEAp7rA3vWuAYVerlTOBL+1 -3LBCO5hHv6bb4tolGiFbG9Lo0VkQ9jcXTclx+0c7+4tZnRxC3WlmOPhCwRv8Hmpu -UwjbviWx35EMK8gsjMP+pacb1XHXLPKE8PcnwCWLDEaEdwljZiTpIG4TrujqsMuS -lKMVB6kGA/zaEMwACCx/OdMCgYEAw3paQn+8LXJO3peORg6qy+wZf1M1kW/rdOCv -sPkm06CvTDVM84SBfWTcwABSbOcmTfH0D+Bl9TmyU/74jFKCJn6ytcbc5r5KekkU -lIgzwgI3artrAuz9X0MBcO4w1vFit3Rfd99LoBQ0gHGbVvEOlmsRO+Yy32/0K3sW -CqxSKwECgYABoRFmqDOpQqPDbl3R5H7uah14Q+U0z/g+WUT+yV3cF11qF11479F5 -QpbnL+x3SHWcUACnf3wdnCMChz6+vKWqQyrVE4SolaZoRMHg1X8bLjC6Qcvo1mrh -v7ZpWsSSsocWcRrUvVpNEwfS42SjUCcL34Co0dpJ36FWc2Lg9HOjfg== ------END RSA PRIVATE KEY----- diff --git a/carvel-packages/installer/scenarios/minica/minica.pem b/carvel-packages/installer/scenarios/minica/minica.pem deleted file mode 100644 index 7ba7e9f09..000000000 --- a/carvel-packages/installer/scenarios/minica/minica.pem +++ /dev/null @@ -1,20 +0,0 @@ ------BEGIN CERTIFICATE----- -MIIDSzCCAjOgAwIBAgIIGj3S9tN2wR4wDQYJKoZIhvcNAQELBQAwIDEeMBwGA1UE -AxMVbWluaWNhIHJvb3QgY2EgMWEzZGQyMCAXDTI0MDIwODE2NTUzMVoYDzIxMjQw -MjA4MTY1NTMxWjAgMR4wHAYDVQQDExVtaW5pY2Egcm9vdCBjYSAxYTNkZDIwggEi -MA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDXgF6+fQssRMG3qTpMzKx1v2Kg -XLqqHjeAToohBDaIVoxSWF+0ni0xtMFM9Q8tFOFr/0y2vHcbrupWOMEZU/0J1ker -6Vzypb8Q5QPLrOrvn/bZGNDhqIY1lBKtwrqzUHpF8BKoWp+82MxZwq+SKnuGzbOW -ad2Q5tYXzbRWNJOs1BdUY9YhgNcGB2//tPfREB0lGWIiDzxIlYVmA7nuhsJoUjUt -JaxJ+8DvSk+bzDV+orECVVuNtXSG2R03WX64TXdycKTGsegjjT7V4lHR5/nffkmL -Jm5vgup16XO9MfVFimZzUryv0EJuu5r62nNBjJbrJ7/0zAHzUppdgZ9rdA4vAgMB -AAGjgYYwgYMwDgYDVR0PAQH/BAQDAgKEMB0GA1UdJQQWMBQGCCsGAQUFBwMBBggr -BgEFBQcDAjASBgNVHRMBAf8ECDAGAQH/AgEAMB0GA1UdDgQWBBQ1V19z/BTMm8wX -mjmPBsu5arq+SDAfBgNVHSMEGDAWgBQ1V19z/BTMm8wXmjmPBsu5arq+SDANBgkq -hkiG9w0BAQsFAAOCAQEAO2bTVLdZhj/nJoRdsNY3z56muFxibRVTh7V6S2QEh/fM -mKGOJ8lwOjmOUEONVCq80052OCS8Km1ODtt1iDkmPUkd/XJkiRnMyI4ANMTePZ1S -D0VuMfxRWgFCJM6GWSjUjz3cB9xysQlm3FqtPa+D//lXe37TN4HcjlbhPZz2c7LB -Qjzm15500rUlXRjbuRURHpbqtXGKjVXMwnbTKlxQwV4twisDDwjBDyk8qbcIcKrG -ZwQL0zCeBT6tv+MprWuj+AH+ouTdsGet2ISzOO3KtDqZirHALxo9BotblXNLVtfz -Nqprnk73cNDWMzP9eim9qLawdzfrZL0TDomkqK90Ng== ------END CERTIFICATE----- diff --git a/carvel-packages/installer/scenarios/test-scenarios.sh b/carvel-packages/installer/scenarios/test-scenarios.sh deleted file mode 100755 index 4f503019b..000000000 --- a/carvel-packages/installer/scenarios/test-scenarios.sh +++ /dev/null @@ -1,149 +0,0 @@ -#!/bin/bash - -# Handle source locations that might be a symlink (ref: http://bit.ly/2kcvSCS) -SOURCE="${BASH_SOURCE[0]}" -while [ -h "$SOURCE" ]; do # resolve $SOURCE until the file is no longer a symlink - DIR="$( cd -P "$( dirname "$SOURCE" )" && pwd )" - SOURCE="$(readlink "$SOURCE")" - [[ $SOURCE != /* ]] && SOURCE="$DIR/$SOURCE" # if $SOURCE was a relative symlink, we need to resolve it relative to the path where the symlink file was located -done -DIR="$( cd -P "$( dirname "$SOURCE" )" && pwd )" - -# Make a test to verify yq command is accesible and can be run or else fail with a message to install it -yq --version >/dev/null 2>&1 -result=$? -if [[ "$result" -ne 0 ]] -then - echo "yq command not found. Please install it from https://github.com/mikefarah/yq/releases" - exit 1 -fi - -# -# Colors for echo -# -RED='\033[0;31m' -NC='\033[0m' # No Color - -function help { - local pattern=$1 - pushd ${DIR} >/dev/null 2>&1 - for test_dir in `ls -d {kind,eks,custom,gke,vcluster,generic}/test*/` - do - if [[ $test_dir != *${pattern}* ]]; then - continue - fi - pushd ${DIR}/${test_dir} >/dev/null 2>&1 - echo "---------------------------------------------" - echo "Scenario ${test_dir}:" - echo "===" - cat description.md - echo "===" - echo "" - popd >/dev/null 2>&1 - done - popd >/dev/null 2>&1 -} - -function todo { - local pattern=$1 - echo $pattern - pushd ${DIR} >/dev/null 2>&1 - for test_dir in `ls -d {kind,eks,custom,gke,vcluster,generic}/test*/` - do - if [[ $test_dir != *${pattern}* ]]; then - continue - fi - pushd ${DIR}/${test_dir} >/dev/null 2>&1 - cat description.md | grep TODO >/dev/null 2>&1 - result=$? - if [[ "$result" -eq 0 ]] - then - echo "---------------------------------------------" - echo "Scenario ${test_dir}:" - echo "===" - cat description.md - echo "===" - echo "" - fi - popd >/dev/null 2>&1 - done - popd >/dev/null 2>&1 -} - -function test { - local pattern=$1 - - pushd ${DIR} >/dev/null 2>&1 - for test_dir in `ls -d {kind,eks,custom,gke,vcluster,generic}/test*/` - do - if [[ $test_dir != *${pattern}* ]]; then - continue - fi - pushd ${DIR}/${test_dir} >/dev/null 2>&1 - echo "---------------------------------------------" - echo "Scenario ${test_dir}:" - echo "===" - cat description.md - echo "===" - RESULT_VALUES=$(ytt --data-values-file values.yaml -f ${DIR}/../bundle/config/ytt --data-value-yaml debug=true | yq -P 'sort_keys(..)') - diff <(echo "$RESULT_VALUES") <(cat expected.yaml | yq -P 'sort_keys(..)') - result=$? - [[ "$result" -eq 0 ]] && echo "Result Diff Values/Expected: OK" || echo -e "Result Diff Values/Expected: ${RED}NO OK${NC}" - ytt --data-values-file values.yaml -f ${DIR}/../bundle/config/ytt --data-value-yaml debug=false >/dev/null 2>&1 - result=$? - [[ "$result" -eq 0 ]] && echo "Result ytt processing: OK" || echo -e "Result ytt processing: ${RED}NO OK${NC}" - popd >/dev/null 2>&1 - done - popd >/dev/null 2>&1 -} - -function debug { - local pattern=$1 - pushd ${DIR} >/dev/null 2>&1 - for test_dir in `ls -d {kind,eks,custom,gke,vcluster,generic}/test*/` - do - if [[ $test_dir != *${pattern}* ]]; then - continue - fi - pushd ${DIR}/${test_dir} >/dev/null 2>&1 - echo "---------------------------------------------" - echo "Scenario ${test_dir}:" - echo "===" - cat description.md - echo "===" - RESULT_VALUES=$(ytt --data-values-file values.yaml -f ${DIR}/../bundle/config/ytt --data-value-yaml debug=true) - result=$? - echo "$RESULT_VALUES" | yq -P 'sort_keys(..)' - [[ "$result" -eq 0 ]] || - echo -e "${RED}Error processing ytt template${NC}" - popd >/dev/null 2>&1 - done - popd >/dev/null 2>&1 -} - -for arg in "$@" -do - case $arg in - -h|--help) - shift - help ${1:-"*"} - exit 0 - ;; - -d|--debug) - shift - debug ${1:-"*"} - exit 0 - ;; - -t|--todo) - shift - todo ${1:-"*"} - exit 0 - ;; - *) - test ${1:-"*"} - exit 0 - ;; - esac -done -# this last one is because it's not doing the for loop when there's no arguments -test "*" diff --git a/carvel-packages/installer/scenarios/vcluster/README.md b/carvel-packages/installer/scenarios/vcluster/README.md deleted file mode 100644 index 24ab8b5c7..000000000 --- a/carvel-packages/installer/scenarios/vcluster/README.md +++ /dev/null @@ -1,3 +0,0 @@ -# vcluster -For vcluster we only allow the opinionated configuration for the packages, so, not settings are allowed -and no enablong/disabling of individual packages permitted. \ No newline at end of file diff --git a/carvel-packages/installer/scenarios/vcluster/test-vcluster-scenario-1/description.md b/carvel-packages/installer/scenarios/vcluster/test-vcluster-scenario-1/description.md deleted file mode 100644 index 215972e82..000000000 --- a/carvel-packages/installer/scenarios/vcluster/test-vcluster-scenario-1/description.md +++ /dev/null @@ -1 +0,0 @@ -vcluster configuration with some overrides to see if they are set diff --git a/carvel-packages/installer/scenarios/vcluster/test-vcluster-scenario-1/expected.yaml b/carvel-packages/installer/scenarios/vcluster/test-vcluster-scenario-1/expected.yaml deleted file mode 100644 index 6875e09f1..000000000 --- a/carvel-packages/installer/scenarios/vcluster/test-vcluster-scenario-1/expected.yaml +++ /dev/null @@ -1,34 +0,0 @@ -clusterPackages: - contour: - enabled: false - settings: {} - cert-manager: - enabled: false - settings: {} - external-dns: - enabled: false - settings: {} - certs: - enabled: false - settings: {} - kyverno: - enabled: true - settings: {} - kapp-controller: - enabled: false - settings: {} - educates: - enabled: true - settings: - clusterIngress: - domain: educates.example.com - clusterSecurity: - policyEngine: kyverno - workshopSecurity: - rulesEngine: none - workshopAnalytics: - google: - trackingId: analytics - imagePuller: - enabled: false - prePullImages: [] \ No newline at end of file diff --git a/carvel-packages/installer/scenarios/vcluster/test-vcluster-scenario-1/values.yaml b/carvel-packages/installer/scenarios/vcluster/test-vcluster-scenario-1/values.yaml deleted file mode 100644 index cff389625..000000000 --- a/carvel-packages/installer/scenarios/vcluster/test-vcluster-scenario-1/values.yaml +++ /dev/null @@ -1,20 +0,0 @@ -clusterInfrastructure: - provider: "vcluster" -clusterPackages: - educates: - settings: - imagePuller: - enabled: true - prePullImages: - - "a" -imagePuller: - enabled: true - prePullImages: - - "b" -workshopSecurity: - rulesEngine: "none" -workshopAnalytics: - google: - trackingId: "analytics" -clusterIngress: - domain: "educates.example.com" diff --git a/carvel-packages/installer/scenarios/vcluster/test-vcluster-scenario-2/description.md b/carvel-packages/installer/scenarios/vcluster/test-vcluster-scenario-2/description.md deleted file mode 100644 index 37f00eee9..000000000 --- a/carvel-packages/installer/scenarios/vcluster/test-vcluster-scenario-2/description.md +++ /dev/null @@ -1,2 +0,0 @@ -vcluster configuration with some overrides to see if they are set. -Since we are adding configuration for contour, it'll be enabled diff --git a/carvel-packages/installer/scenarios/vcluster/test-vcluster-scenario-2/expected.yaml b/carvel-packages/installer/scenarios/vcluster/test-vcluster-scenario-2/expected.yaml deleted file mode 100644 index 6875e09f1..000000000 --- a/carvel-packages/installer/scenarios/vcluster/test-vcluster-scenario-2/expected.yaml +++ /dev/null @@ -1,34 +0,0 @@ -clusterPackages: - contour: - enabled: false - settings: {} - cert-manager: - enabled: false - settings: {} - external-dns: - enabled: false - settings: {} - certs: - enabled: false - settings: {} - kyverno: - enabled: true - settings: {} - kapp-controller: - enabled: false - settings: {} - educates: - enabled: true - settings: - clusterIngress: - domain: educates.example.com - clusterSecurity: - policyEngine: kyverno - workshopSecurity: - rulesEngine: none - workshopAnalytics: - google: - trackingId: analytics - imagePuller: - enabled: false - prePullImages: [] \ No newline at end of file diff --git a/carvel-packages/installer/scenarios/vcluster/test-vcluster-scenario-2/values.yaml b/carvel-packages/installer/scenarios/vcluster/test-vcluster-scenario-2/values.yaml deleted file mode 100644 index 7b92f4aaa..000000000 --- a/carvel-packages/installer/scenarios/vcluster/test-vcluster-scenario-2/values.yaml +++ /dev/null @@ -1,24 +0,0 @@ -clusterInfrastructure: - provider: "vcluster" -clusterPackages: - contour: - enabled: true - settings: - infraProvider: "custom" - educates: - settings: - imagePuller: - enabled: true - prePullImages: - - "a" -imagePuller: - enabled: true - prePullImages: - - "b" -workshopSecurity: - rulesEngine: "none" -workshopAnalytics: - google: - trackingId: "analytics" -clusterIngress: - domain: "educates.example.com" diff --git a/carvel-packages/installer/scenarios/vcluster/test-vcluster-scenario-3/description.md b/carvel-packages/installer/scenarios/vcluster/test-vcluster-scenario-3/description.md deleted file mode 100644 index b68ea1955..000000000 --- a/carvel-packages/installer/scenarios/vcluster/test-vcluster-scenario-3/description.md +++ /dev/null @@ -1,2 +0,0 @@ -vcluster configuration with some overrides to see if they are set -We're adding configuration to contour, but not enablign the package, so it should be empty \ No newline at end of file diff --git a/carvel-packages/installer/scenarios/vcluster/test-vcluster-scenario-3/expected.yaml b/carvel-packages/installer/scenarios/vcluster/test-vcluster-scenario-3/expected.yaml deleted file mode 100644 index 6875e09f1..000000000 --- a/carvel-packages/installer/scenarios/vcluster/test-vcluster-scenario-3/expected.yaml +++ /dev/null @@ -1,34 +0,0 @@ -clusterPackages: - contour: - enabled: false - settings: {} - cert-manager: - enabled: false - settings: {} - external-dns: - enabled: false - settings: {} - certs: - enabled: false - settings: {} - kyverno: - enabled: true - settings: {} - kapp-controller: - enabled: false - settings: {} - educates: - enabled: true - settings: - clusterIngress: - domain: educates.example.com - clusterSecurity: - policyEngine: kyverno - workshopSecurity: - rulesEngine: none - workshopAnalytics: - google: - trackingId: analytics - imagePuller: - enabled: false - prePullImages: [] \ No newline at end of file diff --git a/carvel-packages/installer/scenarios/vcluster/test-vcluster-scenario-3/values.yaml b/carvel-packages/installer/scenarios/vcluster/test-vcluster-scenario-3/values.yaml deleted file mode 100644 index 7d5f8d835..000000000 --- a/carvel-packages/installer/scenarios/vcluster/test-vcluster-scenario-3/values.yaml +++ /dev/null @@ -1,24 +0,0 @@ -clusterInfrastructure: - provider: "vcluster" -clusterPackages: - contour: - enabled: false - settings: - infraProvider: "custom" - educates: - settings: - imagePuller: - enabled: true - prePullImages: - - "a" -imagePuller: - enabled: true - prePullImages: - - "b" -workshopSecurity: - rulesEngine: "none" -workshopAnalytics: - google: - trackingId: "analytics" -clusterIngress: - domain: "educates.example.com" diff --git a/client-programs/Dockerfile b/client-programs/Dockerfile index 94cb804df..f21f55ab6 100644 --- a/client-programs/Dockerfile +++ b/client-programs/Dockerfile @@ -4,11 +4,10 @@ ARG TAG=latest # Add this stage before the builder stage FROM --platform=$BUILDPLATFORM ${REPOSITORY}/educates-base-environment:${TAG} AS themes-source -# Multi-stage build for client-programs -FROM --platform=$BUILDPLATFORM golang:1.25.0-alpine AS builder - -# Install build dependencies -RUN apk add --no-cache git ca-certificates tzdata +# Multi-stage build for client-programs. Pinned to BUILDPLATFORM so Go +# cross-compiles for non-native target architectures instead of running +# the toolchain under QEMU emulation. +FROM --platform=$BUILDPLATFORM golang:1.26 AS builder # Set working directory WORKDIR /src @@ -34,7 +33,13 @@ COPY --from=themes-source /opt/eduk8s/etc/themes pkg/renderer/files/ ARG TARGETOS ARG TARGETARCH +# Compiled-in defaults, matching the ldflags the binary release builds +# use (see build-and-publish-images.yaml). +ARG PROJECT_VERSION=develop +ARG IMAGE_REPOSITORY=ghcr.io/educates + RUN CGO_ENABLED=0 GOOS=${TARGETOS} GOARCH=${TARGETARCH} go build \ + -ldflags "-X 'main.projectVersion=${PROJECT_VERSION}' -X 'main.imageRepository=${IMAGE_REPOSITORY}'" \ -o bin/educates-${TARGETOS}-${TARGETARCH} \ cmd/educates/main.go diff --git a/client-programs/go.mod b/client-programs/go.mod index 7ec376dae..7105725ec 100644 --- a/client-programs/go.mod +++ b/client-programs/go.mod @@ -1,6 +1,6 @@ module github.com/educates/educates-training-platform/client-programs -go 1.25.0 +go 1.26.0 // replace cloud.google.com/go/compute/metadata => cloud.google.com/go/compute/metadata v0.2.3 @@ -11,7 +11,6 @@ go 1.25.0 require ( carvel.dev/imgpkg v0.46.1 carvel.dev/kapp v0.64.2 - carvel.dev/kbld v0.46.0 carvel.dev/vendir v0.44.0 carvel.dev/ytt v0.52.1 github.com/adrg/xdg v0.5.3 @@ -27,25 +26,31 @@ require ( github.com/joho/godotenv v1.5.1 github.com/mitchellh/go-homedir v1.1.0 github.com/pkg/errors v0.9.1 - github.com/spf13/cobra v1.10.1 - golang.org/x/exp v0.0.0-20251023183803-a4bb9ffd2546 + github.com/spf13/cobra v1.10.2 + golang.org/x/exp v0.0.0-20251219203646-944ab1f22d93 gopkg.in/yaml.v2 v2.4.0 - k8s.io/api v0.34.2 - k8s.io/apimachinery v0.34.2 - k8s.io/cli-runtime v0.34.2 - k8s.io/client-go v0.34.2 + k8s.io/api v0.36.0 + k8s.io/apimachinery v0.36.0 + k8s.io/cli-runtime v0.36.0 + k8s.io/client-go v0.36.0 k8s.io/controller-manager v0.33.5 // indirect - k8s.io/klog/v2 v2.130.1 - k8s.io/kubectl v0.34.2 - sigs.k8s.io/controller-runtime v0.22.4 + k8s.io/klog/v2 v2.140.0 + k8s.io/kubectl v0.36.0 + sigs.k8s.io/controller-runtime v0.24.0 sigs.k8s.io/kind v0.29.0 sigs.k8s.io/yaml v1.6.0 ) +require ( + github.com/xeipuuv/gojsonschema v1.2.0 + gopkg.in/yaml.v3 v3.0.1 + helm.sh/helm/v4 v4.2.0 +) + require ( al.essio.dev/pkg/shellescape v1.6.0 // indirect - cel.dev/expr v0.25.1 // indirect cloud.google.com/go/compute/metadata v0.9.0 // indirect + dario.cat/mergo v1.0.1 // indirect github.com/Azure/azure-sdk-for-go v68.0.0+incompatible // indirect github.com/Azure/go-ansiterm v0.0.0-20250102033503-faa5f7b0171c // indirect github.com/Azure/go-autorest v14.2.0+incompatible // indirect @@ -56,11 +61,16 @@ require ( github.com/Azure/go-autorest/autorest/date v0.3.1 // indirect github.com/Azure/go-autorest/logger v0.2.2 // indirect github.com/Azure/go-autorest/tracing v0.6.1 // indirect - github.com/BurntSushi/toml v1.5.0 // indirect + github.com/BurntSushi/toml v1.6.0 // indirect github.com/MakeNowJust/heredoc v1.0.0 // indirect + github.com/Masterminds/goutils v1.1.1 // indirect + github.com/Masterminds/semver/v3 v3.5.0 // indirect + github.com/Masterminds/sprig/v3 v3.3.0 // indirect + github.com/Masterminds/squirrel v1.5.4 // indirect github.com/Microsoft/go-winio v0.6.2 // indirect + github.com/ProtonMail/go-crypto v1.4.1 // indirect github.com/VividCortex/ewma v1.2.0 // indirect - github.com/antlr4-go/antlr/v4 v4.13.1 // indirect + github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 // indirect github.com/aws/aws-sdk-go-v2 v1.39.6 // indirect github.com/aws/aws-sdk-go-v2/config v1.31.19 // indirect github.com/aws/aws-sdk-go-v2/credentials v1.18.23 // indirect @@ -81,30 +91,38 @@ require ( github.com/blang/semver/v4 v4.0.0 // indirect github.com/bmatcuk/doublestar v1.3.4 // indirect github.com/carvel-dev/semver/v4 v4.0.1-0.20240402203627-beb83fbf25e4 // indirect - github.com/cenkalti/backoff/v5 v5.0.3 // indirect github.com/cespare/xxhash/v2 v2.3.0 // indirect + github.com/chai2010/gettext-go v1.0.2 // indirect github.com/cheggaaa/pb/v3 v3.1.7 // indirect github.com/chrismellard/docker-credential-acr-env v0.0.0-20230304212654-82a0ddb27589 // indirect github.com/clipperhouse/stringish v0.1.1 // indirect github.com/clipperhouse/uax29/v2 v2.3.0 // indirect + github.com/cloudflare/circl v1.6.3 // indirect github.com/containerd/errdefs v1.0.0 // indirect github.com/containerd/errdefs/pkg v0.3.0 // indirect github.com/containerd/stargz-snapshotter/estargz v0.18.1 // indirect github.com/cppforlife/cobrautil v0.0.0-20221130162803-acdfead391ef // indirect github.com/cppforlife/color v1.9.1-0.20200716202919-6706ac40b835 // indirect github.com/cppforlife/go-patch v0.0.0-20240118020416-2147782e467b // indirect + github.com/cyphar/filepath-securejoin v0.6.1 // indirect github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect github.com/dimchansky/utfbom v1.1.1 // indirect github.com/distribution/reference v0.6.0 // indirect github.com/docker/cli v29.2.0+incompatible // indirect github.com/docker/distribution v2.8.3+incompatible // indirect - github.com/docker/docker-credential-helpers v0.9.4 // indirect + github.com/docker/docker-credential-helpers v0.9.5 // indirect github.com/docker/go-units v0.5.0 // indirect + github.com/dylibso/observe-sdk/go v0.0.0-20240819160327-2d926c5d788a // indirect github.com/emicklei/go-restful/v3 v3.13.0 // indirect github.com/evanphx/json-patch/v5 v5.9.11 // indirect - github.com/fatih/color v1.18.0 // indirect + github.com/exponent-io/jsonpath v0.0.0-20210407135951-1de76d718b3f // indirect + github.com/extism/go-sdk v1.7.1 // indirect + github.com/fatih/color v1.19.0 // indirect github.com/felixge/httpsnoop v1.0.4 // indirect + github.com/fluxcd/cli-utils v1.2.0 // indirect github.com/fxamacker/cbor/v2 v2.9.0 // indirect + github.com/go-errors/errors v1.5.1 // indirect + github.com/go-gorp/gorp/v3 v3.1.0 // indirect github.com/go-logr/stdr v1.2.2 // indirect github.com/go-openapi/jsonpointer v0.22.1 // indirect github.com/go-openapi/jsonreference v0.21.3 // indirect @@ -120,97 +138,106 @@ require ( github.com/go-openapi/swag/stringutils v0.25.1 // indirect github.com/go-openapi/swag/typeutils v0.25.1 // indirect github.com/go-openapi/swag/yamlutils v0.25.1 // indirect + github.com/gobwas/glob v0.2.3 // indirect + github.com/gofrs/flock v0.13.0 // indirect github.com/gogo/protobuf v1.3.2 // indirect github.com/golang-jwt/jwt/v4 v4.5.2 // indirect - github.com/google/cel-go v0.26.1 // indirect + github.com/google/btree v1.1.3 // indirect github.com/google/gnostic-models v0.7.0 // indirect - github.com/google/go-cmp v0.7.0 // indirect github.com/google/go-containerregistry v0.20.6 // indirect github.com/google/go-github v17.0.0+incompatible // indirect github.com/google/go-querystring v1.1.0 // indirect github.com/google/uuid v1.6.0 // indirect - github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.3 // indirect + github.com/gosuri/uitable v0.0.4 // indirect github.com/hashicorp/go-version v1.7.0 // indirect + github.com/huandu/xstrings v1.5.0 // indirect + github.com/ianlancetaylor/demangle v0.0.0-20240805132620-81f5be970eca // indirect github.com/imdario/mergo v0.3.16 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect + github.com/jmoiron/sqlx v1.4.0 // indirect github.com/json-iterator/go v1.1.12 // indirect github.com/k14s/difflib v0.0.0-20240118055029-596a7a5585c3 // indirect github.com/k14s/starlark-go v0.0.0-20200720175618-3a5c849cc368 // indirect github.com/k14s/ytt v0.39.0 // indirect - github.com/klauspost/compress v1.18.1 // indirect + github.com/klauspost/compress v1.18.4 // indirect + github.com/lann/builder v0.0.0-20180802200727-47ae307949d0 // indirect + github.com/lann/ps v0.0.0-20150810152359-62de8c46ede0 // indirect + github.com/lib/pq v1.12.3 // indirect github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de // indirect github.com/mattn/go-colorable v0.1.14 // indirect github.com/mattn/go-isatty v0.0.20 // indirect github.com/mattn/go-runewidth v0.0.19 // indirect - github.com/mattn/go-shellwords v1.0.12 // indirect + github.com/mattn/go-shellwords v1.0.13 // indirect + github.com/mitchellh/copystructure v1.2.0 // indirect github.com/mitchellh/go-wordwrap v1.0.1 // indirect github.com/mitchellh/mapstructure v1.5.0 // indirect + github.com/mitchellh/reflectwalk v1.0.2 // indirect github.com/moby/docker-image-spec v1.3.1 // indirect - github.com/moby/spdystream v0.5.1 // indirect github.com/moby/sys/sequential v0.6.0 // indirect github.com/moby/term v0.5.2 // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/reflect2 v1.0.3-0.20250322232337-35a7c28c31ee // indirect + github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00 // indirect github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect - github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f // indirect github.com/opencontainers/go-digest v1.0.0 // indirect github.com/opencontainers/image-spec v1.1.1 // indirect - github.com/openshift/crd-schema-checker v0.0.0-20250905140724-c313b6407231 // indirect + github.com/openshift/crd-schema-checker v0.0.0-20240404194209-35a9033b1d11 // indirect github.com/otiai10/copy v1.14.1 // indirect github.com/otiai10/mint v1.6.3 // indirect github.com/pelletier/go-toml v1.9.5 // indirect + github.com/peterbourgon/diskv v2.0.1+incompatible // indirect github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect github.com/prometheus/client_golang v1.23.2 // indirect github.com/prometheus/client_model v0.6.2 // indirect - github.com/prometheus/common v0.67.2 // indirect - github.com/prometheus/procfs v0.19.2 // indirect + github.com/prometheus/common v0.67.5 // indirect + github.com/prometheus/procfs v0.20.1 // indirect + github.com/rubenv/sql-migrate v1.8.1 // indirect github.com/russross/blackfriday/v2 v2.1.0 // indirect - github.com/sirupsen/logrus v1.9.3 // indirect + github.com/santhosh-tekuri/jsonschema/v6 v6.0.2 // indirect + github.com/shopspring/decimal v1.4.0 // indirect + github.com/sirupsen/logrus v1.9.4 // indirect + github.com/spf13/cast v1.7.0 // indirect github.com/spf13/pflag v1.0.10 // indirect - github.com/stoewer/go-strcase v1.3.1 // indirect + github.com/tetratelabs/wabin v0.0.0-20230304001439-f6f874872834 // indirect + github.com/tetratelabs/wazero v1.11.0 // indirect github.com/vbatts/tar-split v0.12.2 // indirect github.com/vito/go-interact v1.0.2 // indirect github.com/vmware-tanzu/carvel-kapp-controller v0.51.3 // indirect github.com/x448/float16 v0.8.4 // indirect github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb // indirect github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect - github.com/xeipuuv/gojsonschema v1.2.0 // indirect + github.com/xlab/treeprint v1.2.0 // indirect go.opentelemetry.io/auto/sdk v1.2.1 // indirect - go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.63.0 // indirect + go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.67.0 // indirect go.opentelemetry.io/otel v1.43.0 // indirect - go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.38.0 // indirect - go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.38.0 // indirect go.opentelemetry.io/otel/metric v1.43.0 // indirect - go.opentelemetry.io/otel/sdk v1.43.0 // indirect go.opentelemetry.io/otel/trace v1.43.0 // indirect - go.opentelemetry.io/proto/otlp v1.9.0 // indirect + go.opentelemetry.io/proto/otlp v1.10.0 // indirect go.yaml.in/yaml/v2 v2.4.3 // indirect go.yaml.in/yaml/v3 v3.0.4 // indirect - golang.org/x/crypto v0.46.0 // indirect - golang.org/x/net v0.48.0 // indirect - golang.org/x/oauth2 v0.34.0 // indirect - golang.org/x/sync v0.19.0 // indirect - golang.org/x/sys v0.42.0 // indirect - golang.org/x/term v0.38.0 // indirect - golang.org/x/text v0.32.0 // indirect - golang.org/x/time v0.14.0 // indirect - google.golang.org/genproto/googleapis/api v0.0.0-20251202230838-ff82c1b0f217 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20251202230838-ff82c1b0f217 // indirect - google.golang.org/grpc v1.79.3 // indirect - google.golang.org/protobuf v1.36.10 // indirect + golang.org/x/crypto v0.50.0 // indirect + golang.org/x/net v0.52.0 // indirect + golang.org/x/oauth2 v0.36.0 // indirect + golang.org/x/sync v0.20.0 // indirect + golang.org/x/sys v0.43.0 // indirect + golang.org/x/term v0.42.0 // indirect + golang.org/x/text v0.36.0 // indirect + golang.org/x/time v0.15.0 // indirect + google.golang.org/protobuf v1.36.12-0.20260120151049-f2248ac996af // indirect gopkg.in/evanphx/json-patch.v4 v4.13.0 // indirect gopkg.in/inf.v0 v0.9.1 // indirect gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 // indirect - gopkg.in/yaml.v3 v3.0.1 // indirect - k8s.io/apiextensions-apiserver v0.34.1 // indirect - k8s.io/apiserver v0.34.1 // indirect - k8s.io/component-base v0.34.2 // indirect - k8s.io/component-helpers v0.34.2 // indirect - k8s.io/kube-openapi v0.0.0-20250910181357-589584f1c912 // indirect + k8s.io/apiextensions-apiserver v0.36.0 // indirect + k8s.io/apiserver v0.36.0 // indirect + k8s.io/component-base v0.36.0 // indirect + k8s.io/component-helpers v0.36.0 // indirect + k8s.io/kube-openapi v0.0.0-20260317180543-43fb72c5454a // indirect k8s.io/kubernetes v1.34.2 // indirect - k8s.io/utils v0.0.0-20251002143259-bc988d571ff4 // indirect - sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.34.0 // indirect + k8s.io/utils v0.0.0-20260210185600-b8788abfbbc2 // indirect + oras.land/oras-go/v2 v2.6.0 // indirect sigs.k8s.io/json v0.0.0-20250730193827-2d320260d730 // indirect + sigs.k8s.io/kustomize/api v0.21.1 // indirect + sigs.k8s.io/kustomize/kyaml v0.21.1 // indirect sigs.k8s.io/randfill v1.0.0 // indirect - sigs.k8s.io/structured-merge-diff/v6 v6.3.0 // indirect + sigs.k8s.io/structured-merge-diff/v6 v6.3.2 // indirect ) diff --git a/client-programs/go.sum b/client-programs/go.sum index 29fcea2ac..499032f21 100644 --- a/client-programs/go.sum +++ b/client-programs/go.sum @@ -4,16 +4,18 @@ carvel.dev/imgpkg v0.46.1 h1:UOYaPllQJRsbzSl61IiNvmDZA5z4951i/KaSROAC1W0= carvel.dev/imgpkg v0.46.1/go.mod h1:Q1E+7tpoiPbVNjb7HSmLZP7E1j0w6mWFzDarOXW1HiI= carvel.dev/kapp v0.64.2 h1:dJhtWVOkvPPgcS0f5A4OtOlrGie9gHvabtZBvB/h0+M= carvel.dev/kapp v0.64.2/go.mod h1:5t0pWQzyoY9SzPVqrqgYhTlzgsuyMy+bvFdmrvtbDJw= -carvel.dev/kbld v0.46.0 h1:khSHTH3yiEE8imE9K245ZT67ZToixa1nC1938Oje1O4= -carvel.dev/kbld v0.46.0/go.mod h1:wmUYbnw0di759Id26P6dtRW59cBHy4UT9/FJgthiJ0I= carvel.dev/vendir v0.44.0 h1:vfq5KgGbbLlxHrE0prY7gZgiEQpjwo4lS2akCaVkcxA= carvel.dev/vendir v0.44.0/go.mod h1:gslrJ0HPiy8gtJYsQZHzIVuGfOG0nfDKDupEm7uBWVQ= carvel.dev/ytt v0.52.1 h1:I9rCwIunzClas2MH5nVGtCK5ujZdiGaqAfGol/wiRKQ= carvel.dev/ytt v0.52.1/go.mod h1:lzkMguCvSVvxT2My9RG3gRMgTws97NpNXufKZ6iiP5E= -cel.dev/expr v0.25.1 h1:1KrZg61W6TWSxuNZ37Xy49ps13NUovb66QLprthtwi4= -cel.dev/expr v0.25.1/go.mod h1:hrXvqGP6G6gyx8UAHSHJ5RGk//1Oj5nXQ2NI02Nrsg4= cloud.google.com/go/compute/metadata v0.9.0 h1:pDUj4QMoPejqq20dK0Pg2N4yG9zIkYGdBtwLoEkH9Zs= cloud.google.com/go/compute/metadata v0.9.0/go.mod h1:E0bWwX5wTnLPedCKqk3pJmVgCBSM6qQI1yTBdEb3C10= +dario.cat/mergo v1.0.1 h1:Ra4+bf83h2ztPIQYNP99R6m+Y7KfnARDfID+a+vLl4s= +dario.cat/mergo v1.0.1/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk= +filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA= +filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4= +github.com/AdaLogics/go-fuzz-headers v0.0.0-20230811130428-ced1acdcaa24 h1:bvDV9vkmnHYOMsOr4WLk+Vo07yKIzd94sVoIqshQ4bU= +github.com/AdaLogics/go-fuzz-headers v0.0.0-20230811130428-ced1acdcaa24/go.mod h1:8o94RPi1/7XTJvwPpRSzSUedZrtlirdB3r9Z20bi2f8= github.com/Azure/azure-sdk-for-go v68.0.0+incompatible h1:fcYLmCpyNYRnvJbPerq7U0hS+6+I79yEDJBqVNcqUzU= github.com/Azure/azure-sdk-for-go v68.0.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc= github.com/Azure/go-ansiterm v0.0.0-20250102033503-faa5f7b0171c h1:udKWzYgxTojEKWjV8V+WSxDXJ4NFATAsZjh8iIbsQIg= @@ -44,20 +46,30 @@ github.com/Azure/go-autorest/logger v0.2.2/go.mod h1:I5fg9K52o+iuydlWfa9T5K6WFos github.com/Azure/go-autorest/tracing v0.6.0/go.mod h1:+vhtPC754Xsa23ID7GlGsrdKBpUA79WCAKPPZVC2DeU= github.com/Azure/go-autorest/tracing v0.6.1 h1:YUMSrC/CeD1ZnnXcNYU4a/fzsO35u2Fsful9L/2nyR0= github.com/Azure/go-autorest/tracing v0.6.1/go.mod h1:/3EgjbsjraOqiicERAeu3m7/z0x1TzjQGAwDrJrXGkc= -github.com/BurntSushi/toml v1.5.0 h1:W5quZX/G/csjUnuI8SUYlsHs9M38FC7znL0lIO+DvMg= -github.com/BurntSushi/toml v1.5.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho= +github.com/BurntSushi/toml v1.6.0 h1:dRaEfpa2VI55EwlIW72hMRHdWouJeRF7TPYhI+AUQjk= +github.com/BurntSushi/toml v1.6.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho= +github.com/DATA-DOG/go-sqlmock v1.5.2 h1:OcvFkGmslmlZibjAjaHm3L//6LiuBgolP7OputlJIzU= +github.com/DATA-DOG/go-sqlmock v1.5.2/go.mod h1:88MAG/4G7SMwSE3CeA0ZKzrT5CiOU3OJ+JlNzwDqpNU= github.com/MakeNowJust/heredoc v1.0.0 h1:cXCdzVdstXyiTqTvfqk9SDHpKNjxuom+DOlyEeQ4pzQ= github.com/MakeNowJust/heredoc v1.0.0/go.mod h1:mG5amYoWBHf8vpLOuehzbGGw0EHxpZZ6lCpQ4fNJ8LE= +github.com/Masterminds/goutils v1.1.1 h1:5nUrii3FMTL5diU80unEVvNevw1nH4+ZV4DSLVJLSYI= +github.com/Masterminds/goutils v1.1.1/go.mod h1:8cTjp+g8YejhMuvIA5y2vz3BpJxksy863GQaJW2MFNU= +github.com/Masterminds/semver/v3 v3.5.0 h1:kQceYJfbupGfZOKZQg0kou0DgAKhzDg2NZPAwZ/2OOE= +github.com/Masterminds/semver/v3 v3.5.0/go.mod h1:4V+yj/TJE1HU9XfppCwVMZq3I84lprf4nC11bSS5beM= +github.com/Masterminds/sprig/v3 v3.3.0 h1:mQh0Yrg1XPo6vjYXgtf5OtijNAKJRNcTdOOGZe3tPhs= +github.com/Masterminds/sprig/v3 v3.3.0/go.mod h1:Zy1iXRYNqNLUolqCpL4uhk6SHUMAOSCzdgBfDb35Lz0= +github.com/Masterminds/squirrel v1.5.4 h1:uUcX/aBc8O7Fg9kaISIUsHXdKuqehiXAMQTYX8afzqM= +github.com/Masterminds/squirrel v1.5.4/go.mod h1:NNaOrjSoIDfDA40n7sr2tPNZRfjzjA400rg+riTZj10= github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY= github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU= +github.com/ProtonMail/go-crypto v1.4.1 h1:9RfcZHqEQUvP8RzecWEUafnZVtEvrBVL9BiF67IQOfM= +github.com/ProtonMail/go-crypto v1.4.1/go.mod h1:e1OaTyu5SYVrO9gKOEhTc+5UcXtTUa+P3uLudwcgPqo= github.com/VividCortex/ewma v1.2.0 h1:f58SaIzcDXrSy3kWaHNvuJgJ3Nmz59Zji6XoJR/q1ow= github.com/VividCortex/ewma v1.2.0/go.mod h1:nz4BbCtbLyFDeC9SUHbtcT5644juEuWfUAUnGx7j5l4= github.com/adrg/xdg v0.5.3 h1:xRnxJXne7+oWDatRhR1JLnvuccuIeCoBu2rtuLqQB78= github.com/adrg/xdg v0.5.3/go.mod h1:nlTsY+NNiCBGCK2tpm09vRqfVzrc2fLmXGpBLF0zlTQ= -github.com/antlr4-go/antlr/v4 v4.13.1 h1:SqQKkuVZ+zWkMMNkjy5FZe5mr5WURWnlpmOuzYWrPrQ= -github.com/antlr4-go/antlr/v4 v4.13.1/go.mod h1:GKmUxMtwp6ZgGwZSva4eWPC5mS6vUAmOABFgjdkM7Nw= -github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio= -github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs= +github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 h1:DklsrG3dyBCFEj5IhUbnKptjxatkF07cF2ak3yi77so= +github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2/go.mod h1:WaHUgvxTVq04UNunO+XhnAqY/wQc+bxr74GqbsZ/Jqw= github.com/aws/aws-sdk-go-v2 v1.39.6 h1:2JrPCVgWJm7bm83BDwY5z8ietmeJUbh3O2ACnn+Xsqk= github.com/aws/aws-sdk-go-v2 v1.39.6/go.mod h1:c9pm7VwuW0UPxAEYGyTmyurVcNrbF6Rt/wixFqDhcjE= github.com/aws/aws-sdk-go-v2/config v1.31.19 h1:qdUtOw4JhZr2YcKO3g0ho/IcFXfXrrb8xlX05Y6EvSw= @@ -96,14 +108,16 @@ github.com/blang/semver/v4 v4.0.0 h1:1PFHFE6yCCTv8C1TeyNNarDzntLi7wMI5i/pzqYIsAM github.com/blang/semver/v4 v4.0.0/go.mod h1:IbckMUScFkM3pff0VJDNKRiT6TG/YpiHIM2yvyW5YoQ= github.com/bmatcuk/doublestar v1.3.4 h1:gPypJ5xD31uhX6Tf54sDPUOBXTqKH4c9aPY66CyQrS0= github.com/bmatcuk/doublestar v1.3.4/go.mod h1:wiQtGV+rzVYxB7WIlirSN++5HPtPlXEo9MEoZQC/PmE= +github.com/bshuster-repo/logrus-logstash-hook v1.1.0 h1:o2FzZifLg+z/DN1OFmzTWzZZx/roaqt8IPZCIVco8r4= +github.com/bshuster-repo/logrus-logstash-hook v1.1.0/go.mod h1:Q2aXOe7rNuPgbBtPCOzYyWDvKX7+FpxE5sRdvcPoui0= github.com/carvel-dev/semver/v4 v4.0.1-0.20240402203627-beb83fbf25e4 h1:F4rZiMGZyC66j9VB7doVOE4tFHF1yNEihQlOuht4jmM= github.com/carvel-dev/semver/v4 v4.0.1-0.20240402203627-beb83fbf25e4/go.mod h1:4cFTBLAr/U11ykiEEQMccu4uJ1i0GS+atJmeETHCFtI= -github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8= -github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= github.com/cenkalti/backoff/v5 v5.0.3 h1:ZN+IMa753KfX5hd8vVaMixjnqRZ3y8CuJKRKj1xcsSM= github.com/cenkalti/backoff/v5 v5.0.3/go.mod h1:rkhZdG3JZukswDf7f0cwqPNk4K0sa+F97BxZthm/crw= github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/chai2010/gettext-go v1.0.2 h1:1Lwwip6Q2QGsAdl/ZKPCwTe9fe0CjlUbqj5bFNSjIRk= +github.com/chai2010/gettext-go v1.0.2/go.mod h1:y+wnP2cHYaVj19NZhYKAwEMH2CI1gNHeQQ+5AjwawxA= github.com/cheggaaa/pb/v3 v3.1.7 h1:2FsIW307kt7A/rz/ZI2lvPO+v3wKazzE4K/0LtTWsOI= github.com/cheggaaa/pb/v3 v3.1.7/go.mod h1:/Ji89zfVPeC/u5j8ukD0MBPHt2bzTYp74lQ7KlgFWTQ= github.com/chrismellard/docker-credential-acr-env v0.0.0-20230304212654-82a0ddb27589 h1:krfRl01rzPzxSxyLyrChD+U+MzsBXbm0OwYYB67uF+4= @@ -115,6 +129,8 @@ github.com/clipperhouse/stringish v0.1.1 h1:+NSqMOr3GR6k1FdRhhnXrLfztGzuG+VuFDfa github.com/clipperhouse/stringish v0.1.1/go.mod h1:v/WhFtE1q0ovMta2+m+UbpZ+2/HEXNWYXQgCt4hdOzA= github.com/clipperhouse/uax29/v2 v2.3.0 h1:SNdx9DVUqMoBuBoW3iLOj4FQv3dN5mDtuqwuhIGpJy4= github.com/clipperhouse/uax29/v2 v2.3.0/go.mod h1:Wn1g7MK6OoeDT0vL+Q0SQLDz/KpfsVRgg6W7ihQeh4g= +github.com/cloudflare/circl v1.6.3 h1:9GPOhQGF9MCYUeXyMYlqTR6a5gTrgR/fBLXvUgtVcg8= +github.com/cloudflare/circl v1.6.3/go.mod h1:2eXP6Qfat4O/Yhh8BznvKnJ+uzEoTQ6jVKJRn81BiS4= github.com/compose-spec/compose-go v1.20.2 h1:u/yfZHn4EaHGdidrZycWpxXgFffjYULlTbRfJ51ykjQ= github.com/compose-spec/compose-go v1.20.2/go.mod h1:+MdqXV4RA7wdFsahh/Kb8U0pAJqkg7mr4PM9tFKU8RM= github.com/containerd/errdefs v1.0.0 h1:tg5yIfIlQIrxYtu9ajqY42W3lpS19XqdxRQeEwYG8PI= @@ -125,10 +141,8 @@ github.com/containerd/log v0.1.0 h1:TCJt7ioM2cr/tfR8GPbGf9/VRAX8D2B4PjzCpfX540I= github.com/containerd/log v0.1.0/go.mod h1:VRRf09a7mHDIRezVKTRCrOq78v577GXq3bSa3EhrzVo= github.com/containerd/stargz-snapshotter/estargz v0.18.1 h1:cy2/lpgBXDA3cDKSyEfNOFMA/c10O1axL69EU7iirO8= github.com/containerd/stargz-snapshotter/estargz v0.18.1/go.mod h1:ALIEqa7B6oVDsrF37GkGN20SuvG/pIMm7FwP7ZmRb0Q= -github.com/coreos/go-semver v0.3.1 h1:yi21YpKnrx1gt5R+la8n5WgS0kCrsPp33dmEyHReZr4= -github.com/coreos/go-semver v0.3.1/go.mod h1:irMmmIw/7yzSRPWryHsK7EYSg09caPQL03VsM8rvUec= -github.com/coreos/go-systemd/v22 v22.5.0 h1:RrqgGjYQKalulkV8NGVIfkXQf6YYmOyiJKk8iXXhfZs= -github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= +github.com/coreos/go-systemd/v22 v22.7.0 h1:LAEzFkke61DFROc7zNLX/WA2i5J8gYqe0rSj9KI28KA= +github.com/coreos/go-systemd/v22 v22.7.0/go.mod h1:xNUYtjHu2EDXbsxz1i41wouACIwT7Ybq9o0BQhMwD0w= github.com/cppforlife/cobrautil v0.0.0-20221130162803-acdfead391ef h1:de10GNLe45JTMghl2qf9WH17H/BjGShK41X3vKAsPJA= github.com/cppforlife/cobrautil v0.0.0-20221130162803-acdfead391ef/go.mod h1:2w+qxVu2KSGW78Ex/XaIqfh/OvBgjEsmN53S4T8vEyA= github.com/cppforlife/color v1.9.1-0.20200716202919-6706ac40b835 h1:mYQweUIBD+TBRjIeQnJmXr0GSVMpI6O0takyb/aaOgo= @@ -140,43 +154,73 @@ github.com/cppforlife/go-patch v0.0.0-20240118020416-2147782e467b/go.mod h1:67a7 github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g= github.com/creack/pty v1.1.24 h1:bJrF4RRfyJnbTJqzRLHzcGaZK1NeM5kTC9jGgovnR1s= github.com/creack/pty v1.1.24/go.mod h1:08sCNb52WyoAwi2QDyzUCTgcvVFhUzewun7wtTfvcwE= +github.com/cyphar/filepath-securejoin v0.6.1 h1:5CeZ1jPXEiYt3+Z6zqprSAgSWiggmpVyciv8syjIpVE= +github.com/cyphar/filepath-securejoin v0.6.1/go.mod h1:A8hd4EnAeyujCJRrICiOWqjS1AX0a9kM5XL+NwKoYSc= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78= +github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc= github.com/dimchansky/utfbom v1.1.1 h1:vV6w1AhK4VMnhBno/TPVCoK9U/LP0PkLCS9tbxHdi/U= github.com/dimchansky/utfbom v1.1.1/go.mod h1:SxdoEBH5qIqFocHMyGOXVAybYJdr71b1Q/j0mACtrfE= +github.com/distribution/distribution/v3 v3.1.1 h1:KUbk7C8CfaLXy8kbf/hGq9cad/wCoLB6dbWH6DMbmX0= +github.com/distribution/distribution/v3 v3.1.1/go.mod h1:d7lXwZpph0bVcOj4Aqn0nMrWHIwRQGdiV5TLeI+/w6Y= github.com/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk= github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E= +github.com/dlclark/regexp2 v1.11.0 h1:G/nrcoOa7ZXlpoa/91N3X7mM3r8eIlMBBJZvsz/mxKI= +github.com/dlclark/regexp2 v1.11.0/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8= github.com/docker/cli v29.2.0+incompatible h1:9oBd9+YM7rxjZLfyMGxjraKBKE4/nVyvVfN4qNl9XRM= github.com/docker/cli v29.2.0+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= github.com/docker/distribution v2.8.3+incompatible h1:AtKxIZ36LoNK51+Z6RpzLpddBirtxJnzDrHLEKxTAYk= github.com/docker/distribution v2.8.3+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= github.com/docker/docker v28.5.2+incompatible h1:DBX0Y0zAjZbSrm1uzOkdr1onVghKaftjlSWt4AFexzM= github.com/docker/docker v28.5.2+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= -github.com/docker/docker-credential-helpers v0.9.4 h1:76ItO69/AP/V4yT9V4uuuItG0B1N8hvt0T0c0NN/DzI= -github.com/docker/docker-credential-helpers v0.9.4/go.mod h1:v1S+hepowrQXITkEfw6o4+BMbGot02wiKpzWhGUZK6c= +github.com/docker/docker-credential-helpers v0.9.5 h1:EFNN8DHvaiK8zVqFA2DT6BjXE0GzfLOZ38ggPTKePkY= +github.com/docker/docker-credential-helpers v0.9.5/go.mod h1:v1S+hepowrQXITkEfw6o4+BMbGot02wiKpzWhGUZK6c= github.com/docker/go-connections v0.6.0 h1:LlMG9azAe1TqfR7sO+NJttz1gy6KO7VJBh+pMmjSD94= github.com/docker/go-connections v0.6.0/go.mod h1:AahvXYshr6JgfUJGdDCs2b5EZG/vmaMAntpSFH5BFKE= +github.com/docker/go-events v0.0.0-20250808211157-605354379745 h1:yOn6Ze6IbYI/KAw2lw/83ELYvZh6hvsygTVkD0dzMC4= +github.com/docker/go-events v0.0.0-20250808211157-605354379745/go.mod h1:Uw6UezgYA44ePAFQYUehOuCzmy5zmg/+nl2ZfMWGkpA= +github.com/docker/go-metrics v0.0.1 h1:AgB/0SvBxihN0X8OR4SjsblXkbMvalQ8cjmtKQ2rQV8= +github.com/docker/go-metrics v0.0.1/go.mod h1:cG1hvH2utMXtqgqqYE9plW6lDxS3/5ayHzueweSI3Vw= github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4= github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= +github.com/dylibso/observe-sdk/go v0.0.0-20240819160327-2d926c5d788a h1:UwSIFv5g5lIvbGgtf3tVwC7Ky9rmMFBp0RMs+6f6YqE= +github.com/dylibso/observe-sdk/go v0.0.0-20240819160327-2d926c5d788a/go.mod h1:C8DzXehI4zAbrdlbtOByKX6pfivJTBiV9Jjqv56Yd9Q= github.com/emicklei/go-restful/v3 v3.13.0 h1:C4Bl2xDndpU6nJ4bc1jXd+uTmYPVUwkD6bFY/oTyCes= github.com/emicklei/go-restful/v3 v3.13.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= github.com/evanphx/json-patch/v5 v5.9.11 h1:/8HVnzMq13/3x9TPvjG08wUGqBTmZBsCWzjTM0wiaDU= github.com/evanphx/json-patch/v5 v5.9.11/go.mod h1:3j+LviiESTElxA4p3EMKAB9HXj3/XEtnUf6OZxqIQTM= -github.com/fatih/color v1.18.0 h1:S8gINlzdQ840/4pfAwic/ZE0djQEH3wM94VfqLTZcOM= -github.com/fatih/color v1.18.0/go.mod h1:4FelSpRwEGDpQ12mAdzqdOukCy4u8WUtOY6lkT/6HfU= +github.com/exponent-io/jsonpath v0.0.0-20210407135951-1de76d718b3f h1:Wl78ApPPB2Wvf/TIe2xdyJxTlb6obmF18d8QdkxNDu4= +github.com/exponent-io/jsonpath v0.0.0-20210407135951-1de76d718b3f/go.mod h1:OSYXu++VVOHnXeitef/D8n/6y4QV8uLHSFXX4NeXMGc= +github.com/extism/go-sdk v1.7.1 h1:lWJos6uY+tRFdlIHR+SJjwFDApY7OypS/2nMhiVQ9Sw= +github.com/extism/go-sdk v1.7.1/go.mod h1:IT+Xdg5AZM9hVtpFUA+uZCJMge/hbvshl8bwzLtFyKA= +github.com/fatih/color v1.19.0 h1:Zp3PiM21/9Ld6FzSKyL5c/BULoe/ONr9KlbYVOfG8+w= +github.com/fatih/color v1.19.0/go.mod h1:zNk67I0ZUT1bEGsSGyCZYZNrHuTkJJB+r6Q9VuMi0LE= github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg= github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= +github.com/fluxcd/cli-utils v1.2.0 h1:1o07pXTMxJ/XJ1GpAbLtjdXwfCUMq4Ku1OcnvJHLohI= +github.com/fluxcd/cli-utils v1.2.0/go.mod h1:d5HdTDdR5sCbsIbgtOQ7x7srKYwYeZORU6CD2yn4j/M= +github.com/foxcpp/go-mockdns v1.2.0 h1:omK3OrHRD1IWJz1FuFBCFquhXslXoF17OvBS6JPzZF0= +github.com/foxcpp/go-mockdns v1.2.0/go.mod h1:IhLeSFGed3mJIAXPH2aiRQB+kqz7oqu8ld2qVbOu7Wk= +github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8= +github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0= github.com/fsnotify/fsnotify v1.9.0 h1:2Ml+OJNzbYCTzsxtv8vKSFD9PbJjmhYF14k/jKC7S9k= github.com/fsnotify/fsnotify v1.9.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0= github.com/fxamacker/cbor/v2 v2.9.0 h1:NpKPmjDBgUfBms6tr6JZkTHtfFGcMKsw3eGcmD/sapM= github.com/fxamacker/cbor/v2 v2.9.0/go.mod h1:vM4b+DJCtHn+zz7h3FFp/hDAI9WNWCsZj23V5ytsSxQ= +github.com/go-errors/errors v1.5.1 h1:ZwEMSLRCapFLflTpT7NKaAc7ukJ8ZPEjzlxt8rPN8bk= +github.com/go-errors/errors v1.5.1/go.mod h1:sIVyrIiJhuEF+Pj9Ebtd6P/rEYROXFi3BopGUQ5a5Og= +github.com/go-gorp/gorp/v3 v3.1.0 h1:ItKF/Vbuj31dmV4jxA1qblpSwkl9g1typ24xoe70IGs= +github.com/go-gorp/gorp/v3 v3.1.0/go.mod h1:dLEjIyyRNiXvNZ8PSmzpt1GsWAUK8kjVhEpjH8TixEw= github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI= github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= +github.com/go-logr/zapr v1.3.0 h1:XGdV8XW8zdwFiwOA2Dryh1gj2KRQyOOoNmBy4EplIcQ= +github.com/go-logr/zapr v1.3.0/go.mod h1:YKepepNBd1u/oyhd/yQmtjVXmm9uML4IXUgMOwR8/Gg= github.com/go-openapi/jsonpointer v0.22.1 h1:sHYI1He3b9NqJ4wXLoJDKmUmHkWy/L7rtEo92JUxBNk= github.com/go-openapi/jsonpointer v0.22.1/go.mod h1:pQT9OsLkfz1yWoMgYFy4x3U5GY5nUlsOn1qSBH5MkCM= github.com/go-openapi/jsonreference v0.21.3 h1:96Dn+MRPa0nYAR8DR1E03SblB5FJvh7W6krPI0Z7qMc= @@ -209,8 +253,14 @@ github.com/go-openapi/swag/yamlutils v0.25.1 h1:mry5ez8joJwzvMbaTGLhw8pXUnhDK91o github.com/go-openapi/swag/yamlutils v0.25.1/go.mod h1:cm9ywbzncy3y6uPm/97ysW8+wZ09qsks+9RS8fLWKqg= github.com/go-openapi/testify/v2 v2.0.2 h1:X999g3jeLcoY8qctY/c/Z8iBHTbwLz7R2WXd6Ub6wls= github.com/go-openapi/testify/v2 v2.0.2/go.mod h1:HCPmvFFnheKK2BuwSA0TbbdxJ3I16pjwMkYkP4Ywn54= +github.com/go-sql-driver/mysql v1.8.1 h1:LedoTUt/eveggdHS9qUFC1EFSa8bU2+1pZjSRpvNJ1Y= +github.com/go-sql-driver/mysql v1.8.1/go.mod h1:wEBSXgmK//2ZFJyE+qWnIsVGmvmEKlqwuVSjsCm7DZg= github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1vB6EwHI= github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8= +github.com/gobwas/glob v0.2.3 h1:A4xDbljILXROh+kObIiy5kIaPYD8e96x1tgBhUI5J+Y= +github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJAkT8= +github.com/gofrs/flock v0.13.0 h1:95JolYOvGMqeH31+FC7D2+uULf6mG61mEZ/A8dRYMzw= +github.com/gofrs/flock v0.13.0/go.mod h1:jxeyy9R1auM5S6JYDBhDt+E2TCo7DkratH4Pgi8P+Z0= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= github.com/golang-jwt/jwt/v4 v4.0.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzwAxVc6locg= @@ -218,12 +268,8 @@ github.com/golang-jwt/jwt/v4 v4.2.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzw github.com/golang-jwt/jwt/v4 v4.5.0/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0= github.com/golang-jwt/jwt/v4 v4.5.2 h1:YtQM7lnr8iZ+j5q71MGKkNw9Mn7AjHM68uc9g5fXeUI= github.com/golang-jwt/jwt/v4 v4.5.2/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0= -github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= -github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= github.com/google/btree v1.1.3 h1:CVpQJjYgC4VbzxeGVHfvZrv1ctoYCAI8vbl07Fcxlyg= github.com/google/btree v1.1.3/go.mod h1:qOPhT0dTNdNzV6Z/lhRX0YXUafgPLFUh+gZMl761Gm4= -github.com/google/cel-go v0.26.1 h1:iPbVVEdkhTX++hpe3lzSk7D3G3QSYqLGoHOcEio+UXQ= -github.com/google/cel-go v0.26.1/go.mod h1:A9O8OU9rdvrK5MQyrqfIxo1a0u4g3sF8KB6PUIaryMM= github.com/google/gnostic-models v0.7.0 h1:qwTtogB15McXDaNqTZdzPJRHvaVJlAl+HVQnLmJEJxo= github.com/google/gnostic-models v0.7.0/go.mod h1:whL5G0m6dmc5cPxKc5bdKdEN3UjI7OUGxBlw57miDrQ= github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= @@ -238,24 +284,38 @@ github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17 github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0= github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= -github.com/google/pprof v0.0.0-20250315033105-103756e64e1d h1:tx51Lf+wdE+aavqH8TcPJoCjTf4cE8hrMzROghCely0= -github.com/google/pprof v0.0.0-20250315033105-103756e64e1d/go.mod h1:vavhavw2zAxS5dIdcRluK6cSGGPlZynqzFM8NdvU144= +github.com/google/pprof v0.0.0-20260115054156-294ebfa9ad83 h1:z2ogiKUYzX5Is6zr/vP9vJGqPwcdqsWjOt+V8J7+bTc= +github.com/google/pprof v0.0.0-20260115054156-294ebfa9ad83/go.mod h1:MxpfABSjhmINe3F1It9d+8exIHFvUqtLIRCdOGNXqiI= github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 h1:El6M4kTTCOh6aBiKaUGG7oYTSPP8MxqL4YI3kZKwcP4= github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/gorilla/handlers v1.5.2 h1:cLTUSsNkgcwhgRqvCNmdbRWG0A3N4F+M2nWKdScwyEE= +github.com/gorilla/handlers v1.5.2/go.mod h1:dX+xVpaxdSw+q0Qek8SSsl3dfMk3jNddUkMzo0GtH0w= +github.com/gorilla/mux v1.8.1 h1:TuBL49tXwgrFYWhqrNgrUNEY92u81SPhu7sTdzQEiWY= +github.com/gorilla/mux v1.8.1/go.mod h1:AKf9I4AEqPTmMytcMc0KkNouC66V3BtZ4qD5fmWSiMQ= github.com/gorilla/websocket v1.5.4-0.20250319132907-e064f32e3674 h1:JeSE6pjso5THxAzdVpqr6/geYxZytqFMBCOtn/ujyeo= github.com/gorilla/websocket v1.5.4-0.20250319132907-e064f32e3674/go.mod h1:r4w70xmWCQKmi1ONH4KIaBptdivuRPyosB9RmPlGEwA= -github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 h1:Ovs26xHkKqVztRpIrF/92BcuyuQ/YW4NSIpoGtfXNho= -github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.3 h1:NmZ1PKzSTQbuGHw9DGPFomqkkLWMC+vZCkfs+FHv1Vg= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.3/go.mod h1:zQrxl1YP88HQlA6i9c63DSVPFklWpGX4OWAc9bFuaH4= +github.com/gosuri/uitable v0.0.4 h1:IG2xLKRvErL3uhY6e1BylFzG+aJiwQviDDTfOKeKTpY= +github.com/gosuri/uitable v0.0.4/go.mod h1:tKR86bXuXPZazfOTG1FIzvjIdXzd0mo4Vtn16vt0PJo= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.28.0 h1:HWRh5R2+9EifMyIHV7ZV+MIZqgz+PMpZ14Jynv3O2Zs= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.28.0/go.mod h1:JfhWUomR1baixubs02l85lZYYOm7LV6om4ceouMv45c= github.com/hashicorp/go-version v1.7.0 h1:5tqGy27NaOTB8yJKUZELlFAS/LTKJkrmONwQKeRZfjY= github.com/hashicorp/go-version v1.7.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= +github.com/hashicorp/golang-lru/arc/v2 v2.0.5 h1:l2zaLDubNhW4XO3LnliVj0GXO3+/CGNJAg1dcN2Fpfw= +github.com/hashicorp/golang-lru/arc/v2 v2.0.5/go.mod h1:ny6zBSQZi2JxIeYcv7kt2sH2PXJtirBN7RDhRpxPkxU= +github.com/hashicorp/golang-lru/v2 v2.0.5 h1:wW7h1TG88eUIJ2i69gaE3uNVtEPIagzhGvHgwfx2Vm4= +github.com/hashicorp/golang-lru/v2 v2.0.5/go.mod h1:QeFd9opnmA6QUJc5vARoKUSoFhyfM2/ZepoAG6RGpeM= +github.com/huandu/xstrings v1.5.0 h1:2ag3IFq9ZDANvthTwTiqSSZLjDc+BedvHPAp5tJy2TI= +github.com/huandu/xstrings v1.5.0/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE= +github.com/ianlancetaylor/demangle v0.0.0-20240805132620-81f5be970eca h1:T54Ema1DU8ngI+aef9ZhAhNGQhcRTrWxVeG07F+c/Rw= +github.com/ianlancetaylor/demangle v0.0.0-20240805132620-81f5be970eca/go.mod h1:gx7rwoVhcfuVKG5uya9Hs3Sxj7EIvldVofAWIUtGouw= github.com/imdario/mergo v0.3.16 h1:wwQJbIsHYGMUyLSPrEq1CT16AhnhNJQ51+4fdHUnCl4= github.com/imdario/mergo v0.3.16/go.mod h1:WBLT9ZmE3lPoWsEzCh9LPo3TiwVN+ZKEjmz+hD27ysY= github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= +github.com/jmoiron/sqlx v1.4.0 h1:1PLqN7S1UYp5t4SrVVnt4nUVNemrDAtxlulVe+Qgm3o= +github.com/jmoiron/sqlx v1.4.0/go.mod h1:ZrZ7UsYB/weZdl2Bxg6jCRO9c3YHl8r3ahlKmRT4JLY= github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0= github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4= github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= @@ -268,8 +328,8 @@ github.com/k14s/ytt v0.39.0 h1:SSdF030TVUBTP9lGge51v5GLgUjgu49B7l/YPzzrm8g= github.com/k14s/ytt v0.39.0/go.mod h1:JLCkplRQQm6X+4FqgAYrwvDtVxzMCZxe88bH1kr4bgQ= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= -github.com/klauspost/compress v1.18.1 h1:bcSGx7UbpBqMChDtsF28Lw6v/G94LPrrbMbdC3JH2co= -github.com/klauspost/compress v1.18.1/go.mod h1:ZQFFVG+MdnR0P+l6wpXgIL4NTtwiKIdBnrBd8Nrxr+0= +github.com/klauspost/compress v1.18.4 h1:RPhnKRAQ4Fh8zU2FY/6ZFDwTVTxgJ/EMydqSTzE9a2c= +github.com/klauspost/compress v1.18.4/go.mod h1:R0h/fSBs8DE4ENlcrlib3PsXS61voFxhIs2DeRhCvJ4= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/kr/pty v1.1.8 h1:AkaSdXYQOWeaO3neb8EM634ahkXXe3jYbVh/F9lq+GI= @@ -278,6 +338,13 @@ github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= +github.com/lann/builder v0.0.0-20180802200727-47ae307949d0 h1:SOEGU9fKiNWd/HOJuq6+3iTQz8KNCLtVX6idSoTLdUw= +github.com/lann/builder v0.0.0-20180802200727-47ae307949d0/go.mod h1:dXGbAdH5GtBTC4WfIxhKZfyBF/HBFgRZSWwZ9g/He9o= +github.com/lann/ps v0.0.0-20150810152359-62de8c46ede0 h1:P6pPBnrTSX3DEVR4fDembhRWSsG5rVo6hYhAB/ADZrk= +github.com/lann/ps v0.0.0-20150810152359-62de8c46ede0/go.mod h1:vmVJ0l/dxyfGW6FmdpVm2joNMFikkuWg0EoCKLGUMNw= +github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= +github.com/lib/pq v1.12.3 h1:tTWxr2YLKwIvK90ZXEw8GP7UFHtcbTtty8zsI+YjrfQ= +github.com/lib/pq v1.12.3/go.mod h1:/p+8NSbOcwzAEI7wiMXFlgydTwcgTr3OSKMsD2BitpA= github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de h1:9TO3cAIGXtEhnIaL+V+BEER86oLrvS+kWobKpbJuye0= github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de/go.mod h1:zAbeS9B/r2mtpb6U+EI2rYA5OAXxsYw6wTamcNW+zcE= github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= @@ -289,18 +356,24 @@ github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWE github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/mattn/go-runewidth v0.0.19 h1:v++JhqYnZuu5jSKrk9RbgF5v4CGUjqRfBm05byFGLdw= github.com/mattn/go-runewidth v0.0.19/go.mod h1:XBkDxAl56ILZc9knddidhrOlY5R/pDhgLpndooCuJAs= -github.com/mattn/go-shellwords v1.0.12 h1:M2zGm7EW6UQJvDeQxo4T51eKPurbeFbe8WtebGE2xrk= -github.com/mattn/go-shellwords v1.0.12/go.mod h1:EZzvwXDESEeg03EKmM+RmDnNOPKG4lLtQsUlTZDWQ8Y= +github.com/mattn/go-shellwords v1.0.13 h1:DC0OMEpGjm6LfNFU4ckYcvbQKyp2vE8atyFGXNtDcf4= +github.com/mattn/go-shellwords v1.0.13/go.mod h1:EZzvwXDESEeg03EKmM+RmDnNOPKG4lLtQsUlTZDWQ8Y= +github.com/mattn/go-sqlite3 v1.14.22 h1:2gZY6PC6kBnID23Tichd1K+Z0oS6nE/XwU+Vz/5o4kU= +github.com/mattn/go-sqlite3 v1.14.22/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y= +github.com/miekg/dns v1.1.57 h1:Jzi7ApEIzwEPLHWRcafCN9LZSBbqQpxjt/wpgvg7wcM= +github.com/miekg/dns v1.1.57/go.mod h1:uqRjCRUuEAA6qsOiJvDd+CFo/vW+y5WR6SNmHE55hZk= +github.com/mitchellh/copystructure v1.2.0 h1:vpKXTN4ewci03Vljg/q9QvCGUDttBOGBIa15WveJJGw= +github.com/mitchellh/copystructure v1.2.0/go.mod h1:qLl+cE2AmVv+CoeAwDPye/v+N2HKCj9FbZEVFJRxO9s= github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= github.com/mitchellh/go-wordwrap v1.0.1 h1:TLuKupo69TCn6TQSyGxwI1EblZZEsQ0vMlAFQflz0v0= github.com/mitchellh/go-wordwrap v1.0.1/go.mod h1:R62XHJLzvMFRBbcrT7m7WgmE1eOyTSsCt+hzestvNj0= github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= +github.com/mitchellh/reflectwalk v1.0.2 h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zxSIeXaQ= +github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= github.com/moby/docker-image-spec v1.3.1 h1:jMKff3w6PgbfSa69GfNg+zN/XLhfXJGnEx3Nl2EsFP0= github.com/moby/docker-image-spec v1.3.1/go.mod h1:eKmb5VW8vQEh/BAr2yvVNvuiJuY6UIocYsFu/DxxRpo= -github.com/moby/spdystream v0.5.1 h1:9sNYeYZUcci9R6/w7KDaFWEWeV4LStVG78Mpyq/Zm/Y= -github.com/moby/spdystream v0.5.1/go.mod h1:xBAYlnt/ay+11ShkdFKNAG7LsyK/tmNBVvVOwrfMgdI= github.com/moby/sys/atomicwriter v0.1.0 h1:kw5D/EqkBwsBFi0ss9v1VG3wIkVhzGvLklJ+w3A14Sw= github.com/moby/sys/atomicwriter v0.1.0/go.mod h1:Ul8oqv2ZMNHOceF643P6FKPXeCmYtlQMvpizfsSoaWs= github.com/moby/sys/sequential v0.6.0 h1:qrx7XFUd/5DxtqcoH1h438hF5TmOvzC/lspjy7zgvCU= @@ -313,32 +386,34 @@ github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJ github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= github.com/modern-go/reflect2 v1.0.3-0.20250322232337-35a7c28c31ee h1:W5t00kpgFdJifH4BDsTlE89Zl93FEloxaWZfGcifgq8= github.com/modern-go/reflect2 v1.0.3-0.20250322232337-35a7c28c31ee/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= +github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00 h1:n6/2gBQ3RWajuToeY6ZtZTIKv2v7ThUy5KKusIT0yc0= +github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00/go.mod h1:Pm3mSP3c5uWn86xMLZ5Sa7JB9GsEZySvHYXCTK4E9q4= github.com/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A= github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= -github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f h1:y5//uYreIhSUg3J1GEMiLbxo1LJaP8RfCpH6pymGZus= -github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw= github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE= github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= github.com/onsi/ginkgo v1.16.4 h1:29JGrr5oVBm5ulCWet69zQkzWipVXIol6ygQUe/EzNc= github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0= -github.com/onsi/ginkgo/v2 v2.23.0 h1:FA1xjp8ieYDzlgS5ABTpdUDB7wtngggONc8a7ku2NqQ= -github.com/onsi/ginkgo/v2 v2.23.0/go.mod h1:zXTP6xIp3U8aVuXN8ENK9IXRaTjFnpVB9mGmaSRvxnM= -github.com/onsi/gomega v1.36.2 h1:koNYke6TVk6ZmnyHrCXba/T/MoLBXFjeC1PtvYgw0A8= -github.com/onsi/gomega v1.36.2/go.mod h1:DdwyADRjrc825LhMEkD76cHR5+pUnjhUN8GlHlRPHzY= +github.com/onsi/ginkgo/v2 v2.28.1 h1:S4hj+HbZp40fNKuLUQOYLDgZLwNUVn19N3Atb98NCyI= +github.com/onsi/ginkgo/v2 v2.28.1/go.mod h1:CLtbVInNckU3/+gC8LzkGUb9oF+e8W8TdUsxPwvdOgE= +github.com/onsi/gomega v1.39.1 h1:1IJLAad4zjPn2PsnhH70V4DKRFlrCzGBNrNaru+Vf28= +github.com/onsi/gomega v1.39.1/go.mod h1:hL6yVALoTOxeWudERyfppUcZXjMwIMLnuSfruD2lcfg= github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= github.com/opencontainers/image-spec v1.1.1 h1:y0fUlFfIZhPF1W537XOLg0/fcx6zcHCJwooC2xJA040= github.com/opencontainers/image-spec v1.1.1/go.mod h1:qpqAh3Dmcf36wStyyWU+kCeDgrGnAve2nCC8+7h8Q0M= -github.com/openshift/crd-schema-checker v0.0.0-20250905140724-c313b6407231 h1:8lSGufji9rfiyDxtUl7A4uOyeeP4x0UOOXcsDBFfkGI= -github.com/openshift/crd-schema-checker v0.0.0-20250905140724-c313b6407231/go.mod h1:sTxJ4ZFW9r9fEdbW2v0yMRi6NcyTbx0fII4p83IQ+L8= +github.com/openshift/crd-schema-checker v0.0.0-20240404194209-35a9033b1d11 h1:eTNDkNRNV5lZvUbVM9Nop0lBcljSnA8rZX6yQPZ0ZnU= +github.com/openshift/crd-schema-checker v0.0.0-20240404194209-35a9033b1d11/go.mod h1:EmVJt97N+pfWFsli/ipXTBZqSG5F5KGQhm3c3IsGq1o= github.com/otiai10/copy v1.14.1 h1:5/7E6qsUMBaH5AnQ0sSLzzTg1oTECmcCmT6lvF45Na8= github.com/otiai10/copy v1.14.1/go.mod h1:oQwrEDDOci3IM8dJF0d8+jnbfPDllW6vUjNc3DoZm9I= github.com/otiai10/mint v1.6.3 h1:87qsV/aw1F5as1eH1zS/yqHY85ANKVMgkDrf9rcxbQs= github.com/otiai10/mint v1.6.3/go.mod h1:MJm72SBthJjz8qhefc4z1PYEieWmy8Bku7CjcAqyUSM= github.com/pelletier/go-toml v1.9.5 h1:4yBQzkHv+7BHq2PQUZF3Mx0IYxG7LsP222s7Agd3ve8= github.com/pelletier/go-toml v1.9.5/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= +github.com/peterbourgon/diskv v2.0.1+incompatible h1:UBdAOUP5p4RWqPBg048CAvpKN+vxiaj6gdUUzhl4XmI= +github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU= github.com/phayes/freeport v0.0.0-20220201140144-74d24b5ae9f5 h1:Ii+DKncOVM8Cu1Hc+ETb5K+23HdAMvESYE3ZJ5b5cMI= github.com/phayes/freeport v0.0.0-20220201140144-74d24b5ae9f5/go.mod h1:iIss55rKnNBTvrwdmkUpLnDpZoAHvWaiq5+iMmen4AE= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= @@ -346,40 +421,63 @@ github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINE github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/poy/onpar v1.1.2 h1:QaNrNiZx0+Nar5dLgTVp5mXkyoVFIbepjyEoGSnhbAY= +github.com/poy/onpar v1.1.2/go.mod h1:6X8FLNoxyr9kkmnlqpK6LSoiOtrO6MICtWwEuWkLjzg= github.com/prometheus/client_golang v1.23.2 h1:Je96obch5RDVy3FDMndoUsjAhG5Edi49h0RJWRi/o0o= github.com/prometheus/client_golang v1.23.2/go.mod h1:Tb1a6LWHB3/SPIzCoaDXI4I8UHKeFTEQ1YCr+0Gyqmg= github.com/prometheus/client_model v0.6.2 h1:oBsgwpGs7iVziMvrGhE53c/GrLUsZdHnqNwqPLxwZyk= github.com/prometheus/client_model v0.6.2/go.mod h1:y3m2F6Gdpfy6Ut/GBsUqTWZqCUvMVzSfMLjcu6wAwpE= -github.com/prometheus/common v0.67.2 h1:PcBAckGFTIHt2+L3I33uNRTlKTplNzFctXcWhPyAEN8= -github.com/prometheus/common v0.67.2/go.mod h1:63W3KZb1JOKgcjlIr64WW/LvFGAqKPj0atm+knVGEko= -github.com/prometheus/procfs v0.19.2 h1:zUMhqEW66Ex7OXIiDkll3tl9a1ZdilUOd/F6ZXw4Vws= -github.com/prometheus/procfs v0.19.2/go.mod h1:M0aotyiemPhBCM0z5w87kL22CxfcH05ZpYlu+b4J7mw= +github.com/prometheus/common v0.67.5 h1:pIgK94WWlQt1WLwAC5j2ynLaBRDiinoAb86HZHTUGI4= +github.com/prometheus/common v0.67.5/go.mod h1:SjE/0MzDEEAyrdr5Gqc6G+sXI67maCxzaT3A2+HqjUw= +github.com/prometheus/otlptranslator v1.0.0 h1:s0LJW/iN9dkIH+EnhiD3BlkkP5QVIUVEoIwkU+A6qos= +github.com/prometheus/otlptranslator v1.0.0/go.mod h1:vRYWnXvI6aWGpsdY/mOT/cbeVRBlPWtBNDb7kGR3uKM= +github.com/prometheus/procfs v0.20.1 h1:XwbrGOIplXW/AU3YhIhLODXMJYyC1isLFfYCsTEycfc= +github.com/prometheus/procfs v0.20.1/go.mod h1:o9EMBZGRyvDrSPH1RqdxhojkuXstoe4UlK79eF5TGGo= +github.com/redis/go-redis/extra/rediscmd/v9 v9.0.5 h1:EaDatTxkdHG+U3Bk4EUr+DZ7fOGwTfezUiUJMaIcaho= +github.com/redis/go-redis/extra/rediscmd/v9 v9.0.5/go.mod h1:fyalQWdtzDBECAQFBJuQe5bzQ02jGd5Qcbgb97Flm7U= +github.com/redis/go-redis/extra/redisotel/v9 v9.0.5 h1:EfpWLLCyXw8PSM2/XNJLjI3Pb27yVE+gIAfeqp8LUCc= +github.com/redis/go-redis/extra/redisotel/v9 v9.0.5/go.mod h1:WZjPDy7VNzn77AAfnAfVjZNvfJTYfPetfZk5yoSTLaQ= +github.com/redis/go-redis/v9 v9.7.3 h1:YpPyAayJV+XErNsatSElgRZZVCwXX9QzkKYNvO7x0wM= +github.com/redis/go-redis/v9 v9.7.3/go.mod h1:bGUrSggJ9X9GUmZpZNEOQKaANxSGgOEBRltRTZHSvrA= github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ= github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc= +github.com/rubenv/sql-migrate v1.8.1 h1:EPNwCvjAowHI3TnZ+4fQu3a915OpnQoPAjTXCGOy2U0= +github.com/rubenv/sql-migrate v1.8.1/go.mod h1:BTIKBORjzyxZDS6dzoiw6eAFYJ1iNlGAtjn4LGeVjS8= github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= -github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= -github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= -github.com/spf13/cobra v1.10.1 h1:lJeBwCfmrnXthfAupyUTzJ/J4Nc1RsHC/mSRU2dll/s= -github.com/spf13/cobra v1.10.1/go.mod h1:7SmJGaTHFVBY0jW4NXGluQoLvhqFQM+6XSKD+P4XaB0= +github.com/santhosh-tekuri/jsonschema/v6 v6.0.2 h1:KRzFb2m7YtdldCEkzs6KqmJw4nqEVZGK7IN2kJkjTuQ= +github.com/santhosh-tekuri/jsonschema/v6 v6.0.2/go.mod h1:JXeL+ps8p7/KNMjDQk3TCwPpBy0wYklyWTfbkIzdIFU= +github.com/sergi/go-diff v1.4.0 h1:n/SP9D5ad1fORl+llWyN+D6qoUETXNZARKjyY2/KVCw= +github.com/sergi/go-diff v1.4.0/go.mod h1:A0bzQcvG0E7Rwjx0REVgAGH58e96+X0MeOfepqsbeW4= +github.com/shopspring/decimal v1.4.0 h1:bxl37RwXBklmTi0C79JfXCEBD1cqqHt0bbgBAGFp81k= +github.com/shopspring/decimal v1.4.0/go.mod h1:gawqmDU56v4yIKSwfBSFip1HdCCXN8/+DMd9qYNcwME= +github.com/sirupsen/logrus v1.9.4 h1:TsZE7l11zFCLZnZ+teH4Umoq5BhEIfIzfRDZ1Uzql2w= +github.com/sirupsen/logrus v1.9.4/go.mod h1:ftWc9WdOfJ0a92nsE2jF5u5ZwH8Bv2zdeOC42RjbV2g= +github.com/spf13/cast v1.7.0 h1:ntdiHjuueXFgm5nzDRdOS4yfT43P5Fnud6DH50rz/7w= +github.com/spf13/cast v1.7.0/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo= +github.com/spf13/cobra v1.10.2 h1:DMTTonx5m65Ic0GOoRY2c16WCbHxOOw6xxezuLaBpcU= +github.com/spf13/cobra v1.10.2/go.mod h1:7C1pvHqHw5A4vrJfjNwvOdzYu0Gml16OCs2GRiTUUS4= github.com/spf13/pflag v1.0.9/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/spf13/pflag v1.0.10 h1:4EBh2KAYBwaONj6b2Ye1GiHfwjqyROoF4RwYO+vPwFk= github.com/spf13/pflag v1.0.10/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= -github.com/stoewer/go-strcase v1.3.1 h1:iS0MdW+kVTxgMoE1LAZyMiYJFKlOzLooE4MxjirtkAs= -github.com/stoewer/go-strcase v1.3.1/go.mod h1:fAH5hQ5pehh+j3nZfvwdk2RgEgQjAoM8wodgtPmh1xo= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY= github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= +github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= -github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U= github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U= +github.com/tetratelabs/wabin v0.0.0-20230304001439-f6f874872834 h1:ZF+QBjOI+tILZjBaFj3HgFonKXUcwgJ4djLb6i42S3Q= +github.com/tetratelabs/wabin v0.0.0-20230304001439-f6f874872834/go.mod h1:m9ymHTgNSEjuxvw8E7WWe4Pl4hZQHXONY8wE6dMLaRk= +github.com/tetratelabs/wazero v1.11.0 h1:+gKemEuKCTevU4d7ZTzlsvgd1uaToIDtlQlmNbwqYhA= +github.com/tetratelabs/wazero v1.11.0/go.mod h1:eV28rsN8Q+xwjogd7f4/Pp4xFxO7uOGbLcD/LzB1wiU= github.com/vbatts/tar-split v0.12.2 h1:w/Y6tjxpeiFMR47yzZPlPj/FcPLpXbTUi/9H7d3CPa4= github.com/vbatts/tar-split v0.12.2/go.mod h1:eF6B6i6ftWQcDqEn3/iGFRFRo8cBIMSJVOpnNdfTMFA= github.com/vito/go-interact v1.0.2 h1:viJuANio3WH9utUG4rKbJC9V3JR5JgYNS+i0efeA+GU= @@ -395,45 +493,63 @@ github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 h1:EzJWgHo github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ= github.com/xeipuuv/gojsonschema v1.2.0 h1:LhYJRs+L4fBtjZUfuSZIKGeVu0QRy8e5Xi7D17UxZ74= github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y= +github.com/xlab/treeprint v1.2.0 h1:HzHnuAF1plUN2zGlAFHbSQP2qJ0ZAD3XF5XD7OesXRQ= +github.com/xlab/treeprint v1.2.0/go.mod h1:gj5Gd3gPdKtR1ikdDK6fnFLdmIS0X30kTTuNd/WEJu0= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= -go.etcd.io/etcd/api/v3 v3.6.4 h1:7F6N7toCKcV72QmoUKa23yYLiiljMrT4xCeBL9BmXdo= -go.etcd.io/etcd/api/v3 v3.6.4/go.mod h1:eFhhvfR8Px1P6SEuLT600v+vrhdDTdcfMzmnxVXXSbk= -go.etcd.io/etcd/client/pkg/v3 v3.6.4 h1:9HBYrjppeOfFjBjaMTRxT3R7xT0GLK8EJMVC4xg6ok0= -go.etcd.io/etcd/client/pkg/v3 v3.6.4/go.mod h1:sbdzr2cl3HzVmxNw//PH7aLGVtY4QySjQFuaCgcRFAI= -go.etcd.io/etcd/client/v3 v3.6.4 h1:YOMrCfMhRzY8NgtzUsHl8hC2EBSnuqbR3dh84Uryl7A= -go.etcd.io/etcd/client/v3 v3.6.4/go.mod h1:jaNNHCyg2FdALyKWnd7hxZXZxZANb0+KGY+YQaEMISo= go.opentelemetry.io/auto/sdk v1.2.1 h1:jXsnJ4Lmnqd11kwkBV2LgLoFMZKizbCi5fNZ/ipaZ64= go.opentelemetry.io/auto/sdk v1.2.1/go.mod h1:KRTj+aOaElaLi+wW1kO/DZRXwkF4C5xPbEe3ZiIhN7Y= -go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.60.0 h1:x7wzEgXfnzJcHDwStJT+mxOz4etr2EcexjqhBvmoakw= -go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.60.0/go.mod h1:rg+RlpR5dKwaS95IyyZqj5Wd4E13lk/msnTS0Xl9lJM= -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.63.0 h1:RbKq8BG0FI8OiXhBfcRtqqHcZcka+gU3cskNuf05R18= -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.63.0/go.mod h1:h06DGIukJOevXaj/xrNjhi/2098RZzcLTbc0jDAUbsg= +go.opentelemetry.io/contrib/bridges/prometheus v0.67.0 h1:dkBzNEAIKADEaFnuESzcXvpd09vxvDZsOjx11gjUqLk= +go.opentelemetry.io/contrib/bridges/prometheus v0.67.0/go.mod h1:Z5RIwRkZgauOIfnG5IpidvLpERjhTninpP1dTG2jTl4= +go.opentelemetry.io/contrib/exporters/autoexport v0.67.0 h1:4fnRcNpc6YFtG3zsFw9achKn3XgmxPxuMuqIL5rE8e8= +go.opentelemetry.io/contrib/exporters/autoexport v0.67.0/go.mod h1:qTvIHMFKoxW7HXg02gm6/Wofhq5p3Ib/A/NNt1EoBSQ= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.67.0 h1:OyrsyzuttWTSur2qN/Lm0m2a8yqyIjUVBZcxFPuXq2o= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.67.0/go.mod h1:C2NGBr+kAB4bk3xtMXfZ94gqFDtg/GkI7e9zqGh5Beg= go.opentelemetry.io/otel v1.43.0 h1:mYIM03dnh5zfN7HautFE4ieIig9amkNANT+xcVxAj9I= go.opentelemetry.io/otel v1.43.0/go.mod h1:JuG+u74mvjvcm8vj8pI5XiHy1zDeoCS2LB1spIq7Ay0= -go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.38.0 h1:GqRJVj7UmLjCVyVJ3ZFLdPRmhDUp2zFmQe3RHIOsw24= -go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.38.0/go.mod h1:ri3aaHSmCTVYu2AWv44YMauwAQc0aqI9gHKIcSbI1pU= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.38.0 h1:lwI4Dc5leUqENgGuQImwLo4WnuXFPetmPpkLi2IrX54= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.38.0/go.mod h1:Kz/oCE7z5wuyhPxsXDuaPteSWqjSBD5YaSdbxZYGbGk= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.33.0 h1:wpMfgF8E1rkrT1Z6meFh1NDtownE9Ii3n3X2GJYjsaU= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.33.0/go.mod h1:wAy0T/dUbs468uOlkT31xjvqQgEVXv58BRFWEgn5v/0= +go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploggrpc v0.18.0 h1:deI9UQMoGFgrg5iLPgzueqFPHevDl+28YKfSpPTI6rY= +go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploggrpc v0.18.0/go.mod h1:PFx9NgpNUKXdf7J4Q3agRxMs3Y07QhTCVipKmLsMKnU= +go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp v0.19.0 h1:HIBTQ3VO5aupLKjC90JgMqpezVXwFuq6Ryjn0/izoag= +go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp v0.19.0/go.mod h1:ji9vId85hMxqfvICA0Jt8JqEdrXaAkcpkI9HPXya0ro= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.42.0 h1:MdKucPl/HbzckWWEisiNqMPhRrAOQX8r4jTuGr636gk= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.42.0/go.mod h1:RolT8tWtfHcjajEH5wFIZ4Dgh5jpPdFXYV9pTAk/qjc= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.43.0 h1:w1K+pCJoPpQifuVpsKamUdn9U0zM3xUziVOqsGksUrY= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.43.0/go.mod h1:HBy4BjzgVE8139ieRI75oXm3EcDN+6GhD88JT1Kjvxg= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.43.0 h1:88Y4s2C8oTui1LGM6bTWkw0ICGcOLCAI5l6zsD1j20k= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.43.0/go.mod h1:Vl1/iaggsuRlrHf/hfPJPvVag77kKyvrLeD10kpMl+A= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.42.0 h1:zWWrB1U6nqhS/k6zYB74CjRpuiitRtLLi68VcgmOEto= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.42.0/go.mod h1:2qXPNBX1OVRC0IwOnfo1ljoid+RD0QK3443EaqVlsOU= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.43.0 h1:3iZJKlCZufyRzPzlQhUIWVmfltrXuGyfjREgGP3UUjc= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.43.0/go.mod h1:/G+nUPfhq2e+qiXMGxMwumDrP5jtzU+mWN7/sjT2rak= +go.opentelemetry.io/otel/exporters/prometheus v0.64.0 h1:g0LRDXMX/G1SEZtK8zl8Chm4K6GBwRkjPKE36LxiTYs= +go.opentelemetry.io/otel/exporters/prometheus v0.64.0/go.mod h1:UrgcjnarfdlBDP3GjDIJWe6HTprwSazNjwsI+Ru6hro= +go.opentelemetry.io/otel/exporters/stdout/stdoutlog v0.18.0 h1:KJVjPD3rcPb98rIs3HznyJlrfx9ge5oJvxxlGR+P/7s= +go.opentelemetry.io/otel/exporters/stdout/stdoutlog v0.18.0/go.mod h1:K3kRa2ckmHWQaTWQdPRHc7qGXASuVuoEQXzrvlA98Ws= +go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.42.0 h1:lSZHgNHfbmQTPfuTmWVkEu8J8qXaQwuV30pjCcAUvP8= +go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.42.0/go.mod h1:so9ounLcuoRDu033MW/E0AD4hhUjVqswrMF5FoZlBcw= +go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.42.0 h1:s/1iRkCKDfhlh1JF26knRneorus8aOwVIDhvYx9WoDw= +go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.42.0/go.mod h1:UI3wi0FXg1Pofb8ZBiBLhtMzgoTm1TYkMvn71fAqDzs= +go.opentelemetry.io/otel/log v0.19.0 h1:KUZs/GOsw79TBBMfDWsXS+KZ4g2Ckzksd1ymzsIEbo4= +go.opentelemetry.io/otel/log v0.19.0/go.mod h1:5DQYeGmxVIr4n0/BcJvF4upsraHjg6vudJJpnkL6Ipk= go.opentelemetry.io/otel/metric v1.43.0 h1:d7638QeInOnuwOONPp4JAOGfbCEpYb+K6DVWvdxGzgM= go.opentelemetry.io/otel/metric v1.43.0/go.mod h1:RDnPtIxvqlgO8GRW18W6Z/4P462ldprJtfxHxyKd2PY= go.opentelemetry.io/otel/sdk v1.43.0 h1:pi5mE86i5rTeLXqoF/hhiBtUNcrAGHLKQdhg4h4V9Dg= go.opentelemetry.io/otel/sdk v1.43.0/go.mod h1:P+IkVU3iWukmiit/Yf9AWvpyRDlUeBaRg6Y+C58QHzg= +go.opentelemetry.io/otel/sdk/log v0.19.0 h1:scYVLqT22D2gqXItnWiocLUKGH9yvkkeql5dBDiXyko= +go.opentelemetry.io/otel/sdk/log v0.19.0/go.mod h1:vFBowwXGLlW9AvpuF7bMgnNI95LiW10szrOdvzBHlAg= go.opentelemetry.io/otel/sdk/metric v1.43.0 h1:S88dyqXjJkuBNLeMcVPRFXpRw2fuwdvfCGLEo89fDkw= go.opentelemetry.io/otel/sdk/metric v1.43.0/go.mod h1:C/RJtwSEJ5hzTiUz5pXF1kILHStzb9zFlIEe85bhj6A= go.opentelemetry.io/otel/trace v1.43.0 h1:BkNrHpup+4k4w+ZZ86CZoHHEkohws8AY+WTX09nk+3A= go.opentelemetry.io/otel/trace v1.43.0/go.mod h1:/QJhyVBUUswCphDVxq+8mld+AvhXZLhe+8WVFxiFff0= -go.opentelemetry.io/proto/otlp v1.9.0 h1:l706jCMITVouPOqEnii2fIAuO3IVGBRPV5ICjceRb/A= -go.opentelemetry.io/proto/otlp v1.9.0/go.mod h1:xE+Cx5E/eEHw+ISFkwPLwCZefwVjY+pqKg1qcK03+/4= +go.opentelemetry.io/proto/otlp v1.10.0 h1:IQRWgT5srOCYfiWnpqUYz9CVmbO8bFmKcwYxpuCSL2g= +go.opentelemetry.io/proto/otlp v1.10.0/go.mod h1:/CV4QoCR/S9yaPj8utp3lvQPoqMtxXdzn7ozvvozVqk= go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= -go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8= -go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E= +go.uber.org/zap v1.27.1 h1:08RqriUEv8+ArZRYSTXy1LeBScaMpVSTBhCeaZYfMYc= +go.uber.org/zap v1.27.1/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E= go.yaml.in/yaml/v2 v2.4.3 h1:6gvOSjQoTB3vt1l+CU+tSyi/HOjfOjRLJ4YwYZGwRO0= go.yaml.in/yaml/v2 v2.4.3/go.mod h1:zSxWcmIDjOzPXpjlTTbAsKokqkDNAVtZO0WOMiT90s8= go.yaml.in/yaml/v3 v3.0.4 h1:tfq32ie2Jv2UxXFdLJdh3jXuOzWiL1fo0bu/FbuKpbc= @@ -444,14 +560,16 @@ golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPh golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.17.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4= -golang.org/x/crypto v0.46.0 h1:cKRW/pmt1pKAfetfu+RCEvjvZkA9RimPbh7bhFjGVBU= -golang.org/x/crypto v0.46.0/go.mod h1:Evb/oLKmMraqjZ2iQTwDwvCtJkczlDuTmdJXoZVzqU0= -golang.org/x/exp v0.0.0-20251023183803-a4bb9ffd2546 h1:mgKeJMpvi0yx/sU5GsxQ7p6s2wtOnGAHZWCHUM4KGzY= -golang.org/x/exp v0.0.0-20251023183803-a4bb9ffd2546/go.mod h1:j/pmGrbnkbPtQfxEe5D0VQhZC6qKbfKifgD0oM7sR70= +golang.org/x/crypto v0.50.0 h1:zO47/JPrL6vsNkINmLoo/PH1gcxpls50DNogFvB5ZGI= +golang.org/x/crypto v0.50.0/go.mod h1:3muZ7vA7PBCE6xgPX7nkzzjiUq87kRItoJQM1Yo8S+Q= +golang.org/x/exp v0.0.0-20251219203646-944ab1f22d93 h1:fQsdNF2N+/YewlRZiricy4P1iimyPKZ/xwniHj8Q2a0= +golang.org/x/exp v0.0.0-20251219203646-944ab1f22d93/go.mod h1:EPRbTFwzwjXj9NpYyyrvenVh9Y+GFeEvMNh7Xuz7xgU= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= +golang.org/x/mod v0.34.0 h1:xIHgNUUnW6sYkcM5Jleh05DvLOtwc6RitGHbDk4akRI= +golang.org/x/mod v0.34.0/go.mod h1:ykgH52iCZe79kzLLMhyCUzhMci+nQj+0XkbXpNYtVjY= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= @@ -461,17 +579,17 @@ golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qx golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= -golang.org/x/net v0.48.0 h1:zyQRTTrjc33Lhh0fBgT/H3oZq9WuvRR5gPC70xpDiQU= -golang.org/x/net v0.48.0/go.mod h1:+ndRgGjkh8FGtu1w1FGbEC31if4VrNVMuKTgcAAnQRY= -golang.org/x/oauth2 v0.34.0 h1:hqK/t4AKgbqWkdkcAeI8XLmbK+4m4G5YeQRrmiotGlw= -golang.org/x/oauth2 v0.34.0/go.mod h1:lzm5WQJQwKZ3nwavOZ3IS5Aulzxi68dUSgRHujetwEA= +golang.org/x/net v0.52.0 h1:He/TN1l0e4mmR3QqHMT2Xab3Aj3L9qjbhRm78/6jrW0= +golang.org/x/net v0.52.0/go.mod h1:R1MAz7uMZxVMualyPXb+VaqGSa3LIaUqk0eEt3w36Sw= +golang.org/x/oauth2 v0.36.0 h1:peZ/1z27fi9hUOFCAZaHyrpWG5lwe0RJEEEeH0ThlIs= +golang.org/x/oauth2 v0.36.0/go.mod h1:YDBUJMTkDnJS+A4BP4eZBjCqtokkg1hODuPjwiGPO7Q= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.19.0 h1:vV+1eWNmZ5geRlYjzm2adRgW2/mcpevXNg50YZtPCE4= -golang.org/x/sync v0.19.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI= +golang.org/x/sync v0.20.0 h1:e0PTpb7pjO8GAtTs2dQ6jYa5BWYlMuX047Dco/pItO4= +golang.org/x/sync v0.20.0/go.mod h1:9xrNwdLfx4jkKbNva9FpL6vEN7evnE43NNNJQ2LF3+0= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -483,21 +601,20 @@ golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/sys v0.42.0 h1:omrd2nAlyT5ESRdCLYdm3+fMfNFE/+Rf4bDIQImRJeo= -golang.org/x/sys v0.42.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw= +golang.org/x/sys v0.43.0 h1:Rlag2XtaFTxp19wS8MXlJwTvoh8ArU6ezoyFsMyCTNI= +golang.org/x/sys v0.43.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= golang.org/x/term v0.15.0/go.mod h1:BDl952bC7+uMoWR75FIrCDx79TPU9oHkTZ9yRbYOrX0= -golang.org/x/term v0.38.0 h1:PQ5pkm/rLO6HnxFR7N2lJHOZX6Kez5Y1gDSJla6jo7Q= -golang.org/x/term v0.38.0/go.mod h1:bSEAKrOT1W+VSu9TSCMtoGEOUcKxOKgl3LE5QEF/xVg= +golang.org/x/term v0.42.0 h1:UiKe+zDFmJobeJ5ggPwOshJIVt6/Ft0rcfrXZDLWAWY= +golang.org/x/term v0.42.0/go.mod h1:Dq/D+snpsbazcBG5+F9Q1n2rXV8Ma+71xEjTRufARgY= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= @@ -505,32 +622,31 @@ golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= -golang.org/x/text v0.32.0 h1:ZD01bjUt1FQ9WJ0ClOL5vxgxOI/sVCNgX1YtKwcY0mU= -golang.org/x/text v0.32.0/go.mod h1:o/rUWzghvpD5TXrTIBuJU77MTaN0ljMWE47kxGJQ7jY= -golang.org/x/time v0.14.0 h1:MRx4UaLrDotUKUdCIqzPC48t1Y9hANFKIRpNx+Te8PI= -golang.org/x/time v0.14.0/go.mod h1:eL/Oa2bBBK0TkX57Fyni+NgnyQQN4LitPmob2Hjnqw4= +golang.org/x/text v0.36.0 h1:JfKh3XmcRPqZPKevfXVpI1wXPTqbkE5f7JA92a55Yxg= +golang.org/x/text v0.36.0/go.mod h1:NIdBknypM8iqVmPiuco0Dh6P5Jcdk8lJL0CUebqK164= +golang.org/x/time v0.15.0 h1:bbrp8t3bGUeFOx08pvsMYRTCVSMk89u4tKbNOZbp88U= +golang.org/x/time v0.15.0/go.mod h1:Y4YMaQmXwGQZoFaVFk4YpCt4FLQMYKZe9oeV/f4MSno= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= -golang.org/x/tools v0.39.0 h1:ik4ho21kwuQln40uelmciQPp9SipgNDdrafrYA4TmQQ= -golang.org/x/tools v0.39.0/go.mod h1:JnefbkDPyD8UU2kI5fuf8ZX4/yUeh9W877ZeBONxUqQ= +golang.org/x/tools v0.43.0 h1:12BdW9CeB3Z+J/I/wj34VMl8X+fEXBxVR90JeMX5E7s= +golang.org/x/tools v0.43.0/go.mod h1:uHkMso649BX2cZK6+RpuIPXS3ho2hZo4FVwfoy1vIk0= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -gonum.org/v1/gonum v0.16.0 h1:5+ul4Swaf3ESvrOnidPp4GZbzf0mxVQpDCYUQE7OJfk= -gonum.org/v1/gonum v0.16.0/go.mod h1:fef3am4MQ93R2HHpKnLk4/Tbh/s0+wqD5nfa6Pnwy4E= -google.golang.org/genproto/googleapis/api v0.0.0-20251202230838-ff82c1b0f217 h1:fCvbg86sFXwdrl5LgVcTEvNC+2txB5mgROGmRL5mrls= -google.golang.org/genproto/googleapis/api v0.0.0-20251202230838-ff82c1b0f217/go.mod h1:+rXWjjaukWZun3mLfjmVnQi18E1AsFbDN9QdJ5YXLto= -google.golang.org/genproto/googleapis/rpc v0.0.0-20251202230838-ff82c1b0f217 h1:gRkg/vSppuSQoDjxyiGfN4Upv/h/DQmIR10ZU8dh4Ww= -google.golang.org/genproto/googleapis/rpc v0.0.0-20251202230838-ff82c1b0f217/go.mod h1:7i2o+ce6H/6BluujYR+kqX3GKH+dChPTQU19wjRPiGk= -google.golang.org/grpc v1.79.3 h1:sybAEdRIEtvcD68Gx7dmnwjZKlyfuc61Dyo9pGXXkKE= -google.golang.org/grpc v1.79.3/go.mod h1:KmT0Kjez+0dde/v2j9vzwoAScgEPx/Bw1CYChhHLrHQ= -google.golang.org/protobuf v1.36.10 h1:AYd7cD/uASjIL6Q9LiTjz8JLcrh/88q5UObnmY3aOOE= -google.golang.org/protobuf v1.36.10/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco= +google.golang.org/genproto v0.0.0-20230711160842-782d3b101e98 h1:Z0hjGZePRE0ZBWotvtrwxFNrNE9CUAGtplaDK5NNI/g= +google.golang.org/genproto/googleapis/api v0.0.0-20260401024825-9d38bb4040a9 h1:VPWxll4HlMw1Vs/qXtN7BvhZqsS9cdAittCNvVENElA= +google.golang.org/genproto/googleapis/api v0.0.0-20260401024825-9d38bb4040a9/go.mod h1:7QBABkRtR8z+TEnmXTqIqwJLlzrZKVfAUm7tY3yGv0M= +google.golang.org/genproto/googleapis/rpc v0.0.0-20260401024825-9d38bb4040a9 h1:m8qni9SQFH0tJc1X0vmnpw/0t+AImlSvp30sEupozUg= +google.golang.org/genproto/googleapis/rpc v0.0.0-20260401024825-9d38bb4040a9/go.mod h1:4Hqkh8ycfw05ld/3BWL7rJOSfebL2Q+DVDeRgYgxUU8= +google.golang.org/grpc v1.80.0 h1:Xr6m2WmWZLETvUNvIUmeD5OAagMw3FiKmMlTdViWsHM= +google.golang.org/grpc v1.80.0/go.mod h1:ho/dLnxwi3EDJA4Zghp7k2Ec1+c2jqup0bFkw07bwF4= +google.golang.org/protobuf v1.36.12-0.20260120151049-f2248ac996af h1:+5/Sw3GsDNlEmu7TfklWKPdQ0Ykja5VEmq2i817+jbI= +google.golang.org/protobuf v1.36.12-0.20260120151049-f2248ac996af/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= @@ -547,45 +663,51 @@ gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gotest.tools/v3 v3.4.0 h1:ZazjZUfuVeZGLAmlKKuyv3IKP5orXcwtOwDQH6YVr6o= gotest.tools/v3 v3.4.0/go.mod h1:CtbdzLSsqVhDgMtKsx03ird5YTGB3ar27v0u/yKBW5g= -k8s.io/api v0.34.2 h1:fsSUNZhV+bnL6Aqrp6O7lMTy6o5x2C4XLjnh//8SLYY= -k8s.io/api v0.34.2/go.mod h1:MMBPaWlED2a8w4RSeanD76f7opUoypY8TFYkSM+3XHw= -k8s.io/apiextensions-apiserver v0.34.1 h1:NNPBva8FNAPt1iSVwIE0FsdrVriRXMsaWFMqJbII2CI= -k8s.io/apiextensions-apiserver v0.34.1/go.mod h1:hP9Rld3zF5Ay2Of3BeEpLAToP+l4s5UlxiHfqRaRcMc= -k8s.io/apimachinery v0.34.2 h1:zQ12Uk3eMHPxrsbUJgNF8bTauTVR2WgqJsTmwTE/NW4= -k8s.io/apimachinery v0.34.2/go.mod h1:/GwIlEcWuTX9zKIg2mbw0LRFIsXwrfoVxn+ef0X13lw= -k8s.io/apiserver v0.34.1 h1:U3JBGdgANK3dfFcyknWde1G6X1F4bg7PXuvlqt8lITA= -k8s.io/apiserver v0.34.1/go.mod h1:eOOc9nrVqlBI1AFCvVzsob0OxtPZUCPiUJL45JOTBG0= -k8s.io/cli-runtime v0.34.2 h1:cct1GEuWc3IyVT8MSCoIWzRGw9HJ/C5rgP32H60H6aE= -k8s.io/cli-runtime v0.34.2/go.mod h1:X13tsrYexYUCIq8MarCBy8lrm0k0weFPTpcaNo7lms4= -k8s.io/client-go v0.34.2 h1:Co6XiknN+uUZqiddlfAjT68184/37PS4QAzYvQvDR8M= -k8s.io/client-go v0.34.2/go.mod h1:2VYDl1XXJsdcAxw7BenFslRQX28Dxz91U9MWKjX97fE= -k8s.io/component-base v0.34.2 h1:HQRqK9x2sSAsd8+R4xxRirlTjowsg6fWCPwWYeSvogQ= -k8s.io/component-base v0.34.2/go.mod h1:9xw2FHJavUHBFpiGkZoKuYZ5pdtLKe97DEByaA+hHbM= -k8s.io/component-helpers v0.34.2 h1:RIUGDdU+QFzeVKLZ9f05sXTNAtJrRJ3bnbMLrogCrvM= -k8s.io/component-helpers v0.34.2/go.mod h1:pLi+GByuRTeFjjcezln8gHL7LcT6HImkwVQ3A2SQaEE= +helm.sh/helm/v4 v4.2.0 h1:J+0TmTtPK2NuS6z9Z2WOcIX0nGGJylokEZLt0fi0X4U= +helm.sh/helm/v4 v4.2.0/go.mod h1:sDQRGAct/I/ogTvOX8QqE/8bBWuLH4BHbB3QFL5G3do= +k8s.io/api v0.36.0 h1:SgqDhZzHdOtMk40xVSvCXkP9ME0H05hPM3p9AB1kL80= +k8s.io/api v0.36.0/go.mod h1:m1LVrGPNYax5NBHdO+QuAedXyuzTt4RryI/qnmNvs34= +k8s.io/apiextensions-apiserver v0.36.0 h1:Wt7E8J+VBCbj4FjiBfDTK/neXDDjyJVJc7xfuOHImZ0= +k8s.io/apiextensions-apiserver v0.36.0/go.mod h1:kGDjH0msuiIB3tgsYRV0kS9GqpMYMUsQ3GHv7TApyug= +k8s.io/apimachinery v0.36.0 h1:jZyPzhd5Z+3h9vJLt0z9XdzW9VzNzWAUw+P1xZ9PXtQ= +k8s.io/apimachinery v0.36.0/go.mod h1:FklypaRJt6n5wUIwWXIP6GJlIpUizTgfo1T/As+Tyxc= +k8s.io/apiserver v0.36.0 h1:Jg5OFAENUACByUCg15CmhZAYrr5ZyJ+jodyA1mHl3YE= +k8s.io/apiserver v0.36.0/go.mod h1:mHvwdHf+qKEm+1/hYm756SV+oREOKSPnsjagOpx6Vho= +k8s.io/cli-runtime v0.36.0 h1:HNxciQpQMMOKS0/GiUXcKDyA6J2FDILJj9NmP2BZrTg= +k8s.io/cli-runtime v0.36.0/go.mod h1:KObkknK9Ro5LYX+1RdiKc7C8CvGg4aX+V/Zv+E8WPHA= +k8s.io/client-go v0.36.0 h1:pOYi7C4RHChYjMiHpZSpSbIM6ZxVbRXBy7CuiIwqA3c= +k8s.io/client-go v0.36.0/go.mod h1:ZKKcpwF0aLYfkHFCjillCKaTK/yBkEDHTDXCFY6AS9Y= +k8s.io/component-base v0.36.0 h1:hFjEktssxiJhrK1zfybkH4kJOi8iZuF+mIDCqS5+jRo= +k8s.io/component-base v0.36.0/go.mod h1:JZvIfcNHk+uck+8LhJzhSBtydWXaZNQwX2OdL+Mnwsk= +k8s.io/component-helpers v0.36.0 h1:KznLAOD7oPxjaeheW4SOQijz9UtMO8Nvp89+lR8FYks= +k8s.io/component-helpers v0.36.0/go.mod h1:BqZG+01Z97KR8GN9Stb8SiRmtn/EpZogriuQtpMCsLg= k8s.io/controller-manager v0.33.5 h1:abmssknXnhOhW533583v2SYQObD5RhYiSL7Za1rezGM= k8s.io/controller-manager v0.33.5/go.mod h1:KuQeAlf4vI2+qj5fwPVLaDlbtrTBA/8L/LqQvI74Ow0= -k8s.io/klog/v2 v2.130.1 h1:n9Xl7H1Xvksem4KFG4PYbdQCQxqc/tTUyrgXaOhHSzk= -k8s.io/klog/v2 v2.130.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE= -k8s.io/kube-openapi v0.0.0-20250910181357-589584f1c912 h1:Y3gxNAuB0OBLImH611+UDZcmKS3g6CthxToOb37KgwE= -k8s.io/kube-openapi v0.0.0-20250910181357-589584f1c912/go.mod h1:kdmbQkyfwUagLfXIad1y2TdrjPFWp2Q89B3qkRwf/pQ= -k8s.io/kubectl v0.34.2 h1:+fWGrVlDONMUmmQLDaGkQ9i91oszjjRAa94cr37hzqA= -k8s.io/kubectl v0.34.2/go.mod h1:X2KTOdtZZNrTWmUD4oHApJ836pevSl+zvC5sI6oO2YQ= +k8s.io/klog/v2 v2.140.0 h1:Tf+J3AH7xnUzZyVVXhTgGhEKnFqye14aadWv7bzXdzc= +k8s.io/klog/v2 v2.140.0/go.mod h1:o+/RWfJ6PwpnFn7OyAG3QnO47BFsymfEfrz6XyYSSp0= +k8s.io/kube-openapi v0.0.0-20260317180543-43fb72c5454a h1:xCeOEAOoGYl2jnJoHkC3hkbPJgdATINPMAxaynU2Ovg= +k8s.io/kube-openapi v0.0.0-20260317180543-43fb72c5454a/go.mod h1:uGBT7iTA6c6MvqUvSXIaYZo9ukscABYi2btjhvgKGZ0= +k8s.io/kubectl v0.36.0 h1:hEGr8NvIm2Wjqs2Xy48Uzmvo6lpHdGKlLyMvau2gTms= +k8s.io/kubectl v0.36.0/go.mod h1:iDe8aV5BEi45W8k+5n71I2pJ/nwE0PHDu+/2cejzYoo= k8s.io/kubernetes v1.34.2 h1:WQdDvYJazkmkwSncgNwGvVtaCt4TYXIU3wSMRgvp3MI= k8s.io/kubernetes v1.34.2/go.mod h1:m6pZk6a179pRo2wsTiCPORJ86iOEQmfIzUvtyEF8BwA= -k8s.io/utils v0.0.0-20251002143259-bc988d571ff4 h1:SjGebBtkBqHFOli+05xYbK8YF1Dzkbzn+gDM4X9T4Ck= -k8s.io/utils v0.0.0-20251002143259-bc988d571ff4/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= -sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.34.0 h1:hSfpvjjTQXQY2Fol2CS0QHMNs/WI1MOSGzCm1KhM5ec= -sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.34.0/go.mod h1:Ve9uj1L+deCXFrPOk1LpFXqTg7LCFzFso6PA48q/XZw= -sigs.k8s.io/controller-runtime v0.22.4 h1:GEjV7KV3TY8e+tJ2LCTxUTanW4z/FmNB7l327UfMq9A= -sigs.k8s.io/controller-runtime v0.22.4/go.mod h1:+QX1XUpTXN4mLoblf4tqr5CQcyHPAki2HLXqQMY6vh8= +k8s.io/utils v0.0.0-20260210185600-b8788abfbbc2 h1:AZYQSJemyQB5eRxqcPky+/7EdBj0xi3g0ZcxxJ7vbWU= +k8s.io/utils v0.0.0-20260210185600-b8788abfbbc2/go.mod h1:xDxuJ0whA3d0I4mf/C4ppKHxXynQ+fxnkmQH0vTHnuk= +oras.land/oras-go/v2 v2.6.0 h1:X4ELRsiGkrbeox69+9tzTu492FMUu7zJQW6eJU+I2oc= +oras.land/oras-go/v2 v2.6.0/go.mod h1:magiQDfG6H1O9APp+rOsvCPcW1GD2MM7vgnKY0Y+u1o= +sigs.k8s.io/controller-runtime v0.24.0 h1:Ck6N2LdS8Lovy1o25BB4r1xjvLEKUl1s2o9kU+KWDE4= +sigs.k8s.io/controller-runtime v0.24.0/go.mod h1:vFkfY5fGt5xAC/sKb8IBFKgWPNKG9OUG29dR8Y2wImw= sigs.k8s.io/json v0.0.0-20250730193827-2d320260d730 h1:IpInykpT6ceI+QxKBbEflcR5EXP7sU1kvOlxwZh5txg= sigs.k8s.io/json v0.0.0-20250730193827-2d320260d730/go.mod h1:mdzfpAEoE6DHQEN0uh9ZbOCuHbLK5wOm7dK4ctXE9Tg= sigs.k8s.io/kind v0.29.0 h1:3TpCsyh908IkXXpcSnsMjWdwdWjIl7o9IMZImZCWFnI= sigs.k8s.io/kind v0.29.0/go.mod h1:ldWQisw2NYyM6k64o/tkZng/1qQW7OlzcN5a8geJX3o= +sigs.k8s.io/kustomize/api v0.21.1 h1:lzqbzvz2CSvsjIUZUBNFKtIMsEw7hVLJp0JeSIVmuJs= +sigs.k8s.io/kustomize/api v0.21.1/go.mod h1:f3wkKByTrgpgltLgySCntrYoq5d3q7aaxveSagwTlwI= +sigs.k8s.io/kustomize/kyaml v0.21.1 h1:IVlbmhC076nf6foyL6Taw4BkrLuEsXUXNpsE+ScX7fI= +sigs.k8s.io/kustomize/kyaml v0.21.1/go.mod h1:hmxADesM3yUN2vbA5z1/YTBnzLJ1dajdqpQonwBL1FQ= sigs.k8s.io/randfill v1.0.0 h1:JfjMILfT8A6RbawdsK2JXGBR5AQVfd+9TbzrlneTyrU= sigs.k8s.io/randfill v1.0.0/go.mod h1:XeLlZ/jmk4i1HRopwe7/aU3H5n1zNUcX6TM94b3QxOY= -sigs.k8s.io/structured-merge-diff/v6 v6.3.0 h1:jTijUJbW353oVOd9oTlifJqOGEkUw2jB/fXCbTiQEco= -sigs.k8s.io/structured-merge-diff/v6 v6.3.0/go.mod h1:M3W8sfWvn2HhQDIbGWj3S099YozAsymCo/wrT5ohRUE= +sigs.k8s.io/structured-merge-diff/v6 v6.3.2 h1:kwVWMx5yS1CrnFWA/2QHyRVJ8jM6dBA80uLmm0wJkk8= +sigs.k8s.io/structured-merge-diff/v6 v6.3.2/go.mod h1:M3W8sfWvn2HhQDIbGWj3S099YozAsymCo/wrT5ohRUE= sigs.k8s.io/yaml v1.6.0 h1:G8fkbMSAFqgEFgh4b1wmtzDnioxFCUgTZhlbj5P9QYs= sigs.k8s.io/yaml v1.6.0/go.mod h1:796bPqUfzR/0jLAl6XjHl3Ck7MiyVv8dbTdyT3/pMf4= diff --git a/client-programs/hack/gen-cli-schemas/main.go b/client-programs/hack/gen-cli-schemas/main.go new file mode 100644 index 000000000..2bed00e55 --- /dev/null +++ b/client-programs/hack/gen-cli-schemas/main.go @@ -0,0 +1,252 @@ +// gen-cli-schemas regenerates EducatesConfig.schema.json from the four +// platform CRDs. The escape-hatch kind mirrors the CRDs verbatim, so its +// schema is derived from controller-gen output rather than hand-authored. +// +// Inputs: +// - installer/charts/educates-installer/crds/*.yaml +// +// Output: +// - client-programs/pkg/config/v1alpha1/schemas/EducatesConfig.schema.json +// +// Run from the repo root: +// +// go run ./client-programs/hack/gen-cli-schemas +package main + +import ( + "encoding/json" + "fmt" + "os" + "path/filepath" + "sort" + "strings" + + "gopkg.in/yaml.v2" +) + +const ( + crdDir = "installer/charts/educates-installer/crds" + schemaOut = "client-programs/pkg/config/v1alpha1/schemas/EducatesConfig.schema.json" +) + +// crdSources maps the CRD filename to (envelope-key, $defs-name). Envelope +// key is the camelCase top-level field in EducatesConfig; $defs name is the +// JSON schema definition handle. +var crdSources = []struct { + file string + envKey string + defName string +}{ + {"config.educates.dev_educatesclusterconfigs.yaml", "educatesClusterConfig", "EducatesClusterConfigSpec"}, + {"platform.educates.dev_secretsmanagers.yaml", "secretsManager", "SecretsManagerSpec"}, + {"platform.educates.dev_lookupservices.yaml", "lookupService", "LookupServiceSpec"}, + {"platform.educates.dev_sessionmanagers.yaml", "sessionManager", "SessionManagerSpec"}, +} + +func main() { + if err := run(); err != nil { + fmt.Fprintln(os.Stderr, "gen-cli-schemas:", err) + os.Exit(1) + } +} + +func run() error { + defs := map[string]interface{}{} + envelopeProps := envelopeProperties() + envelopeRequired := []string{"apiVersion", "kind"} + + for _, src := range crdSources { + spec, err := extractSpec(filepath.Join(crdDir, src.file)) + if err != nil { + return fmt.Errorf("%s: %w", src.file, err) + } + defs[src.defName] = sanitise(spec) + envelopeProps[src.envKey] = map[string]interface{}{ + "$ref": "#/$defs/" + src.defName, + } + } + + root := map[string]interface{}{ + "$schema": "http://json-schema.org/draft-07/schema#", + "$id": "https://schemas.educates.dev/cli/v1alpha1/EducatesConfig.json", + "title": "EducatesConfig", + "description": "Escape-hatch CLI config kind. Mirrors the platform CRDs verbatim; CLI hand-wraps apiVersion/kind/metadata at translate time.", + "type": "object", + "additionalProperties": false, + "required": envelopeRequired, + "properties": envelopeProps, + "$defs": defs, + } + + out, err := json.MarshalIndent(root, "", " ") + if err != nil { + return err + } + out = append(out, '\n') + if err := os.WriteFile(schemaOut, out, 0o644); err != nil { + return err + } + fmt.Printf("wrote %s (%d bytes)\n", schemaOut, len(out)) + return nil +} + +// envelopeProperties returns the hand-authored CLI-side envelope fields +// (apiVersion, kind, target, operator). CR-spec fields are added by the +// caller after extracting them from the CRDs. +func envelopeProperties() map[string]interface{} { + return map[string]interface{}{ + "apiVersion": map[string]interface{}{"const": "cli.educates.dev/v1alpha1"}, + "kind": map[string]interface{}{"const": "EducatesConfig"}, + + // target is optional; when absent the CLI skips side effects and + // just applies the declared CRs. provider drives which side + // effects run (kind cluster bootstrap, macOS resolver). + "target": map[string]interface{}{ + "type": "object", + "additionalProperties": false, + "properties": map[string]interface{}{ + "provider": map[string]interface{}{ + "type": "string", + "minLength": 1, + }, + "cluster": map[string]interface{}{"type": "object"}, + "resolver": map[string]interface{}{"type": "object"}, + }, + }, + + "operator": map[string]interface{}{ + "type": "object", + "additionalProperties": false, + "properties": map[string]interface{}{ + "image": map[string]interface{}{ + "type": "object", + "additionalProperties": false, + "properties": map[string]interface{}{ + "repository": map[string]interface{}{"type": "string"}, + "tag": map[string]interface{}{"type": "string"}, + }, + }, + "imagePullSecrets": map[string]interface{}{ + "type": "array", + "items": map[string]interface{}{"type": "string", "minLength": 1}, + }, + "logLevel": map[string]interface{}{ + "type": "string", + "enum": []string{"debug", "info", "warn", "error"}, + "default": "info", + }, + }, + }, + } +} + +// extractSpec navigates a CRD YAML and returns the openAPIV3Schema subtree +// for the v1alpha1 version's spec property. Returned value is a JSON-ready +// nested map. +func extractSpec(path string) (interface{}, error) { + data, err := os.ReadFile(path) + if err != nil { + return nil, err + } + var raw interface{} + if err := yaml.Unmarshal(data, &raw); err != nil { + return nil, err + } + normalised := normalise(raw) + + root, ok := normalised.(map[string]interface{}) + if !ok { + return nil, fmt.Errorf("root is not a map") + } + spec, ok := root["spec"].(map[string]interface{}) + if !ok { + return nil, fmt.Errorf(".spec not a map") + } + versions, ok := spec["versions"].([]interface{}) + if !ok { + return nil, fmt.Errorf(".spec.versions not a list") + } + for _, v := range versions { + ver, ok := v.(map[string]interface{}) + if !ok { + continue + } + if ver["name"] != "v1alpha1" { + continue + } + schema, ok := ver["schema"].(map[string]interface{}) + if !ok { + return nil, fmt.Errorf("v1alpha1.schema not a map") + } + oas, ok := schema["openAPIV3Schema"].(map[string]interface{}) + if !ok { + return nil, fmt.Errorf("openAPIV3Schema not a map") + } + props, ok := oas["properties"].(map[string]interface{}) + if !ok { + return nil, fmt.Errorf("openAPIV3Schema.properties not a map") + } + specProp, ok := props["spec"] + if !ok { + return nil, fmt.Errorf("openAPIV3Schema.properties.spec missing") + } + return specProp, nil + } + return nil, fmt.Errorf("no v1alpha1 version found") +} + +// sanitise walks a CRD-derived schema subtree and removes keys that +// gojsonschema (draft-07) cannot handle: x-kubernetes-* extensions and the +// OpenAPI-only `nullable` keyword. Recursively applied. +func sanitise(v interface{}) interface{} { + switch x := v.(type) { + case map[string]interface{}: + out := make(map[string]interface{}, len(x)) + for k, val := range x { + if strings.HasPrefix(k, "x-kubernetes-") || k == "nullable" { + continue + } + out[k] = sanitise(val) + } + return out + case []interface{}: + out := make([]interface{}, len(x)) + for i, val := range x { + out[i] = sanitise(val) + } + return out + default: + return v + } +} + +// normalise converts yaml.v2's map[interface{}]interface{} to +// map[string]interface{} so the structure can be JSON-marshalled. Keys are +// sorted on traversal so the output schema is deterministic regardless of +// YAML key order. +func normalise(v interface{}) interface{} { + switch x := v.(type) { + case map[interface{}]interface{}: + keys := make([]string, 0, len(x)) + strMap := make(map[string]interface{}, len(x)) + for k, val := range x { + ks := fmt.Sprint(k) + keys = append(keys, ks) + strMap[ks] = normalise(val) + } + sort.Strings(keys) + out := make(map[string]interface{}, len(x)) + for _, k := range keys { + out[k] = strMap[k] + } + return out + case []interface{}: + out := make([]interface{}, len(x)) + for i, val := range x { + out[i] = normalise(val) + } + return out + default: + return v + } +} diff --git a/client-programs/pkg/cluster/kindbootstrap.go b/client-programs/pkg/cluster/kindbootstrap.go new file mode 100644 index 000000000..21c21b43e --- /dev/null +++ b/client-programs/pkg/cluster/kindbootstrap.go @@ -0,0 +1,35 @@ +package cluster + +// KindBootstrapInput is the focused payload the kind-cluster template +// reads from. Decouples cluster-bootstrap rendering from any specific +// CLI config kind: 'local cluster create' builds one from +// EducatesLocalConfig; future scenario kinds (GKE/EKS — though they +// would not use kind) or test fixtures build it directly. +type KindBootstrapInput struct { + ListenAddress string + ApiServer KindApiServer + Networking KindNetworking + VolumeMounts []KindVolumeMount +} + +type KindApiServer struct { + Address string + Port int +} + +type KindNetworking struct { + ServiceSubnet string + PodSubnet string +} + +type KindVolumeMount struct { + HostPath string + ContainerPath string + // HasReadOnly + ReadOnly map to kind's extraMounts[].readOnly. + // The pair models a nullable bool without requiring text/template + // pointer dereference: HasReadOnly=false leaves the field unset + // (kind defaults to read-write); HasReadOnly=true emits the + // explicit ReadOnly value into the template. + HasReadOnly bool + ReadOnly bool +} diff --git a/client-programs/pkg/cluster/kindcluster.go b/client-programs/pkg/cluster/kindcluster.go index c6b6ab4ac..f4d6de1a1 100644 --- a/client-programs/pkg/cluster/kindcluster.go +++ b/client-programs/pkg/cluster/kindcluster.go @@ -17,7 +17,6 @@ import ( "sigs.k8s.io/kind/pkg/cluster" "sigs.k8s.io/kind/pkg/cmd" - "github.com/educates/educates-training-platform/client-programs/pkg/config" "github.com/educates/educates-training-platform/client-programs/pkg/docker" "github.com/educates/educates-training-platform/client-programs/pkg/utils" ) @@ -46,23 +45,25 @@ func NewKindClusterConfig(kubeconfig string) *KindClusterConfig { //go:embed kindclusterconfig.yaml.tpl var clusterConfigTemplateData string +// ClusterExists reports whether the 'educates' kind cluster currently +// exists. err is set only when the underlying list call failed; the +// existence outcome itself is not an error — callers decide whether +// "exists" or "does not exist" is acceptable for the operation they're +// performing (CreateCluster wants !exists; Delete/Start/Stop/Status +// want exists). func (o *KindClusterConfig) ClusterExists() (bool, error) { clusters, err := o.provider.List() - if err != nil { return false, errors.Wrap(err, "unable to get list of clusters") } - - if slices.Contains(clusters, "educates") { - return true, errors.New("cluster for Educates already exists") - } - - return false, nil + return slices.Contains(clusters, "educates"), nil } -func (o *KindClusterConfig) CreateCluster(config *config.InstallationConfig, image string) error { - if exists, err := o.ClusterExists(); !exists && err != nil { +func (o *KindClusterConfig) CreateCluster(input *KindBootstrapInput, image string) error { + if exists, err := o.ClusterExists(); err != nil { return err + } else if exists { + return errors.New("cluster for Educates already exists") } clusterConfigTemplate, err := template.New("kind-cluster-config").Parse(clusterConfigTemplateData) @@ -73,7 +74,7 @@ func (o *KindClusterConfig) CreateCluster(config *config.InstallationConfig, ima var clusterConfigData bytes.Buffer - err = clusterConfigTemplate.Execute(&clusterConfigData, config) + err = clusterConfigTemplate.Execute(&clusterConfigData, input) if err != nil { return errors.Wrap(err, "failed to generate cluster config") diff --git a/client-programs/pkg/cluster/kindclusterconfig.yaml.tpl b/client-programs/pkg/cluster/kindclusterconfig.yaml.tpl index 5499f7640..39896193f 100644 --- a/client-programs/pkg/cluster/kindclusterconfig.yaml.tpl +++ b/client-programs/pkg/cluster/kindclusterconfig.yaml.tpl @@ -1,23 +1,23 @@ kind: Cluster apiVersion: kind.x-k8s.io/v1alpha4 -{{- if or .LocalKindCluster.ApiServer .LocalKindCluster.Networking }} +{{- if or .ApiServer .Networking }} networking: - {{- if .LocalKindCluster.ApiServer.Address }} + {{- if .ApiServer.Address }} # WARNING: It is _strongly_ recommended that you keep this the default # (127.0.0.1) for security reasons. However it is possible to change this. - apiServerAddress: "{{ .LocalKindCluster.ApiServer.Address }}" + apiServerAddress: "{{ .ApiServer.Address }}" {{- end }} - {{- if .LocalKindCluster.ApiServer.Port }} + {{- if .ApiServer.Port }} # By default the API server listens on a random open port. # You may choose a specific port but probably don't need to in most cases. # Using a random port makes it easier to spin up multiple clusters. - apiServerPort: {{ .LocalKindCluster.ApiServer.Port }} + apiServerPort: {{ .ApiServer.Port }} {{- end }} - {{- if .LocalKindCluster.Networking.ServiceSubnet }} - serviceSubnet: "{{ .LocalKindCluster.Networking.ServiceSubnet }}" + {{- if .Networking.ServiceSubnet }} + serviceSubnet: "{{ .Networking.ServiceSubnet }}" {{- end }} - {{- if .LocalKindCluster.Networking.PodSubnet }} - podSubnet: "{{ .LocalKindCluster.Networking.PodSubnet }}" + {{- if .Networking.PodSubnet }} + podSubnet: "{{ .Networking.PodSubnet }}" {{- end }} {{- end }} nodes: @@ -28,40 +28,30 @@ nodes: nodeRegistration: kubeletExtraArgs: node-labels: "ingress-ready=true" - {{- if eq .ClusterSecurity.PolicyEngine "pod-security-policies" }} - - | - kind: ClusterConfiguration - metadata: - name: config - apiServer: - extraArgs: - enable-admission-plugins: PodSecurityPolicy - {{- end }} extraPortMappings: - containerPort: 80 - {{- if .LocalKindCluster.ListenAddress }} - listenAddress: {{ .LocalKindCluster.ListenAddress }} + {{- if .ListenAddress }} + listenAddress: {{ .ListenAddress }} {{- end }} hostPort: 80 protocol: TCP - containerPort: 443 - {{- if .LocalKindCluster.ListenAddress }} - listenAddress: {{ .LocalKindCluster.ListenAddress }} + {{- if .ListenAddress }} + listenAddress: {{ .ListenAddress }} {{- end }} hostPort: 443 protocol: TCP - {{- if .LocalKindCluster.VolumeMounts }} + {{- if .VolumeMounts }} extraMounts: - {{- range .LocalKindCluster.VolumeMounts }} + {{- range .VolumeMounts }} - hostPath: {{ .HostPath }} containerPath: {{ .ContainerPath }} + {{- if .HasReadOnly }} + readOnly: {{ .ReadOnly }} + {{- end }} {{- end }} {{- end }} containerdConfigPatches: - |- [plugins."io.containerd.grpc.v1.cri".registry] config_path = "/etc/containerd/certs.d" -{{- if eq .ClusterSecurity.PolicyEngine "pod-security-standards" }} -featureGates: - PodSecurity: true -{{ end }} diff --git a/client-programs/pkg/cmd/admin_platform_cmd_group.go b/client-programs/pkg/cmd/admin_platform_cmd_group.go index 7bf471f0f..eb14c1b50 100644 --- a/client-programs/pkg/cmd/admin_platform_cmd_group.go +++ b/client-programs/pkg/cmd/admin_platform_cmd_group.go @@ -21,8 +21,7 @@ func (p *ProjectInfo) NewAdminPlatformCmdGroup() *cobra.Command { Commands: []*cobra.Command{ p.NewAdminPlatformDeployCmd(), p.NewAdminPlatformDeleteCmd(), - p.NewAdminPlatformConfigCmd(), - p.NewAdminPlatformValuesCmd(), + p.NewAdminPlatformRenderCmd(), }, }, } diff --git a/client-programs/pkg/cmd/admin_platform_config_cmd.go b/client-programs/pkg/cmd/admin_platform_config_cmd.go deleted file mode 100644 index 5e7d2b490..000000000 --- a/client-programs/pkg/cmd/admin_platform_config_cmd.go +++ /dev/null @@ -1,120 +0,0 @@ -package cmd - -import ( - "fmt" - - "github.com/spf13/cobra" - - "github.com/educates/educates-training-platform/client-programs/pkg/config" - "github.com/educates/educates-training-platform/client-programs/pkg/installer" -) - -var ( - adminPlatformConfigExample = ` - # Show configuration config for local deployment - educates admin platform config --local-config - - # Show configuration config for specific config file - educates admin platform config --config config.yaml - - # Get configuration used to deploy to the current cluster - educates admin platform config --from-cluster - educates admin platform config --from-cluster --kubeconfig /path/to/kubeconfig --context my-cluster - - # Get configuration config with different domain (to make copies of the config) - educates admin platform config --local-config --domain cluster1.dev.educates.io > cluster1-config.yaml - ` -) - -type PlatformConfigOptions struct { - KubeconfigOptions - Domain string - LocalConfig bool - FromCluster bool - Verbose bool -} - -func (o *PlatformConfigOptions) Run() error { - installer := installer.NewInstaller() - - // Validation: Check if domain is set when from-cluster is true - // TODO: Maybe be able to modify the domain for the from-cluster config as well? - if o.FromCluster && o.Domain != "" { - return fmt.Errorf("domain must not be set when from-cluster is true") - } - - if o.FromCluster { - config, err := installer.GetConfigFromCluster(o.Kubeconfig, o.Context) - if err != nil { - return err - } - fmt.Println(config) - } else { - fullConfig, err := config.ConfigForLocalClusters("", o.Domain, o.LocalConfig) - - if err != nil { - return err - } - - config.PrintConfigToStdout(fullConfig) - } - - return nil -} - -func (p *ProjectInfo) NewAdminPlatformConfigCmd() *cobra.Command { - var o PlatformConfigOptions - - var c = &cobra.Command{ - Args: cobra.NoArgs, - Use: "config", - Short: "Show config used when deploying the platform", - RunE: func(cmd *cobra.Command, _ []string) error { - return o.Run() - }, - Example: adminPlatformConfigExample, - } - - c.Flags().StringVar( - &o.Kubeconfig, - "kubeconfig", - "", - "kubeconfig file to use instead of $KUBECONFIG or $HOME/.kube/config", - ) - c.Flags().StringVar( - &o.Context, - "context", - "", - "Context to use from Kubeconfig", - ) - c.Flags().StringVar( - &o.Domain, - "domain", - "", - "wildcard ingress subdomain name for Educates", - ) - c.Flags().BoolVar( - &o.Verbose, - "verbose", - false, - "print verbose output", - ) - c.Flags().BoolVar( - &o.LocalConfig, - "local-config", - false, - "Use local configuration", - ) - // TODO: From cluster - c.Flags().BoolVar( - &o.FromCluster, - "from-cluster", - false, - "Show the configuration (from the cluster) used when the plaform was deployed", - ) - - c.MarkFlagsMutuallyExclusive("local-config", "from-cluster") - c.MarkFlagsOneRequired("local-config", "from-cluster") - - return c -} diff --git a/client-programs/pkg/cmd/admin_platform_delete_cmd.go b/client-programs/pkg/cmd/admin_platform_delete_cmd.go index 6dfdb03a3..89eaae8ad 100644 --- a/client-programs/pkg/cmd/admin_platform_delete_cmd.go +++ b/client-programs/pkg/cmd/admin_platform_delete_cmd.go @@ -1,69 +1,173 @@ package cmd import ( + "bufio" + "context" "fmt" + "io" + "os" + "strings" + "time" - "github.com/pkg/errors" "github.com/spf13/cobra" + "k8s.io/cli-runtime/pkg/genericclioptions" - "github.com/educates/educates-training-platform/client-programs/pkg/cluster" - "github.com/educates/educates-training-platform/client-programs/pkg/config" - "github.com/educates/educates-training-platform/client-programs/pkg/installer" + "github.com/educates/educates-training-platform/client-programs/pkg/deployer" + "github.com/educates/educates-training-platform/client-programs/pkg/deployer/progress" ) type PlatformDeleteOptions struct { - KubeconfigOptions - Verbose bool + Kubeconfig string + Context string + Timeout time.Duration + Verbose bool + Yes bool + Purge bool } -func (o *PlatformDeleteOptions) Run() error { - fullConfig := config.NewDefaultInstallationConfig() +func (p *ProjectInfo) NewAdminPlatformDeleteCmd() *cobra.Command { + var o PlatformDeleteOptions + + c := &cobra.Command{ + Args: cobra.NoArgs, + Use: "delete", + Short: "Uninstall Educates: drain platform CRs + helm uninstall", + Long: `Reverse of 'admin platform deploy': - installer := installer.NewInstaller() + 1. delete SessionManager → wait gone + 2. delete LookupService → wait gone + 3. delete SecretsManager → wait gone + 4. delete EducatesClusterConfig → wait gone + (the ECC finalizer drains kyverno, external-dns, contour, + cert-manager and the CustomCA Secret copy in reverse install order) + 5. helm uninstall the operator chart - clusterConfig := cluster.NewClusterConfig(o.Kubeconfig, o.Context) +By default this is idempotent and leaves cluster-shared state alone: +missing CRs are skipped silently; the four CRDs, the operator +namespace, the educates-secrets namespace, and any locally-cached +secrets stay in place so the next deploy reuses them. - err := installer.Delete(fullConfig, clusterConfig, o.Verbose) +--purge extends the pipeline AFTER helm uninstall to also remove the +CRDs and the operator + educates-secrets namespaces. Local +/config.yaml + cached CA Secret YAMLs survive — they're +your authoring inputs, kept across cluster reinstalls. - if err != nil { - return errors.Wrap(err, "educates could not be deleted") +A confirmation prompt fires when stdout is a TTY; pass --yes to skip +it (required when running under CI / non-interactive shells without +piping). + +Unlike deploy, this command takes no --config / --local-config — the +resources are always the four CRs at metadata.name=cluster plus the +educates-installer release.`, + RunE: func(cmd *cobra.Command, _ []string) error { + return p.runDelete(cmd.Context(), cmd.OutOrStdout(), &o) + }, } - fmt.Println("\nEducates has been deleted succesfully") + c.Flags().StringVar(&o.Kubeconfig, "kubeconfig", "", "kubeconfig file (defaults to $KUBECONFIG / ~/.kube/config)") + c.Flags().StringVar(&o.Context, "context", "", "context name to use within the kubeconfig") + c.Flags().DurationVar(&o.Timeout, "timeout", deployer.DefaultTimeout, "per-CR finalizer-drain wait timeout") + c.Flags().BoolVar(&o.Verbose, "verbose", false, "show helm SDK debug output on stderr") + c.Flags().BoolVarP(&o.Yes, "yes", "y", false, "skip the confirmation prompt") + c.Flags().BoolVar(&o.Purge, "purge", false, "also remove the 4 CRDs + operator namespace + educates-secrets namespace (cluster-shared state)") - return nil + return c } -func (p *ProjectInfo) NewAdminPlatformDeleteCmd() *cobra.Command { - var o PlatformDeleteOptions +func (p *ProjectInfo) runDelete(ctx context.Context, w io.Writer, o *PlatformDeleteOptions) error { + if err := confirmDelete(w, o); err != nil { + return err + } - var c = &cobra.Command{ - Args: cobra.NoArgs, - Use: "delete", - Short: "Delete Educates and related cluster services from your cluster", - RunE: func(cmd *cobra.Command, _ []string) error { - return o.Run() - }, + cf := genericclioptions.NewConfigFlags(true) + if o.Kubeconfig != "" { + cf.KubeConfig = &o.Kubeconfig + } + if o.Context != "" { + cf.Context = &o.Context } + ns := deployer.OperatorNamespace + cf.Namespace = &ns - c.Flags().StringVar( - &o.Kubeconfig, - "kubeconfig", - "", - "kubeconfig file to use instead of $KUBECONFIG or $HOME/.kube/config", - ) - c.Flags().StringVar( - &o.Context, - "context", - "", - "Context to use from Kubeconfig", - ) - c.Flags().BoolVar( - &o.Verbose, - "verbose", - false, - "print verbose output", - ) + helmLog := io.Discard + if o.Verbose { + helmLog = w + } - return c + return deployer.Delete(ctx, deployer.DeleteOptions{ + Getter: cf, + Out: w, + HelmLog: helmLog, + Timeout: o.Timeout, + Progress: progress.New(w, 0, isStdoutTTY(w)), + Purge: o.Purge, + }) +} + +// confirmDelete renders an itemised list of what's about to be deleted +// and gates on the user typing 'yes'. Skipped when --yes is set OR +// when stdin isn't a TTY (CI runs accidentally hanging on a prompt is +// worse than the destructive-action risk; users in CI should pass --yes +// explicitly to be unambiguous). +func confirmDelete(w io.Writer, o *PlatformDeleteOptions) error { + if o.Yes { + return nil + } + if !isStdinTTY() { + return fmt.Errorf("non-interactive shell detected; pass --yes to skip the confirmation prompt") + } + fmt.Fprintln(w, "This command will delete the following from the cluster:") + for _, line := range deleteInventory(o.Purge) { + fmt.Fprintln(w, " - "+line) + } + if !o.Purge { + fmt.Fprintln(w, " (CRDs, operator namespace, and educates-secrets namespace stay — pass --purge to remove)") + } + fmt.Fprintln(w, " (Local /config.yaml + cached CA Secret YAMLs are never touched)") + fmt.Fprint(w, "Type 'yes' to confirm: ") + + reader := bufio.NewReader(os.Stdin) + answer, err := reader.ReadString('\n') + if err != nil { + return fmt.Errorf("read confirmation: %w", err) + } + if strings.TrimSpace(answer) != "yes" { + return fmt.Errorf("aborted") + } + return nil +} + +// deleteInventory renders the human-readable list of cluster +// resources the run will touch. The order mirrors the actual delete +// sequence so the prompt's mental model matches what the user sees in +// the progress output afterward. +func deleteInventory(purge bool) []string { + out := []string{ + "SessionManager/cluster (platform.educates.dev)", + "LookupService/cluster (platform.educates.dev)", + "SecretsManager/cluster (platform.educates.dev)", + "EducatesClusterConfig/cluster (config.educates.dev)", + "helm release: educates-installer (in namespace " + deployer.OperatorNamespace + ")", + } + if !purge { + return out + } + plan := deployer.PurgePlan() + for _, name := range plan.CRDs { + out = append(out, "CRD: "+name) + } + for _, name := range plan.Namespaces { + out = append(out, "namespace: "+name+" (and everything inside it)") + } + return out +} + +// isStdinTTY mirrors isStdoutTTY but for the input stream — used by +// confirmDelete to decide whether to prompt or refuse-and-instruct. +func isStdinTTY() bool { + info, err := os.Stdin.Stat() + if err != nil { + return false + } + return info.Mode()&os.ModeCharDevice != 0 } diff --git a/client-programs/pkg/cmd/admin_platform_delete_test.go b/client-programs/pkg/cmd/admin_platform_delete_test.go new file mode 100644 index 000000000..c9ce15e4a --- /dev/null +++ b/client-programs/pkg/cmd/admin_platform_delete_test.go @@ -0,0 +1,68 @@ +package cmd + +import ( + "bytes" + "strings" + "testing" +) + +func TestDeleteInventory_NoPurge_OnlyCRsAndRelease(t *testing.T) { + got := deleteInventory(false) + wantContains := []string{ + "SessionManager/cluster", + "LookupService/cluster", + "SecretsManager/cluster", + "EducatesClusterConfig/cluster", + "helm release: educates-installer", + } + for _, w := range wantContains { + var found bool + for _, line := range got { + if strings.Contains(line, w) { + found = true + break + } + } + if !found { + t.Errorf("inventory missing %q in %v", w, got) + } + } + for _, line := range got { + if strings.Contains(line, "CRD:") || strings.Contains(line, "namespace:") { + t.Errorf("non-purge inventory leaked purge-only entry: %q", line) + } + } +} + +func TestDeleteInventory_Purge_AddsCRDsAndNamespaces(t *testing.T) { + got := deleteInventory(true) + for _, want := range []string{ + "CRD: educatesclusterconfigs.config.educates.dev", + "CRD: secretsmanagers.platform.educates.dev", + "CRD: lookupservices.platform.educates.dev", + "CRD: sessionmanagers.platform.educates.dev", + "namespace: educates-installer", + "namespace: educates-secrets", + } { + var found bool + for _, line := range got { + if strings.Contains(line, want) { + found = true + break + } + } + if !found { + t.Errorf("purge inventory missing %q in %v", want, got) + } + } +} + +func TestConfirmDelete_YesFlag_NoPrompt(t *testing.T) { + var buf bytes.Buffer + if err := confirmDelete(&buf, &PlatformDeleteOptions{Yes: true}); err != nil { + t.Fatalf("confirmDelete with --yes: %v", err) + } + if buf.Len() != 0 { + t.Errorf("--yes should not print anything, got: %s", buf.String()) + } +} diff --git a/client-programs/pkg/cmd/admin_platform_deploy_cmd.go b/client-programs/pkg/cmd/admin_platform_deploy_cmd.go index 51d4bf15f..c26ee4ba1 100644 --- a/client-programs/pkg/cmd/admin_platform_deploy_cmd.go +++ b/client-programs/pkg/cmd/admin_platform_deploy_cmd.go @@ -1,203 +1,124 @@ package cmd import ( + "context" "fmt" + "io" + "path/filepath" + "time" - "github.com/pkg/errors" "github.com/spf13/cobra" - "github.com/educates/educates-training-platform/client-programs/pkg/cluster" "github.com/educates/educates-training-platform/client-programs/pkg/config" - "github.com/educates/educates-training-platform/client-programs/pkg/installer" - "github.com/educates/educates-training-platform/client-programs/pkg/secrets" -) - -var ( - adminPlatformDeployExample = ` - # Deploy educates platform - educates admin platform deploy --config config.yaml - - # Get deployment descriptors for a specific provider with provided config - educates admin platform deploy --config config.yaml --dry-run - - # Get deployment descriptors for local cluster default installation - educates admin platform deploy --local-config --dry-run - - # Deploy educates platform with verbose output - educates admin platform deploy --config config.yaml --verbose - - # Deploy educates platform with an alternate domain - educates admin platform deploy --config config.yaml --domain test.educates.io - educates admin platform deploy --local-config --domain test.educates.io - - # Deploy educates platform without resolving images via kbld (using latest images) - educates admin platform deploy --config config.yaml --skip-image-resolution - - # Deploy educates platform showing the changes to be applied to the cluster - educates admin platform deploy --config config.yaml --show-changes - - # Install educates with bundle from different repository - educates admin platform deploy --config config.yaml --package-repository ghcr.io/jorgemoralespou --version installer-clean - - # Install educates when locally built (version latest does the same and skips image resolution) - educates admin platform deploy --config config.yaml --package-repository localhost:5001 --version 0.0.1 - educates admin platform deploy --config config.yaml --version latest - - # Install educates on a specific cluster - educates admin platform deploy --config config.yaml --kubeconfig /path/to/kubeconfig --context my-cluster - educates admin platform deploy --config config.yaml --kubeconfig /path/to/kubeconfig - educates admin platform deploy --config config.yaml --context my-cluster - ` + "github.com/educates/educates-training-platform/client-programs/pkg/config/hostinfo" + "github.com/educates/educates-training-platform/client-programs/pkg/config/v1alpha1" + "github.com/educates/educates-training-platform/client-programs/pkg/deployer" + "github.com/educates/educates-training-platform/client-programs/pkg/utils" ) +// PlatformDeployOptions mirrors PlatformRenderOptions plus the kubectl +// connection flags consumed by the install path. type PlatformDeployOptions struct { - KubeconfigOptions - Config string - Domain string - DryRun bool - Version string - PackageRepository string - Verbose bool - LocalConfig bool - skipImageResolution bool - showChanges bool + Config string + LocalConfig bool + Kubeconfig string + Context string + Timeout time.Duration + Verbose bool } -func (o *PlatformDeployOptions) Run() error { - installer := installer.NewInstaller() - - fullConfig, err := config.ConfigForLocalClusters(o.Config, o.Domain, o.LocalConfig) +func (p *ProjectInfo) NewAdminPlatformDeployCmd() *cobra.Command { + var o PlatformDeployOptions - if err != nil { - return err + c := &cobra.Command{ + Args: cobra.NoArgs, + Use: "deploy", + Short: "Install Educates: helm install operator + apply 4 platform CRs", + Long: `Drive the install end-to-end. Same translator as 'admin platform render', +then push to the cluster: + + 1. helm upgrade --install educates-installer (embedded chart) + 2. apply EducatesClusterConfig → wait Ready=True + 3. verify educates-custom-ca Secret prerequisite (skipped when + --local-config syncs the cached CA in step 0) + 4. apply SecretsManager → wait Ready=True + 5. apply LookupService (if configured) → wait Ready=True + (interleaved with SessionManager — both apply, then both wait) + 6. apply SessionManager → wait Ready=True`, + RunE: func(cmd *cobra.Command, _ []string) error { + return p.runDeploy(cmd.Context(), cmd.OutOrStdout(), &o) + }, } - if o.DryRun { - if err = installer.DryRun(o.Version, o.PackageRepository, fullConfig, o.Verbose, false, o.skipImageResolution); err != nil { - return errors.Wrap(err, "educates could not be installed") - } - return nil - } + c.Flags().StringVarP(&o.Config, "config", "c", "", "path to a CLI config file (any kind)") + c.Flags().BoolVar(&o.LocalConfig, "local-config", false, + "use /config.yaml; applies host-IP nip.io fallback for ingress.domain") + c.Flags().StringVar(&o.Kubeconfig, "kubeconfig", "", "kubeconfig file (defaults to $KUBECONFIG / ~/.kube/config)") + c.Flags().StringVar(&o.Context, "context", "", "context name to use within the kubeconfig") + c.Flags().DurationVar(&o.Timeout, "timeout", deployer.DefaultTimeout, "per-CR Ready=True wait timeout") + c.Flags().BoolVar(&o.Verbose, "verbose", false, "show helm SDK debug output on stderr") + c.MarkFlagsMutuallyExclusive("config", "local-config") + c.MarkFlagsOneRequired("config", "local-config") - clusterConfig, err := cluster.NewClusterConfigIfAvailable(o.Kubeconfig, o.Context) - if err != nil { - return err - } + return c +} - client, err := clusterConfig.GetClient() +func (p *ProjectInfo) runDeploy(ctx context.Context, w io.Writer, o *PlatformDeployOptions) error { + // Reuse the same load → default → translate path as render so the + // two commands stay in lock-step. (Step-9 cleanup factors this into + // a shared helper.) + path, err := resolveDeployConfigPath(o) if err != nil { return err } - - // This creates the educates-secrets namespace if it doesn't exist and creates the - // wildcard and CA secrets in there - if err = secrets.SyncLocalCachedSecretsToCluster(client); err != nil { - return err + if o.LocalConfig { + if err := config.EnsureLocalConfigFile(utils.GetEducatesHomeDir()); err != nil { + return err + } } - - err = installer.Run(o.Version, o.PackageRepository, fullConfig, clusterConfig, o.Verbose, false, o.skipImageResolution, o.showChanges) + cfg, err := config.Load(path) if err != nil { - return errors.Wrap(err, "educates could not be installed") + return err } - // This is for hugo livereload (educates serve-workshop). Reconfigures the loopback service - // We do create this loopback service for all providers except vcluster, as vcluster will map - // it's own service to the host's loopback service to use the host's single loopback service - if fullConfig.ClusterInfrastructure.Provider != "vcluster" { - if err = cluster.CreateLoopbackService(client, fullConfig.ClusterIngress.Domain); err != nil { - return err + var caSecretName, caSecretNamespace string + syncLocalSecrets := false + switch c := cfg.(type) { + case *v1alpha1.EducatesLocalConfig: + c.ApplyCLIDefaults(p.Version, p.ImageRepository) + if o.LocalConfig && c.Ingress.Domain == "" { + ip, err := hostinfo.DetectHostIP() + if err != nil { + return fmt.Errorf("auto-detect host IP: %w", err) + } + c.Ingress.Domain = hostinfo.NipDomain(ip) + } else if c.Ingress.Domain == "" { + return fmt.Errorf("ingress.domain is required when using --config (set it in %s)", path) } + var lookupErr error + caSecretName, caSecretNamespace, lookupErr = caRefForLocal(c) + if lookupErr != nil { + return lookupErr + } + syncLocalSecrets = true + case *v1alpha1.EducatesConfig: + // Pure passthrough. } - fmt.Println("\nEducates has been installed succesfully") - - return nil + return translateAndDeploy(ctx, w, cfg, caSecretName, caSecretNamespace, syncLocalSecrets, deployPipelineFlags{ + Kubeconfig: o.Kubeconfig, + Context: o.Context, + Timeout: o.Timeout, + Verbose: o.Verbose, + }) } -func (p *ProjectInfo) NewAdminPlatformDeployCmd() *cobra.Command { - var o PlatformDeployOptions - - var c = &cobra.Command{ - Args: cobra.NoArgs, - Use: "deploy", - Short: "Install Educates and related cluster services onto your cluster in an imperative manner", - RunE: func(cmd *cobra.Command, _ []string) error { - if o.LocalConfig { - o.Config = "" - } - return o.Run() - }, - Example: adminPlatformDeployExample, +func resolveDeployConfigPath(o *PlatformDeployOptions) (string, error) { + if o.LocalConfig { + return filepath.Join(utils.GetEducatesHomeDir(), "config.yaml"), nil } - - c.Flags().StringVar( - &o.Config, - "config", - "", - "path to the installation config file for Educates", - ) - c.Flags().StringVar( - &o.Kubeconfig, - "kubeconfig", - "", - "kubeconfig file to use instead of $KUBECONFIG or $HOME/.kube/config", - ) - c.Flags().StringVar( - &o.Context, - "context", - "", - "Context to use from Kubeconfig", - ) - c.Flags().StringVar( - &o.Domain, - "domain", - "", - "wildcard ingress subdomain name for Educates", - ) - c.Flags().BoolVar( - &o.DryRun, - "dry-run", - false, - "prints to stdout the yaml that would be deployed to the cluster", - ) - c.Flags().BoolVar( - &o.Verbose, - "verbose", - false, - "print verbose output", - ) - c.Flags().StringVar( - &o.PackageRepository, - "package-repository", - p.ImageRepository, - "image repository hosting package bundles", - ) - c.Flags().StringVar( - &o.Version, - "version", - p.Version, - "version to be installed", - ) - c.Flags().BoolVar( - &o.LocalConfig, - "local-config", - false, - "Use local configuration. When used, --config and --domain flags are ignored", - ) - c.Flags().BoolVar( - &o.skipImageResolution, - "skip-image-resolution", - false, - "skips resolution of referenced images so that all will be fetched from their original location", - ) - c.Flags().BoolVar( - &o.showChanges, - "show-changes", - false, - "shows the diffs to be applied to the cluster when running the install", - ) - c.MarkFlagsMutuallyExclusive("config", "local-config") - c.MarkFlagsOneRequired("config", "local-config") - - return c + if o.Config == "" { + return "", fmt.Errorf("internal: neither --config nor --local-config set") + } + return o.Config, nil } diff --git a/client-programs/pkg/cmd/admin_platform_render_cmd.go b/client-programs/pkg/cmd/admin_platform_render_cmd.go new file mode 100644 index 000000000..43d512fdf --- /dev/null +++ b/client-programs/pkg/cmd/admin_platform_render_cmd.go @@ -0,0 +1,234 @@ +package cmd + +import ( + "fmt" + "io" + "path/filepath" + + "github.com/spf13/cobra" + + "github.com/educates/educates-training-platform/client-programs/pkg/config" + "github.com/educates/educates-training-platform/client-programs/pkg/config/hostinfo" + "github.com/educates/educates-training-platform/client-programs/pkg/config/translator" + "github.com/educates/educates-training-platform/client-programs/pkg/config/v1alpha1" + "github.com/educates/educates-training-platform/client-programs/pkg/secrets" + "github.com/educates/educates-training-platform/client-programs/pkg/utils" +) + +const adminPlatformRenderExample = ` + # Render the install for a checked-in config file (GitOps mode). + # - operator.image is defaulted from this CLI's compiled-in version. + # - ingress.domain MUST be set in the config; render errors if empty. + educates admin platform render --config env.yaml > install.yaml + + # Render the install for laptop convenience (uses ~/.educates/config.yaml + # or $EDUCATES_CLI_DATA_HOME/config.yaml). When ingress.domain is empty, + # falls back to .nip.io with a comment header noting the + # derivation. + educates admin platform render --local-config +` + +type PlatformRenderOptions struct { + Config string + LocalConfig bool +} + +func (p *ProjectInfo) NewAdminPlatformRenderCmd() *cobra.Command { + var o PlatformRenderOptions + + c := &cobra.Command{ + Args: cobra.NoArgs, + Use: "render", + Short: "Render the install plan (operator chart values + 4 platform CRs) to stdout", + Long: `Render the install plan that "educates admin platform deploy" would apply, +without touching the cluster. Useful for inspection, GitOps, and diffing. + +Output is a single YAML stream with two sections, in deploy order: + - operator chart values (consumed by 'helm install -f - educates-installer') + - the four platform CRs (consumed by 'kubectl apply -f -') + +Defaulting is flag-driven: + --config Explicit / GitOps mode. operator.image defaults from + this CLI binary; ingress.domain MUST be set in the + config. Render is deterministic for a given (input, + CLI version) pair. + --local-config Laptop convenience mode. Same defaults, plus a + .nip.io fallback for ingress.domain when + empty. Output is host-specific.`, + Example: adminPlatformRenderExample, + RunE: func(cmd *cobra.Command, _ []string) error { + return p.runRender(cmd.OutOrStdout(), &o) + }, + } + + c.Flags().StringVarP(&o.Config, "config", "c", "", "path to a CLI config file (any kind)") + c.Flags().BoolVar(&o.LocalConfig, "local-config", false, + "use /config.yaml; applies host-IP nip.io fallback for ingress.domain") + c.MarkFlagsMutuallyExclusive("config", "local-config") + c.MarkFlagsOneRequired("config", "local-config") + + return c +} + +func (p *ProjectInfo) runRender(w io.Writer, o *PlatformRenderOptions) error { + path, err := resolveConfigPath(o) + if err != nil { + return err + } + // EnsureLocalConfigFile composes the v3→v4 migration shim + // (MaybeMigrateV3) with the user-actionable missing-file diagnostic + // (MissingLocalConfigError). Returns nil when config.yaml is + // either already present or has just been written by migration. + if o.LocalConfig { + if err := config.EnsureLocalConfigFile(utils.GetEducatesHomeDir()); err != nil { + return err + } + } + cfg, err := config.Load(path) + if err != nil { + return err + } + + header := "" + opts := translator.Options{} + switch c := cfg.(type) { + case *v1alpha1.EducatesLocalConfig: + c.ApplyCLIDefaults(p.Version, p.ImageRepository) + var hostNote string + if o.LocalConfig { + hostNote, err = maybeApplyHostDomain(c) + if err != nil { + return err + } + } else if c.Ingress.Domain == "" { + return fmt.Errorf(`ingress.domain is required when using --config. +Set it explicitly in %s, or use --local-config to derive a .nip.io +fallback (output becomes host-specific and unsuitable for GitOps).`, path) + } + header = hostNote + + // Local-mode invariant: BundledCertManager+CustomCA. Look up the + // CA Secret in the local cache by the configured domain. Failing + // here (before any rendering) gives the user a remediation path + // before they pipe output to GitOps. + caName, lookupErr := lookupLocalCAByDomain(c.Ingress.Domain) + if lookupErr != nil { + return lookupErr + } + opts.CASecretName = caName + opts.CASecretNamespace = LocalCASecretNamespace + case *v1alpha1.EducatesConfig: + // Escape-hatch: pure passthrough. No CLI-side defaults. User owns + // the full surface; missing required fields are caught by the + // CRD-derived schema at load time or by the apiserver at apply. + } + + out, err := translator.Translate(cfg, opts) + if err != nil { + return err + } + + return writeRender(w, out, header) +} + +// LocalCASecretNamespace is where laptop-mode CA Secrets live, matching +// the v3 convention. The deploy command pushes the local secrets cache +// into this namespace before applying the CRs. +const LocalCASecretNamespace = "educates-secrets" + +// lookupLocalCAByDomain finds the cached CA Secret name whose +// 'training.educates.dev/domain' annotation matches the configured +// ingress.domain. Errors with a copy-paste workaround when nothing +// matches. +func lookupLocalCAByDomain(domain string) (string, error) { + if domain == "" { + return "", fmt.Errorf("ingress.domain is empty; cannot look up cached CA") + } + name := secrets.LocalCachedSecretForCertificateAuthority(domain) + if name == "" { + return "", fmt.Errorf(`no cached CA Secret found for domain %q. + +The Local-mode install configures cert-manager in CustomCA mode and +needs a CA Secret whose 'training.educates.dev/domain' annotation +matches this domain. Add one with: + + educates local secrets add ca \ + --domain %s \ + --cert ca.crt --key ca.key + +For development on a laptop, generate a self-signed CA first: + + openssl req -x509 -newkey rsa:2048 -nodes -days 365 \ + -subj '/CN=educates-dev-ca' \ + -keyout ca.key -out ca.crt + +The cached Secret is pushed into the %q namespace at deploy time.`, + domain, domain, LocalCASecretNamespace) + } + return name, nil +} + +// resolveConfigPath picks the config file based on which flag was set. +// --local-config resolves to /config.yaml, where +// is $EDUCATES_CLI_DATA_HOME or $XDG_DATA_HOME/educates. +func resolveConfigPath(o *PlatformRenderOptions) (string, error) { + if o.LocalConfig { + return filepath.Join(utils.GetEducatesHomeDir(), "config.yaml"), nil + } + if o.Config == "" { + return "", fmt.Errorf("internal: neither --config nor --local-config set (should have been caught by cobra)") + } + return o.Config, nil +} + +// maybeApplyHostDomain applies .nip.io to ingress.domain when +// empty. Returns the header comment block to emit at the top of the +// rendered output (empty when no defaulting was needed). +func maybeApplyHostDomain(c *v1alpha1.EducatesLocalConfig) (string, error) { + if c.Ingress.Domain != "" { + return "", nil + } + ip, err := hostinfo.DetectHostIP() + if err != nil { + return "", fmt.Errorf("auto-detect host IP for ingress.domain default: %w", err) + } + c.Ingress.Domain = hostinfo.NipDomain(ip) + return fmt.Sprintf(`# NOTE: ingress.domain was auto-derived from host IP %s as a last-resort +# nip.io fallback. For configuration that is portable across networks, +# consider configuring the resolver block (resolver.targetAddress + +# resolver.extraDomains) and setting ingress.domain to a fixed name like +# 'workshop.test'. +`, ip), nil +} + +// writeRender emits the rendered install plan in deploy order: +// - optional host-defaulting header +// - "# === operator chart values ===" + values YAML +// - "# === platform CRs ===" + multi-doc CR YAML +func writeRender(w io.Writer, out *translator.Output, hostHeader string) error { + values, err := translator.RenderOperatorValues(out) + if err != nil { + return fmt.Errorf("render operator values: %w", err) + } + crs, err := translator.RenderCRs(out) + if err != nil { + return fmt.Errorf("render CRs: %w", err) + } + + if hostHeader != "" { + if _, err := fmt.Fprint(w, hostHeader); err != nil { + return err + } + } + if _, err := fmt.Fprintln(w, "# === operator chart values (helm install -f - educates-installer ...) ==="); err != nil { + return err + } + if _, err := w.Write(values); err != nil { + return err + } + if _, err := fmt.Fprintln(w, "# === platform CRs (kubectl apply -f - ...) ==="); err != nil { + return err + } + _, err = w.Write(crs) + return err +} diff --git a/client-programs/pkg/cmd/admin_platform_render_cmd_test.go b/client-programs/pkg/cmd/admin_platform_render_cmd_test.go new file mode 100644 index 000000000..7972875a2 --- /dev/null +++ b/client-programs/pkg/cmd/admin_platform_render_cmd_test.go @@ -0,0 +1,220 @@ +package cmd + +import ( + "bytes" + "os" + "path/filepath" + "strings" + "testing" + + "github.com/educates/educates-training-platform/client-programs/pkg/config/hostinfo" +) + +const ( + emptyLocal = `apiVersion: cli.educates.dev/v1alpha1 +kind: EducatesLocalConfig +` + localWithDomain = `apiVersion: cli.educates.dev/v1alpha1 +kind: EducatesLocalConfig +ingress: + domain: workshop.test +operator: + image: + repository: ghcr.io/educates/educates-operator + tag: 4.0.0 +` + escapeMinimal = `apiVersion: cli.educates.dev/v1alpha1 +kind: EducatesConfig +` +) + +func writeFixture(t *testing.T, content string) string { + t.Helper() + dir := t.TempDir() + path := filepath.Join(dir, "cfg.yaml") + if err := os.WriteFile(path, []byte(content), 0o644); err != nil { + t.Fatal(err) + } + return path +} + +// stageCachedCA drops a synthetic CA Secret YAML into /secrets/ +// with the 'training.educates.dev/domain' annotation set to `domain`, +// matching the v4 lookup criteria (kubernetes.io/tls type with both +// tls.crt and tls.key data). The byte contents are placeholders — the +// test only exercises the lookup-by-domain path, not PEM validity. +func stageCachedCA(t *testing.T, dataHome, domain string) (caName string) { + t.Helper() + caName = "test-ca" + secretsDir := filepath.Join(dataHome, "secrets") + if err := os.MkdirAll(secretsDir, 0o755); err != nil { + t.Fatal(err) + } + body := "apiVersion: v1\nkind: Secret\nmetadata:\n name: " + caName + + "\n annotations:\n training.educates.dev/domain: " + domain + + "\ntype: kubernetes.io/tls\ndata:\n tls.crt: dGVzdC1jcnQ=\n tls.key: dGVzdC1rZXk=\n" + if err := os.WriteFile(filepath.Join(secretsDir, caName+".yaml"), []byte(body), 0o644); err != nil { + t.Fatal(err) + } + return +} + +// withCachedCA is a convenience wrapper: creates a fresh temp data home, +// stages a CA for `domain`, and sets $EDUCATES_CLI_DATA_HOME. Use it +// when the test doesn't already manage its own data home. +func withCachedCA(t *testing.T, domain string) (dataHome, caName string) { + t.Helper() + dataHome = t.TempDir() + caName = stageCachedCA(t, dataHome, domain) + t.Setenv("EDUCATES_CLI_DATA_HOME", dataHome) + return +} + +func TestRender_Config_MissingDomain_Errors(t *testing.T) { + p := ProjectInfo{Version: "test", ImageRepository: "ghcr.io/educates"} + o := &PlatformRenderOptions{Config: writeFixture(t, emptyLocal)} + + var buf bytes.Buffer + err := p.runRender(&buf, o) + if err == nil { + t.Fatal("expected error for missing ingress.domain in --config mode") + } + if !strings.Contains(err.Error(), "ingress.domain is required") { + t.Errorf("error %q does not mention required field", err) + } + if buf.Len() != 0 { + t.Errorf("expected no output when erroring, got %d bytes", buf.Len()) + } +} + +func TestRender_Config_WithDomain_NoHostHeader(t *testing.T) { + withCachedCA(t, "workshop.test") + p := ProjectInfo{Version: "test", ImageRepository: "ghcr.io/educates"} + o := &PlatformRenderOptions{Config: writeFixture(t, localWithDomain)} + + var buf bytes.Buffer + if err := p.runRender(&buf, o); err != nil { + t.Fatalf("runRender: %v", err) + } + s := buf.String() + + // No host-derivation note (user-provided domain). + if strings.Contains(s, "auto-derived from host IP") { + t.Errorf("--config mode should not emit host-defaulting note:\n%s", s) + } + // Both sections present. + for _, want := range []string{ + "# === operator chart values", + "# === platform CRs", + "domain: workshop.test", + "tag: 4.0.0", + "repository: ghcr.io/educates/educates-operator", + "kind: EducatesClusterConfig", + "kind: SecretsManager", + "kind: SessionManager", + } { + if !strings.Contains(s, want) { + t.Errorf("output missing %q", want) + } + } +} + +func TestRender_Config_CLIDefaults_AppliedWhenImageEmpty(t *testing.T) { + // Tag and repository come from ProjectInfo when config leaves them empty. + withCachedCA(t, "workshop.test") + cfgYAML := `apiVersion: cli.educates.dev/v1alpha1 +kind: EducatesLocalConfig +ingress: + domain: workshop.test +` + p := ProjectInfo{Version: "v9.9.9-test", ImageRepository: "ghcr.io/custom"} + o := &PlatformRenderOptions{Config: writeFixture(t, cfgYAML)} + + var buf bytes.Buffer + if err := p.runRender(&buf, o); err != nil { + t.Fatalf("runRender: %v", err) + } + s := buf.String() + for _, want := range []string{ + "tag: v9.9.9-test", + "repository: ghcr.io/custom/educates-operator", + } { + if !strings.Contains(s, want) { + t.Errorf("CLI defaults: output missing %q:\n%s", want, s) + } + } +} + +func TestRender_LocalConfig_AutoDomain_EmitsHeader(t *testing.T) { + // Point --local-config at a temp data home so the test doesn't touch + // the user's actual data home. + dataHome := t.TempDir() + if err := os.WriteFile(filepath.Join(dataHome, "config.yaml"), []byte(emptyLocal), 0o644); err != nil { + t.Fatal(err) + } + // Pre-stage a cached CA matching the host-IP-derived domain that + // maybeApplyHostDomain will compute. We mirror the same nip.io + // derivation here to know which annotation to write. + ip, err := hostinfo.DetectHostIP() + if err != nil { + t.Skipf("no host IP detectable: %v", err) + } + stageCachedCA(t, dataHome, hostinfo.NipDomain(ip)) + t.Setenv("EDUCATES_CLI_DATA_HOME", dataHome) + + p := ProjectInfo{Version: "test", ImageRepository: "ghcr.io/educates"} + o := &PlatformRenderOptions{LocalConfig: true} + + var buf bytes.Buffer + if err := p.runRender(&buf, o); err != nil { + t.Fatalf("runRender: %v", err) + } + s := buf.String() + if !strings.Contains(s, "auto-derived from host IP") { + t.Errorf("--local-config with empty domain should emit host-defaulting note:\n%s", s) + } + if !strings.Contains(s, ".nip.io") { + t.Errorf("--local-config with empty domain should produce a nip.io domain:\n%s", s) + } +} + +func TestRender_LocalConfig_UserDomain_NoHeader(t *testing.T) { + dataHome := t.TempDir() + if err := os.WriteFile(filepath.Join(dataHome, "config.yaml"), []byte(localWithDomain), 0o644); err != nil { + t.Fatal(err) + } + stageCachedCA(t, dataHome, "workshop.test") + t.Setenv("EDUCATES_CLI_DATA_HOME", dataHome) + + p := ProjectInfo{Version: "test", ImageRepository: "ghcr.io/educates"} + o := &PlatformRenderOptions{LocalConfig: true} + + var buf bytes.Buffer + if err := p.runRender(&buf, o); err != nil { + t.Fatalf("runRender: %v", err) + } + if strings.Contains(buf.String(), "auto-derived from host IP") { + t.Errorf("--local-config with explicit domain should not emit host-defaulting note:\n%s", buf.String()) + } +} + +func TestRender_EscapeKind_PureUserOutput(t *testing.T) { + p := ProjectInfo{Version: "test", ImageRepository: "ghcr.io/educates"} + o := &PlatformRenderOptions{Config: writeFixture(t, escapeMinimal)} + + var buf bytes.Buffer + if err := p.runRender(&buf, o); err != nil { + t.Fatalf("runRender: %v", err) + } + s := buf.String() + + // Escape kind: no CLI defaulting. The operator chart values section + // should NOT contain the CLI's projectVersion-derived tag — the + // fixture didn't declare operator.image, so output is empty. + if strings.Contains(s, "tag: test") { + t.Errorf("escape kind should not apply CLI image defaults:\n%s", s) + } + if !strings.Contains(s, "kind: EducatesClusterConfig") { + t.Errorf("escape kind should still emit CR wrappers:\n%s", s) + } +} diff --git a/client-programs/pkg/cmd/admin_platform_values_cmd.go b/client-programs/pkg/cmd/admin_platform_values_cmd.go deleted file mode 100644 index 95f57bde5..000000000 --- a/client-programs/pkg/cmd/admin_platform_values_cmd.go +++ /dev/null @@ -1,146 +0,0 @@ -package cmd - -import ( - "fmt" - - "github.com/pkg/errors" - "github.com/spf13/cobra" - - "github.com/educates/educates-training-platform/client-programs/pkg/config" - "github.com/educates/educates-training-platform/client-programs/pkg/installer" -) - -var ( - adminPlatformValuesExample = ` - # Show configuration values for local deployment - educates admin platform values --local-config - - # Show configuration values for specific config file - educates admin platform values --config config.yaml - - # Get configuration used to deploy to the current cluster - educates admin platform values --from-cluster - educates admin platform values --from-cluster --kubeconfig /path/to/kubeconfig --context my-cluster - - # Get configuration values using locally built educates package (version latest does the same and skips image resolution) - educates admin platform values --config config.yaml --package-repository localhost:5001 --version 0.0.1 - educates admin platform values --config config.yaml --version latest - - # Get configuration values with different domain (to make copies of the config) - educates admin platform values --local-config --domain cluster1.dev.educates.io > cluster1-config.yaml - educates admin platform values --config config.yaml --domain cluster2.dev.educates.io > cluster2-config.yaml - ` -) - -type PlatformValuesOptions struct { - KubeconfigOptions - Config string - Domain string - Version string - PackageRepository string - LocalConfig bool - FromCluster bool - Verbose bool -} - -func (o *PlatformValuesOptions) Run() error { - installer := installer.NewInstaller() - - if o.FromCluster { - config, err := installer.GetValuesFromCluster(o.Kubeconfig, o.Context) - if err != nil { - return err - } - fmt.Println(config) - } else { - fullConfig, err := config.ConfigForLocalClusters(o.Config, o.Domain, o.LocalConfig) - - if err != nil { - return err - } - - if err := installer.DryRun(o.Version, o.PackageRepository, fullConfig, o.Verbose, true, true); err != nil { - return errors.Wrap(err, "educates config could not be processed") - } - } - - return nil -} - -func (p *ProjectInfo) NewAdminPlatformValuesCmd() *cobra.Command { - var o PlatformValuesOptions - - var c = &cobra.Command{ - Args: cobra.NoArgs, - Use: "values", - Short: "Show values to be applied when deploying the platform", - RunE: func(cmd *cobra.Command, _ []string) error { - if o.LocalConfig { - o.Config = "" - } - return o.Run() - }, - Example: adminPlatformValuesExample, - } - - c.Flags().StringVar( - &o.Config, - "config", - "", - "path to the installation config file for Educates", - ) - c.Flags().StringVar( - &o.Kubeconfig, - "kubeconfig", - "", - "kubeconfig file to use instead of $KUBECONFIG or $HOME/.kube/config", - ) - c.Flags().StringVar( - &o.Context, - "context", - "", - "Context to use from Kubeconfig", - ) - c.Flags().StringVar( - &o.Domain, - "domain", - "", - "wildcard ingress subdomain name for Educates", - ) - c.Flags().BoolVar( - &o.Verbose, - "verbose", - false, - "print verbose output", - ) - c.Flags().StringVar( - &o.PackageRepository, - "package-repository", - p.ImageRepository, - "image repository hosting package bundles", - ) - c.Flags().StringVar( - &o.Version, - "version", - p.Version, - "version to be installed", - ) - c.Flags().BoolVar( - &o.LocalConfig, - "local-config", - false, - "Use local configuration. When used, --config and --domain flags are ignored", - ) - // TODO: From cluster - c.Flags().BoolVar( - &o.FromCluster, - "from-cluster", - false, - "Show the configuration (from the cluster) used when the plaform was deployed", - ) - - c.MarkFlagsMutuallyExclusive("local-config", "config", "from-cluster") - c.MarkFlagsOneRequired("config", "local-config", "from-cluster") - - return c -} diff --git a/client-programs/pkg/cmd/deploy_pipeline.go b/client-programs/pkg/cmd/deploy_pipeline.go new file mode 100644 index 000000000..449ebad5e --- /dev/null +++ b/client-programs/pkg/cmd/deploy_pipeline.go @@ -0,0 +1,109 @@ +package cmd + +import ( + "context" + "fmt" + "io" + "os" + "time" + + "k8s.io/cli-runtime/pkg/genericclioptions" + + "github.com/educates/educates-training-platform/client-programs/pkg/config/translator" + "github.com/educates/educates-training-platform/client-programs/pkg/config/v1alpha1" + "github.com/educates/educates-training-platform/client-programs/pkg/deployer" + "github.com/educates/educates-training-platform/client-programs/pkg/deployer/progress" +) + +// deployPipelineFlags collects the kubectl/helm connection flags shared +// by both admin platform deploy and local cluster create's tail-call. +// Extracted so the two cmd paths can't drift on which flags they plumb +// (the original drift was tailCallDeploy missing --context). +type deployPipelineFlags struct { + Kubeconfig string + Context string + Timeout time.Duration + Verbose bool +} + +// translateAndDeploy is the shared "config → translator output → deploy" +// tail. Both admin platform deploy (after load+default) and local +// cluster create (after kind+registry bring-up) call this with a +// fully-loaded+defaulted config. Keeps the deploy.Options + Getter +// construction in one place so a new flag or default reaches both. +// +// caSecret{Name,Namespace} are required when cfg is *EducatesLocalConfig +// and ignored otherwise (the dispatcher in translator.Translate routes +// the opts only to TranslateLocal today). +func translateAndDeploy( + ctx context.Context, + w io.Writer, + cfg v1alpha1.Config, + caSecretName, caSecretNamespace string, + syncLocalSecrets bool, + flags deployPipelineFlags, +) error { + out, err := translator.Translate(cfg, translator.Options{ + CASecretName: caSecretName, + CASecretNamespace: caSecretNamespace, + }) + if err != nil { + return err + } + + cf := genericclioptions.NewConfigFlags(true) + if flags.Kubeconfig != "" { + cf.KubeConfig = &flags.Kubeconfig + } + if flags.Context != "" { + cf.Context = &flags.Context + } + ns := deployer.OperatorNamespace + cf.Namespace = &ns + + helmLog := io.Discard + if flags.Verbose { + helmLog = w + } + + return deployer.Deploy(ctx, out, deployer.Options{ + Getter: cf, + Out: w, + HelmLog: helmLog, + Timeout: flags.Timeout, + SyncLocalSecrets: syncLocalSecrets, + Progress: progress.New(w, 0, isStdoutTTY(w)), + }) +} + +// isStdoutTTY tells the progress reporter whether to use \r-based +// in-place updates. Cmd code passes cmd.OutOrStdout() into the +// pipeline; that's *os.File when running interactively, *bytes.Buffer +// in tests. +func isStdoutTTY(w io.Writer) bool { + f, ok := w.(*os.File) + if !ok { + return false + } + info, err := f.Stat() + if err != nil { + return false + } + return info.Mode()&os.ModeCharDevice != 0 +} + +// caRefForLocal looks up the cached CA Secret name + the conventional +// 'educates-secrets' namespace for an EducatesLocalConfig at translate +// time. Returns ("", "", err) when no cached CA matches the domain. +// Caller has already applied host-IP defaulting so c.Ingress.Domain is +// non-empty when we get here. +func caRefForLocal(c *v1alpha1.EducatesLocalConfig) (name, namespace string, err error) { + if c.Ingress.Domain == "" { + return "", "", fmt.Errorf("internal: ingress.domain is empty at CA-lookup time (host-IP defaulting should have run)") + } + name, err = lookupLocalCAByDomain(c.Ingress.Domain) + if err != nil { + return "", "", err + } + return name, LocalCASecretNamespace, nil +} diff --git a/client-programs/pkg/cmd/local_cluster_create_cmd.go b/client-programs/pkg/cmd/local_cluster_create_cmd.go index 876e4392f..149a8cbfe 100644 --- a/client-programs/pkg/cmd/local_cluster_create_cmd.go +++ b/client-programs/pkg/cmd/local_cluster_create_cmd.go @@ -2,307 +2,261 @@ package cmd import ( "context" - _ "embed" "fmt" "io" - "os" + "path/filepath" + "time" - "github.com/docker/docker/api/types/container" - "github.com/docker/docker/api/types/image" - "github.com/docker/go-connections/nat" - "github.com/pkg/errors" "github.com/spf13/cobra" "github.com/educates/educates-training-platform/client-programs/pkg/cluster" "github.com/educates/educates-training-platform/client-programs/pkg/config" - "github.com/educates/educates-training-platform/client-programs/pkg/docker" - "github.com/educates/educates-training-platform/client-programs/pkg/installer" + "github.com/educates/educates-training-platform/client-programs/pkg/config/hostinfo" + "github.com/educates/educates-training-platform/client-programs/pkg/config/v1alpha1" + "github.com/educates/educates-training-platform/client-programs/pkg/deployer" "github.com/educates/educates-training-platform/client-programs/pkg/registry" - "github.com/educates/educates-training-platform/client-programs/pkg/secrets" "github.com/educates/educates-training-platform/client-programs/pkg/utils" ) -var ( - localClusterCreateExample = ` - # Create local educates cluster (no configuration, uses nip.io wildcard domain and Kind as provider config defaults) - educates local cluster create - - # Create local educates cluster with custom configuration - educates local cluster create --config config.yaml - - # Create local kind cluster but don't install anything on it (it creates local registry but not local secrets) - educates local cluster create --cluster-only - - # Create local kind cluster but don't install anything on it, but providing some config for kind - educates local cluster create --cluster-only --config kind-config.yaml - - # Create local educates cluster with bundle from different repository - educates local cluster create --package-repository ghcr.io/jorgemoralespou --version installer-clean - - # Create local educates cluster with local build (for development) - educates local cluster create --package-repository localhost:5001 --version 0.0.1 +type LocalClusterCreateOptions struct { + Config string + LocalConfig bool + Kubeconfig string + Context string + ClusterImage string + ClusterOnly bool + RegistryBindIP string + Timeout time.Duration + Verbose bool +} - # Create local educates cluster with default configuration for a given domain - educates local cluster create --domain test.educates.io +func (p *ProjectInfo) NewLocalClusterCreateCmd() *cobra.Command { + var o LocalClusterCreateOptions - # Create local educates cluster with custom configuration providing a domain - educates local cluster create --config config.yaml --domain test.educates.io + c := &cobra.Command{ + Args: cobra.NoArgs, + Use: "create", + Short: "Create a local kind cluster, bring up the registry, and install Educates", + Long: `Lays down a full laptop install in one command: + + 1. Loads EducatesLocalConfig (or EducatesConfig with target.provider=kind). + 2. Creates the 'educates' kind cluster. + 3. Brings up the always-on localhost:5001 registry. + 4. Sets up the loopback service for 'educates serve-workshop'. + 5. Tail-calls into the platform deploy pipeline + (helm install operator + apply 4 platform CRs + wait Ready). + +--cluster-only stops after step 4 — useful for testing the platform +deploy against a hand-prepared cluster.`, + RunE: func(cmd *cobra.Command, _ []string) error { + ip, err := utils.ValidateAndResolveIP(o.RegistryBindIP) + if err != nil { + return fmt.Errorf("invalid --registry-bind-ip: %w", err) + } + o.RegistryBindIP = ip + return p.runLocalClusterCreate(cmd.Context(), cmd.OutOrStdout(), &o) + }, + } -` -) + c.Flags().StringVarP(&o.Config, "config", "c", "", "path to a CLI config file (any kind)") + c.Flags().BoolVar(&o.LocalConfig, "local-config", false, "use /config.yaml (default when --config is not given)") + c.Flags().StringVar(&o.Kubeconfig, "kubeconfig", "", "kubeconfig file (defaults to $KUBECONFIG / ~/.kube/config)") + c.Flags().StringVar(&o.Context, "context", "", "context name to use within the kubeconfig (for the platform deploy tail-call)") + c.Flags().StringVar(&o.ClusterImage, "kind-cluster-image", "", "docker image to use when booting the kind cluster") + c.Flags().BoolVar(&o.ClusterOnly, "cluster-only", false, "create kind cluster + registry; skip the platform deploy") + c.Flags().StringVar(&o.RegistryBindIP, "registry-bind-ip", "127.0.0.1", "bind IP for the always-on localhost:5001 registry") + c.Flags().DurationVar(&o.Timeout, "timeout", deployer.DefaultTimeout, "per-CR Ready=True wait timeout (passed through to deploy)") + c.Flags().BoolVar(&o.Verbose, "verbose", false, "show helm SDK debug output on stderr") + c.MarkFlagsMutuallyExclusive("config", "local-config") -type LocalClusterCreateOptions struct { - Config string - Kubeconfig string - ClusterImage string - Domain string - PackageRepository string - Version string - ClusterOnly bool - Verbose bool - SkipImageResolution bool - RegistryBindIP string + return c } -func (o *LocalClusterCreateOptions) Run() error { - - fullConfig, err := config.ConfigForLocalClusters(o.Config, o.Domain, true) - +func (p *ProjectInfo) runLocalClusterCreate(ctx context.Context, w io.Writer, o *LocalClusterCreateOptions) error { + cfg, configPath, err := loadLocalConfig(o) if err != nil { return err } - - if o.Verbose { - config.PrintConfigToStdout(fullConfig) + if err := applyLocalDefaults(cfg, p); err != nil { + return err } + // 0. Preflight: fail fast (before any docker / kind / k8s mutation) + // when the cluster already exists OR host 80/443 are bound. The + // second case is the v3 busybox probe — kind itself fails later + // with a much less actionable error if Envoy can't publish. clusterConfig := cluster.NewKindClusterConfig(o.Kubeconfig) - - if exists, err := clusterConfig.ClusterExists(); exists && err != nil { + if exists, err := clusterConfig.ClusterExists(); err != nil { return err + } else if exists { + return fmt.Errorf("kind cluster 'educates' already exists; run 'educates local cluster delete' first or use the existing cluster directly") } - - httpAvailable, err := checkPortAvailability(fullConfig.LocalKindCluster.ListenAddress, []uint{80, 443}, o.Verbose) - - if err != nil { - return errors.Wrap(err, "couldn't test whether ports 80/443 available") - } - - if !httpAvailable { - return errors.New("ports 80/443 not available") + if err := checkHostPortsAvailable(ctx, cfg.Cluster.ListenAddress, o.Verbose, w); err != nil { + return err } - err = clusterConfig.CreateCluster(fullConfig, o.ClusterImage) - - if err != nil { + // 1. kind bootstrap. kindBootstrapFromConfig builds the focused + // KindBootstrapInput from EducatesLocalConfig.Cluster fields + // the template reads. + fmt.Fprintln(w, "→ creating kind cluster 'educates'") + if err := clusterConfig.CreateCluster(kindBootstrapFromConfig(cfg), o.ClusterImage); err != nil { return err } - client, err := clusterConfig.Config.GetClient() - if err != nil { return err } - // This creates the educates-secrets namespace if it doesn't exist and creates the - // wildcard and CA secrets in there - if !o.ClusterOnly { - if err = secrets.SyncLocalCachedSecretsToCluster(client); err != nil { - return err - } - } - - if err = registry.DeployRegistryAndLinkToCluster(o.RegistryBindIP, client); err != nil { - return errors.Wrap(err, "failed to deploy registry") + // 2. always-on local registry + k8s Service for imgpkg pulls. + fmt.Fprintln(w, "→ bringing up localhost:5001 registry") + if err := registry.DeployRegistryAndLinkToCluster(o.RegistryBindIP, client); err != nil { + return fmt.Errorf("registry: %w", err) } - - // This is needed for imgpkg pull from locally published workshops - if err = registry.UpdateRegistryK8SService(client); err != nil { - return errors.Wrap(err, "failed to create service for registry") + if err := registry.UpdateRegistryK8SService(client); err != nil { + return fmt.Errorf("registry service: %w", err) } - // This is for hugo livereload (educates serve-workshop) - if err = cluster.CreateLoopbackService(client, fullConfig.ClusterIngress.Domain); err != nil { - return err + // 3. loopback service for hugo livereload (educates serve-workshop). + if err := cluster.CreateLoopbackService(client, cfg.Ingress.Domain); err != nil { + return fmt.Errorf("loopback service: %w", err) } - // Create and add registry mirrors defined in config to Kind nodes - for _, mirror := range fullConfig.LocalKindCluster.RegistryMirrors { - if err = registry.DeployMirrorAndLinkToCluster(&mirror); err != nil { - return errors.Wrap(err, "failed to deploy registry mirror "+mirror.Mirror) + // 4. registry mirrors declared in config (pull-through caches). + for _, m := range cfg.Cluster.RegistryMirrors { + fmt.Fprintf(w, "→ registry mirror %s → %s\n", m.Mirror, m.URL) + mc := registryMirrorFromConfig(m) + if err := registry.DeployMirrorAndLinkToCluster(&mc); err != nil { + return fmt.Errorf("mirror %s: %w", m.Mirror, err) } } - if !o.ClusterOnly { - installer := installer.NewInstaller() - err = installer.Run(o.Version, o.PackageRepository, fullConfig, &clusterConfig.Config, o.Verbose, false, o.SkipImageResolution, false) - if err != nil { - return errors.Wrap(err, "educates could not be installed") - } + if o.ClusterOnly { + fmt.Fprintln(w, "✓ cluster + registry ready (--cluster-only; skipped platform deploy)") + return nil } - fmt.Println("Educates cluster has been created succesfully") - - return nil + // 5. tail-call the v4 deploy. We have the loaded config; rather + // than re-loading it inside runDeploy (which would re-do + // the host-IP fallback non-deterministically against a freshly + // started cluster's IP), translate here and call deployer.Deploy + // directly. + fmt.Fprintln(w, "→ tail-calling admin platform deploy") + return tailCallDeploy(ctx, w, cfg, configPath, p, o) } -func (p *ProjectInfo) NewLocalClusterCreateCmd() *cobra.Command { - var o LocalClusterCreateOptions - - var c = &cobra.Command{ - Args: cobra.NoArgs, - Use: "create", - Short: "Creates a local Kubernetes cluster", - RunE: func(cmd *cobra.Command, _ []string) error { - ip, err := utils.ValidateAndResolveIP(o.RegistryBindIP) - if err != nil { - return errors.Wrap(err, "invalid registry bind IP") - } - o.RegistryBindIP = ip - - return o.Run() - }, - Example: localClusterCreateExample, - } - - c.Flags().StringVar( - &o.Config, - "config", - "", - "path to the installation config file for Educates", - ) - c.Flags().StringVar( - &o.Kubeconfig, - "kubeconfig", - "", - "kubeconfig file to use instead of $HOME/.kube/config", - ) - c.Flags().StringVar( - &o.ClusterImage, - "kind-cluster-image", - "", - "docker image to use when booting the kind cluster", - ) - c.Flags().StringVar( - &o.Domain, - "domain", - "", - "wildcard ingress subdomain name for Educates", - ) - c.Flags().StringVar( - &o.PackageRepository, - "package-repository", - p.ImageRepository, - "image repository hosting package bundles", - ) - c.Flags().StringVar( - &o.Version, - "version", - p.Version, - "version of Educates training platform to be installed", - ) - c.Flags().BoolVar( - &o.ClusterOnly, - "cluster-only", - false, - "only create the cluster, do not install Educates", - ) - c.Flags().BoolVar( - &o.Verbose, - "verbose", - false, - "print verbose output", - ) - c.Flags().BoolVar( - &o.SkipImageResolution, - "skip-image-resolution", - false, - "skips resolution of referenced images so that all will be fetched from their original location", - ) - c.Flags().StringVar( - &o.RegistryBindIP, - "registry-bind-ip", - "127.0.0.1", - "Bind ip for the registry service", - ) - return c -} - -func checkPortAvailability(listenAddress string, ports []uint, verbose bool) (bool, error) { - ctx := context.Background() - - cli, err := docker.NewDockerClient() - - if err != nil { - return false, errors.Wrap(err, "unable to create docker client") +// loadLocalConfig returns the loaded v4 config + the path it came from +// (used by error messages). Accepts EducatesLocalConfig directly or +// EducatesConfig with target.provider=kind; everything else errors. +func loadLocalConfig(o *LocalClusterCreateOptions) (*v1alpha1.EducatesLocalConfig, string, error) { + var path string + // --local-config is the default for laptop create — matches v3 + // behaviour where running the command with no flags pointed at + // /config.yaml. --config still wins when set. + if o.Config != "" { + path = o.Config + } else { + path = filepath.Join(utils.GetEducatesHomeDir(), "config.yaml") + if err := config.EnsureLocalConfigFile(utils.GetEducatesHomeDir()); err != nil { + return nil, "", err + } } - - cli.ContainerRemove(ctx, "educates-port-availability-check", container.RemoveOptions{}) - - reader, err := cli.ImagePull(ctx, "docker.io/library/busybox:latest", image.PullOptions{}) + cfg, err := config.Load(path) if err != nil { - return false, errors.Wrap(err, "cannot pull busybox image") + return nil, path, err } - - defer reader.Close() - - if verbose { - io.Copy(os.Stdout, reader) - } else { - io.Copy(io.Discard, reader) + switch c := cfg.(type) { + case *v1alpha1.EducatesLocalConfig: + return c, path, nil + case *v1alpha1.EducatesConfig: + if c.Target == nil || c.Target.Provider != "kind" { + return nil, path, fmt.Errorf("%s: EducatesConfig is accepted only with target.provider=kind for laptop create", path) + } + // Synthesise a LocalConfig that mirrors the cluster/resolver + // envelope from the escape kind. The remaining ECC/SessionManager + // CR fields stay in the escape config and reach the deploy via + // re-loading there. (Walking-skeleton compromise — step 11 might + // fold this differently when EducatesInlineConfig lands.) + return &v1alpha1.EducatesLocalConfig{ + TypeMeta: v1alpha1.TypeMeta{ + APIVersion: v1alpha1.APIVersion, + Kind: v1alpha1.KindEducatesLocalConfig, + }, + Cluster: c.Target.Cluster, + }, path, nil + default: + return nil, path, fmt.Errorf("%s: unsupported kind %q for local cluster create", path, cfg.GetKind()) } +} - if listenAddress == "" { - listenAddress, err = config.HostIP() - +// applyLocalDefaults mirrors what render/deploy do before translation: +// CLI-binary defaults for operator.image, host-IP nip.io for ingress.domain +// when empty. +func applyLocalDefaults(cfg *v1alpha1.EducatesLocalConfig, p *ProjectInfo) error { + cfg.ApplyCLIDefaults(p.Version, p.ImageRepository) + if cfg.Ingress.Domain == "" { + ip, err := hostinfo.DetectHostIP() if err != nil { - listenAddress = "127.0.0.1" + return fmt.Errorf("auto-detect host IP for ingress.domain: %w", err) } + cfg.Ingress.Domain = hostinfo.NipDomain(ip) } + return nil +} - hostConfig := &container.HostConfig{ - PortBindings: nat.PortMap{}, - } - - exposedPorts := nat.PortSet{} - - for _, port := range ports { - key := nat.Port(fmt.Sprintf("%d/tcp", port)) - hostConfig.PortBindings[key] = []nat.PortBinding{ - { - HostIP: listenAddress, - HostPort: fmt.Sprintf("%d", port), - }, +// kindBootstrapFromConfig pulls the kind-template inputs from an +// EducatesLocalConfig. +func kindBootstrapFromConfig(cfg *v1alpha1.EducatesLocalConfig) *cluster.KindBootstrapInput { + mounts := make([]cluster.KindVolumeMount, len(cfg.Cluster.VolumeMounts)) + for i, m := range cfg.Cluster.VolumeMounts { + mounts[i] = cluster.KindVolumeMount{ + HostPath: m.HostPath, + ContainerPath: m.ContainerPath, + } + // The v4 source-of-truth is *bool (so "unset" round-trips + // through YAML); collapse to the template-friendly pair here. + if m.ReadOnly != nil { + mounts[i].HasReadOnly = true + mounts[i].ReadOnly = *m.ReadOnly } - exposedPorts[key] = struct{}{} } - - resp, err := cli.ContainerCreate(ctx, &container.Config{ - Image: "docker.io/library/busybox:latest", - Cmd: []string{"/bin/true"}, - Tty: false, - ExposedPorts: exposedPorts, - }, hostConfig, nil, nil, "educates-port-availability-check") - - if err != nil { - return false, errors.Wrap(err, "cannot create busybox container") + return &cluster.KindBootstrapInput{ + ListenAddress: cfg.Cluster.ListenAddress, + ApiServer: cluster.KindApiServer{ + Address: cfg.Cluster.ApiServer.Address, + Port: cfg.Cluster.ApiServer.Port, + }, + Networking: cluster.KindNetworking{ + ServiceSubnet: cfg.Cluster.Networking.ServiceSubnet, + PodSubnet: cfg.Cluster.Networking.PodSubnet, + }, + VolumeMounts: mounts, } +} - defer cli.ContainerRemove(ctx, "educates-port-availability-check", container.RemoveOptions{}) - - if err := cli.ContainerStart(ctx, resp.ID, container.StartOptions{}); err != nil { - return false, errors.Wrap(err, "cannot start busybox container") +func registryMirrorFromConfig(m v1alpha1.RegistryMirror) registry.MirrorConfig { + return registry.MirrorConfig{ + Mirror: m.Mirror, + URL: m.URL, + Username: m.Username, + Password: m.Password, + Port: m.Port, + BindIP: m.BindIP, } +} - statusCh, errCh := cli.ContainerWait(ctx, "educates-port-availability-check", container.WaitConditionNotRunning) - - select { - case err := <-errCh: - if err != nil { - return false, nil - } - case <-statusCh: +// tailCallDeploy translates the already-loaded+defaulted config and +// runs the install. Shares the translate → deploy plumbing with +// runDeploy via translateAndDeploy; configPath isn't used by the shared +// helper (it kept the file-path around for the now-deleted re-load). +func tailCallDeploy(ctx context.Context, w io.Writer, cfg *v1alpha1.EducatesLocalConfig, _ string, _ *ProjectInfo, o *LocalClusterCreateOptions) error { + caName, caNS, err := caRefForLocal(cfg) + if err != nil { + return err } - - return true, nil + return translateAndDeploy(ctx, w, cfg, caName, caNS, true, deployPipelineFlags{ + Kubeconfig: o.Kubeconfig, + Context: o.Context, + Timeout: o.Timeout, + Verbose: o.Verbose, + }) } diff --git a/client-programs/pkg/cmd/local_cluster_create_preflight.go b/client-programs/pkg/cmd/local_cluster_create_preflight.go new file mode 100644 index 000000000..edfe7db09 --- /dev/null +++ b/client-programs/pkg/cmd/local_cluster_create_preflight.go @@ -0,0 +1,86 @@ +package cmd + +import ( + "context" + "fmt" + "io" + + "github.com/docker/docker/api/types/container" + "github.com/docker/docker/api/types/image" + "github.com/docker/go-connections/nat" + + "github.com/educates/educates-training-platform/client-programs/pkg/docker" +) + +// checkHostPortsAvailable confirms host 80 and 443 are free on the given +// listen address by attempting to start a busybox container with those +// ports bound. Mirrors the v3 'local cluster create' preflight — kind +// otherwise comes up successfully but Envoy can't publish 80/443 and +// the install hangs at IngressReady, leaving users to debug "cluster +// created but nothing reachable". +// +// listenAddress="" defaults to 127.0.0.1 (matches the kind template). +func checkHostPortsAvailable(ctx context.Context, listenAddress string, verbose bool, w io.Writer) error { + if listenAddress == "" { + listenAddress = "127.0.0.1" + } + + cli, err := docker.NewDockerClient() + if err != nil { + return fmt.Errorf("port-availability check: docker client: %w", err) + } + + const probeContainer = "educates-port-availability-check" + // Remove any leftover probe container from a previous interrupted run. + _ = cli.ContainerRemove(ctx, probeContainer, container.RemoveOptions{Force: true}) + + reader, err := cli.ImagePull(ctx, "docker.io/library/busybox:latest", image.PullOptions{}) + if err != nil { + return fmt.Errorf("port-availability check: pull busybox: %w", err) + } + defer reader.Close() + if verbose { + _, _ = io.Copy(w, reader) + } else { + _, _ = io.Copy(io.Discard, reader) + } + + exposed := nat.PortSet{} + bindings := nat.PortMap{} + for _, port := range []uint{80, 443} { + key := nat.Port(fmt.Sprintf("%d/tcp", port)) + exposed[key] = struct{}{} + bindings[key] = []nat.PortBinding{{HostIP: listenAddress, HostPort: fmt.Sprintf("%d", port)}} + } + + resp, err := cli.ContainerCreate(ctx, + &container.Config{ + Image: "docker.io/library/busybox:latest", + Cmd: []string{"/bin/true"}, + Tty: false, + ExposedPorts: exposed, + }, + &container.HostConfig{PortBindings: bindings}, + nil, nil, probeContainer) + if err != nil { + return fmt.Errorf("port-availability check: create probe: %w", err) + } + defer cli.ContainerRemove(ctx, probeContainer, container.RemoveOptions{Force: true}) + + if err := cli.ContainerStart(ctx, resp.ID, container.StartOptions{}); err != nil { + return fmt.Errorf("ports 80/443 not available on %s — another process (an ingress controller, a dev server, Docker Desktop port forwards) is holding them: %w", listenAddress, err) + } + + statusCh, errCh := cli.ContainerWait(ctx, probeContainer, container.WaitConditionNotRunning) + select { + case err := <-errCh: + if err != nil { + return fmt.Errorf("port-availability check: wait for probe: %w", err) + } + case <-statusCh: + case <-ctx.Done(): + return ctx.Err() + } + return nil +} + diff --git a/client-programs/pkg/cmd/local_cluster_create_test.go b/client-programs/pkg/cmd/local_cluster_create_test.go new file mode 100644 index 000000000..327f7bece --- /dev/null +++ b/client-programs/pkg/cmd/local_cluster_create_test.go @@ -0,0 +1,72 @@ +package cmd + +import ( + "testing" + + "github.com/educates/educates-training-platform/client-programs/pkg/config/v1alpha1" +) + +func TestKindBootstrapFromConfig_CarriesTemplateFields(t *testing.T) { + tr := true + cfg := &v1alpha1.EducatesLocalConfig{ + Cluster: v1alpha1.LocalClusterConfig{ + ListenAddress: "192.168.50.50", + ApiServer: v1alpha1.ApiServerConfig{ + Address: "192.168.50.50", + Port: 6443, + }, + Networking: v1alpha1.NetworkingConfig{ + ServiceSubnet: "10.96.0.0/12", + PodSubnet: "10.244.0.0/16", + }, + VolumeMounts: []v1alpha1.VolumeMount{ + {HostPath: "/tmp/data", ContainerPath: "/data", ReadOnly: &tr}, + }, + }, + } + in := kindBootstrapFromConfig(cfg) + + if got, want := in.ListenAddress, "192.168.50.50"; got != want { + t.Errorf("ListenAddress = %q, want %q", got, want) + } + if got, want := in.ApiServer.Port, 6443; got != want { + t.Errorf("ApiServer.Port = %d, want %d", got, want) + } + if got, want := in.Networking.PodSubnet, "10.244.0.0/16"; got != want { + t.Errorf("Networking.PodSubnet = %q, want %q", got, want) + } + if got := len(in.VolumeMounts); got != 1 { + t.Fatalf("VolumeMounts len = %d, want 1", got) + } + if got, want := in.VolumeMounts[0].HostPath, "/tmp/data"; got != want { + t.Errorf("VolumeMounts[0].HostPath = %q, want %q", got, want) + } + if !in.VolumeMounts[0].HasReadOnly || !in.VolumeMounts[0].ReadOnly { + t.Errorf("VolumeMounts[0] readOnly pair = {Has=%v, RO=%v}, want {true, true}", + in.VolumeMounts[0].HasReadOnly, in.VolumeMounts[0].ReadOnly) + } +} + +func TestKindBootstrapFromConfig_VolumeMountWithoutReadOnly_LeavesPairUnset(t *testing.T) { + cfg := &v1alpha1.EducatesLocalConfig{ + Cluster: v1alpha1.LocalClusterConfig{ + VolumeMounts: []v1alpha1.VolumeMount{ + {HostPath: "/tmp/data", ContainerPath: "/data"}, // ReadOnly nil + }, + }, + } + in := kindBootstrapFromConfig(cfg) + if in.VolumeMounts[0].HasReadOnly { + t.Errorf("HasReadOnly = true, want false (source ReadOnly was nil)") + } +} + +func TestKindBootstrapFromConfig_Empty_NoCrash(t *testing.T) { + in := kindBootstrapFromConfig(&v1alpha1.EducatesLocalConfig{}) + if in == nil { + t.Fatal("nil result") + } + if got := len(in.VolumeMounts); got != 0 { + t.Errorf("empty VolumeMounts len = %d, want 0", got) + } +} diff --git a/client-programs/pkg/cmd/local_config_cmd_group.go b/client-programs/pkg/cmd/local_config_cmd_group.go index e5ee71f8d..d9b3beb34 100644 --- a/client-programs/pkg/cmd/local_config_cmd_group.go +++ b/client-programs/pkg/cmd/local_config_cmd_group.go @@ -23,9 +23,11 @@ func (p *ProjectInfo) NewLocalConfigCmdGroup() *cobra.Command { { Message: "Available Commands:", Commands: []*cobra.Command{ + p.NewLocalConfigInitCmd(), + p.NewLocalConfigGetCmd(), + p.NewLocalConfigSetCmd(), p.NewLocalConfigEditCmd(), p.NewLocalConfigViewCmd(), - p.NewLocalConfigResetCmd(), }, }, } diff --git a/client-programs/pkg/cmd/local_config_edit_cmd.go b/client-programs/pkg/cmd/local_config_edit_cmd.go index 2b76ce1b6..3fc4b1abe 100644 --- a/client-programs/pkg/cmd/local_config_edit_cmd.go +++ b/client-programs/pkg/cmd/local_config_edit_cmd.go @@ -4,91 +4,77 @@ import ( "fmt" "os" "os/exec" - "path" + "path/filepath" - "github.com/pkg/errors" "github.com/spf13/cobra" + "github.com/educates/educates-training-platform/client-programs/pkg/config" "github.com/educates/educates-training-platform/client-programs/pkg/utils" ) func (p *ProjectInfo) NewLocalConfigEditCmd() *cobra.Command { - var c = &cobra.Command{ + return &cobra.Command{ Args: cobra.NoArgs, Use: "edit", - Short: "Edit local configuration", - RunE: func(_ *cobra.Command, _ []string) error { - err := os.MkdirAll(utils.GetEducatesHomeDir(), os.ModePerm) - - if err != nil { - return errors.Wrapf(err, "unable to create configuration directory %q", utils.GetEducatesHomeDir()) - } - - valuesFilePath := path.Join(utils.GetEducatesHomeDir(), "values.yaml") - tmpValuesFilePath := fmt.Sprintf("%s.%d", valuesFilePath, os.Getpid()) - - tmpValuesFile, err := os.OpenFile(tmpValuesFilePath, os.O_RDWR|os.O_CREATE|os.O_TRUNC, os.ModePerm) - - if err != nil { - return errors.Wrapf(err, "unable to create local configuration file %q", tmpValuesFilePath) - } - - valuesFileData, err := os.ReadFile(valuesFilePath) - - if err == nil && len(valuesFileData) != 0 { - tmpValuesFile.Write(valuesFileData) - } - - tmpValuesFile.Close() - - defer os.Remove(tmpValuesFilePath) - - editor := "vi" - - if s := os.Getenv("EDITOR"); s != "" { - editor = s - } - - editorPath, err := exec.LookPath(editor) - - if err != nil { - return errors.Wrapf(err, "unable to determine path for editor %q", editor) - - } - - cmd := exec.Command(editorPath, tmpValuesFilePath) - - cmd.Stdin = os.Stdin - cmd.Stdout = os.Stdout - cmd.Stderr = os.Stderr - - err = cmd.Start() - - if err != nil { - return errors.Wrapf(err, "cannot execute editor on configuration") - } - - err = cmd.Wait() - - if err != nil { - return errors.Wrapf(err, "editing of values configuration failed") - } - - _, err = config.NewInstallationConfigFromFile(tmpValuesFilePath) + Short: "Open /config.yaml in $EDITOR; validate against the schema on save", + Long: `Opens /config.yaml in $EDITOR (or vi if unset) in a temp +copy. On editor exit, the temp copy is validated against the +EducatesLocalConfig schema; a passing validation atomically replaces +the canonical file. A failing validation leaves the canonical file +untouched and returns the schema error so the user can re-run and try +again.`, + RunE: func(cmd *cobra.Command, _ []string) error { + return runLocalConfigEdit() + }, + } +} - if err != nil { - return errors.Wrapf(err, "error in values configuration file") - } +func runLocalConfigEdit() error { + dataHome := utils.GetEducatesHomeDir() + if err := os.MkdirAll(dataHome, 0o755); err != nil { + return fmt.Errorf("create data home %q: %w", dataHome, err) + } + canonical := filepath.Join(dataHome, "config.yaml") + tmp := fmt.Sprintf("%s.%d", canonical, os.Getpid()) + defer os.Remove(tmp) + + // Seed the temp file with current contents (or the minimal init + // stub when the canonical doesn't exist yet — so 'edit' on a + // pristine data home is a working flow). + seed, err := os.ReadFile(canonical) + if err != nil { + if !os.IsNotExist(err) { + return fmt.Errorf("read %s: %w", canonical, err) + } + seed = []byte(defaultLocalConfigYAML) + } + if err := os.WriteFile(tmp, seed, 0o644); err != nil { + return fmt.Errorf("write temp file: %w", err) + } - err = os.Rename(tmpValuesFilePath, valuesFilePath) + editor := "vi" + if v := os.Getenv("EDITOR"); v != "" { + editor = v + } + editorPath, err := exec.LookPath(editor) + if err != nil { + return fmt.Errorf("locate editor %q: %w", editor, err) + } - if err != nil { - return errors.Wrapf(err, "unable to update default configuration") - } + cmd := exec.Command(editorPath, tmp) + cmd.Stdin = os.Stdin + cmd.Stdout = os.Stdout + cmd.Stderr = os.Stderr + if err := cmd.Run(); err != nil { + return fmt.Errorf("editor: %w", err) + } - return nil - }, + if _, err := config.LoadLocal(tmp); err != nil { + return fmt.Errorf("validation failed; canonical file left unchanged: %w", err) } - return c + if err := os.Rename(tmp, canonical); err != nil { + return fmt.Errorf("replace %s: %w", canonical, err) + } + return nil } diff --git a/client-programs/pkg/cmd/local_config_get_cmd.go b/client-programs/pkg/cmd/local_config_get_cmd.go new file mode 100644 index 000000000..90fc3add6 --- /dev/null +++ b/client-programs/pkg/cmd/local_config_get_cmd.go @@ -0,0 +1,108 @@ +package cmd + +import ( + "fmt" + "io" + "os" + "path/filepath" + "strings" + + "github.com/spf13/cobra" + "gopkg.in/yaml.v2" + + "github.com/educates/educates-training-platform/client-programs/pkg/utils" +) + +func (p *ProjectInfo) NewLocalConfigGetCmd() *cobra.Command { + c := &cobra.Command{ + Args: cobra.MaximumNArgs(1), + Use: "get [PATH]", + Short: "Read a field from /config.yaml by dotted path", + Long: `Print a field from the EducatesLocalConfig. Path is dotted, e.g. +'ingress.domain' or 'operator.image.tag'. With no argument, prints the +whole file. + +For scalar fields, the value is printed bare (no quoting). For maps and +lists, YAML-serialised output is emitted.`, + Example: ` educates local config get + educates local config get ingress.domain + educates local config get operator.image`, + RunE: func(cmd *cobra.Command, args []string) error { + path := "" + if len(args) == 1 { + path = args[0] + } + return runLocalConfigGet(cmd.OutOrStdout(), path) + }, + } + return c +} + +func runLocalConfigGet(w io.Writer, path string) error { + cfgPath := filepath.Join(utils.GetEducatesHomeDir(), "config.yaml") + data, err := os.ReadFile(cfgPath) + if err != nil { + return fmt.Errorf("read %s: %w", cfgPath, err) + } + + if path == "" { + _, err := w.Write(data) + return err + } + + // Parse into a generic map so we can walk by string keys. Don't + // validate against the schema here — get is read-only; the file may + // already be in an invalid state and we still want to surface its + // contents. + var root map[string]interface{} + if err := yaml.Unmarshal(data, &root); err != nil { + return fmt.Errorf("parse %s: %w", cfgPath, err) + } + + val, ok := getByPath(root, path) + if !ok { + return fmt.Errorf("path %q not found in %s", path, cfgPath) + } + + switch v := val.(type) { + case string: + fmt.Fprintln(w, v) + case int, int64, float64, bool, nil: + fmt.Fprintln(w, v) + default: + out, err := yaml.Marshal(v) + if err != nil { + return fmt.Errorf("marshal %s: %w", path, err) + } + _, err = w.Write(out) + return err + } + return nil +} + +// getByPath walks root by dotted path. yaml.v2 produces +// map[interface{}]interface{} for nested objects; normalise on the fly +// rather than pre-walking the whole tree. +func getByPath(root map[string]interface{}, path string) (interface{}, bool) { + segs := strings.Split(path, ".") + var cur interface{} = root + for _, s := range segs { + switch m := cur.(type) { + case map[string]interface{}: + v, ok := m[s] + if !ok { + return nil, false + } + cur = v + case map[interface{}]interface{}: + v, ok := m[s] + if !ok { + return nil, false + } + cur = v + default: + return nil, false + } + } + return cur, true +} diff --git a/client-programs/pkg/cmd/local_config_init_cmd.go b/client-programs/pkg/cmd/local_config_init_cmd.go new file mode 100644 index 000000000..84b8cf7e1 --- /dev/null +++ b/client-programs/pkg/cmd/local_config_init_cmd.go @@ -0,0 +1,61 @@ +package cmd + +import ( + "fmt" + "os" + "path/filepath" + + "github.com/spf13/cobra" + + "github.com/educates/educates-training-platform/client-programs/pkg/config/v1alpha1" + "github.com/educates/educates-training-platform/client-programs/pkg/utils" +) + +// The yaml-language-server modeline gives completion and validation in +// any editor with a YAML language server, against the schema published +// by the release workflow. +const defaultLocalConfigYAML = `# yaml-language-server: $schema=` + v1alpha1.SchemaBaseURL + v1alpha1.KindEducatesLocalConfig + `.json +apiVersion: ` + v1alpha1.APIVersion + ` +kind: ` + v1alpha1.KindEducatesLocalConfig + ` +` + +type LocalConfigInitOptions struct { + Force bool +} + +func (p *ProjectInfo) NewLocalConfigInitCmd() *cobra.Command { + var o LocalConfigInitOptions + + c := &cobra.Command{ + Args: cobra.NoArgs, + Use: "init", + Short: "Write a default EducatesLocalConfig to /config.yaml", + Long: `Creates /config.yaml with the minimum EducatesLocalConfig +(apiVersion + kind only). All other fields take their schema defaults at +deploy time. Errors if the file already exists unless --force. + + is $EDUCATES_CLI_DATA_HOME if set, otherwise +$XDG_DATA_HOME/educates.`, + RunE: func(cmd *cobra.Command, _ []string) error { + return o.Run(cmd.OutOrStdout()) + }, + } + c.Flags().BoolVar(&o.Force, "force", false, "overwrite existing config.yaml") + return c +} + +func (o *LocalConfigInitOptions) Run(w interface{ Write([]byte) (int, error) }) error { + dataHome := utils.GetEducatesHomeDir() + if err := os.MkdirAll(dataHome, 0o755); err != nil { + return fmt.Errorf("create data home %q: %w", dataHome, err) + } + path := filepath.Join(dataHome, "config.yaml") + if _, err := os.Stat(path); err == nil && !o.Force { + return fmt.Errorf("%s already exists (use --force to overwrite)", path) + } + if err := os.WriteFile(path, []byte(defaultLocalConfigYAML), 0o644); err != nil { + return fmt.Errorf("write %s: %w", path, err) + } + fmt.Fprintf(w, "wrote %s\n", path) + return nil +} diff --git a/client-programs/pkg/cmd/local_config_reset_cmd.go b/client-programs/pkg/cmd/local_config_reset_cmd.go deleted file mode 100644 index 450b5ef8e..000000000 --- a/client-programs/pkg/cmd/local_config_reset_cmd.go +++ /dev/null @@ -1,26 +0,0 @@ -package cmd - -import ( - "os" - "path" - - "github.com/spf13/cobra" - "github.com/educates/educates-training-platform/client-programs/pkg/utils" -) - -func (p *ProjectInfo) NewLocalConfigResetCmd() *cobra.Command { - var c = &cobra.Command{ - Args: cobra.NoArgs, - Use: "reset", - Short: "Reset local configuration", - RunE: func(_ *cobra.Command, _ []string) error { - valuesFile := path.Join(utils.GetEducatesHomeDir(), "values.yaml") - - os.Remove(valuesFile) - - return nil - }, - } - - return c -} diff --git a/client-programs/pkg/cmd/local_config_set_cmd.go b/client-programs/pkg/cmd/local_config_set_cmd.go new file mode 100644 index 000000000..a70929f48 --- /dev/null +++ b/client-programs/pkg/cmd/local_config_set_cmd.go @@ -0,0 +1,193 @@ +package cmd + +import ( + "fmt" + "io" + "os" + "path/filepath" + "strconv" + "strings" + + "github.com/spf13/cobra" + "github.com/xeipuuv/gojsonschema" + "gopkg.in/yaml.v2" + + "github.com/educates/educates-training-platform/client-programs/pkg/config/v1alpha1/schemas" + "github.com/educates/educates-training-platform/client-programs/pkg/utils" +) + +func (p *ProjectInfo) NewLocalConfigSetCmd() *cobra.Command { + c := &cobra.Command{ + Args: cobra.ExactArgs(2), + Use: "set PATH VALUE", + Short: "Set a field in /config.yaml by dotted path", + Long: `Modify a field in the EducatesLocalConfig file. Path is dotted, e.g. +'ingress.domain' or 'operator.logLevel'. Intermediate maps are auto- +created as needed. + +VALUE is coerced based on its raw form: + - 'true' / 'false' → boolean + - integer-looking strings → integer + - everything else → string + +The full config is re-validated against the EducatesLocalConfig schema +after the change. The write only happens when validation passes, so +type / enum errors are caught up front with the offending field path.`, + Example: ` educates local config set ingress.domain workshop.test + educates local config set operator.logLevel debug + educates local config set lookupService false`, + RunE: func(cmd *cobra.Command, args []string) error { + return runLocalConfigSet(cmd.OutOrStdout(), args[0], args[1]) + }, + } + return c +} + +func runLocalConfigSet(w io.Writer, path, rawValue string) error { + cfgPath := filepath.Join(utils.GetEducatesHomeDir(), "config.yaml") + data, err := os.ReadFile(cfgPath) + if err != nil { + return fmt.Errorf("read %s (run 'educates local config init' first?): %w", cfgPath, err) + } + + // Round-trip through yaml.v2 → JSON-friendly map so gojsonschema + // and yaml.v2 marshalling both work the same way. + var root map[string]interface{} + if err := yaml.Unmarshal(data, &root); err != nil { + return fmt.Errorf("parse %s: %w", cfgPath, err) + } + if root == nil { + root = map[string]interface{}{} + } + + if err := setByPath(root, path, coerce(rawValue)); err != nil { + return err + } + + if err := validateAgainstLocalSchema(root, cfgPath, path); err != nil { + return err + } + + out, err := yaml.Marshal(root) + if err != nil { + return fmt.Errorf("marshal config: %w", err) + } + if err := os.WriteFile(cfgPath, out, 0o644); err != nil { + return fmt.Errorf("write %s: %w", cfgPath, err) + } + fmt.Fprintf(w, "%s.%s = %v\n", filepath.Base(cfgPath), path, coerce(rawValue)) + return nil +} + +// setByPath walks root by dotted path, creating intermediate maps as +// needed, and sets the leaf to value. yaml.v2 produces +// map[interface{}]interface{} for nested objects from a Unmarshal; we +// normalise every step we touch to map[string]interface{} so the +// re-marshal is clean. +func setByPath(root map[string]interface{}, path string, value interface{}) error { + segs := strings.Split(path, ".") + if len(segs) == 0 || segs[0] == "" { + return fmt.Errorf("empty path") + } + cur := root + for i, s := range segs[:len(segs)-1] { + next, ok := cur[s] + if !ok { + n := map[string]interface{}{} + cur[s] = n + cur = n + continue + } + switch m := next.(type) { + case map[string]interface{}: + cur = m + case map[interface{}]interface{}: + conv := map[string]interface{}{} + for k, v := range m { + conv[fmt.Sprint(k)] = v + } + cur[s] = conv + cur = conv + default: + return fmt.Errorf("path %q: segment %q is a %T, not a map", path, strings.Join(segs[:i+1], "."), next) + } + } + cur[segs[len(segs)-1]] = value + return nil +} + +// coerce maps the raw CLI string to a typed value. Conservative: only +// bools and pure integers are recognised; anything else stays a string +// so the schema's "type: string" enforcement does the rest. +func coerce(raw string) interface{} { + switch raw { + case "true": + return true + case "false": + return false + } + if n, err := strconv.Atoi(raw); err == nil { + return n + } + return raw +} + +// validateAgainstLocalSchema runs the in-memory map through the embedded +// EducatesLocalConfig schema. On failure, errors mention the offending +// JSON path so the user can see which field rejected the value. +// +// We deliberately validate the WHOLE config, not just the field we set: +// catches cases where the new value collides with another field's +// constraint (e.g. setting `mode` would always fail since the schema +// rejects mode at the top level). +func validateAgainstLocalSchema(root map[string]interface{}, source, attemptedPath string) error { + // gojsonschema needs JSON-compatible types; yaml.v2 returns + // map[interface{}]interface{} for objects, which json.Marshal + // rejects. Normalise. + normalised := normaliseForJSON(root) + + loader := gojsonschema.NewBytesLoader(schemas.EducatesLocalConfig) + docLoader := gojsonschema.NewGoLoader(normalised) + result, err := gojsonschema.Validate(loader, docLoader) + if err != nil { + return fmt.Errorf("%s: schema validation: %w", source, err) + } + if result.Valid() { + return nil + } + + var msgs []string + for _, e := range result.Errors() { + msgs = append(msgs, fmt.Sprintf(" - %s: %s", e.Field(), e.Description())) + } + return fmt.Errorf(`set %q rejected by schema validation. %s would become invalid: +%s`, attemptedPath, source, strings.Join(msgs, "\n")) +} + +// normaliseForJSON converts yaml.v2's map[interface{}]interface{} to +// map[string]interface{} recursively. Duplicates the helper in the +// loader; keeping it local avoids exposing it from pkg/config. +func normaliseForJSON(v interface{}) interface{} { + switch x := v.(type) { + case map[interface{}]interface{}: + m := make(map[string]interface{}, len(x)) + for k, val := range x { + m[fmt.Sprint(k)] = normaliseForJSON(val) + } + return m + case map[string]interface{}: + m := make(map[string]interface{}, len(x)) + for k, val := range x { + m[k] = normaliseForJSON(val) + } + return m + case []interface{}: + out := make([]interface{}, len(x)) + for i, val := range x { + out[i] = normaliseForJSON(val) + } + return out + default: + return v + } +} diff --git a/client-programs/pkg/cmd/local_config_v4_cmds_test.go b/client-programs/pkg/cmd/local_config_v4_cmds_test.go new file mode 100644 index 000000000..fc92021e0 --- /dev/null +++ b/client-programs/pkg/cmd/local_config_v4_cmds_test.go @@ -0,0 +1,162 @@ +package cmd + +import ( + "bytes" + "io" + "os" + "path/filepath" + "strings" + "testing" +) + +func TestLocalConfigInit_WritesDefault(t *testing.T) { + t.Setenv("EDUCATES_CLI_DATA_HOME", t.TempDir()) + + o := &LocalConfigInitOptions{} + if err := o.Run(io.Discard); err != nil { + t.Fatalf("init: %v", err) + } + + body, err := os.ReadFile(filepath.Join(os.Getenv("EDUCATES_CLI_DATA_HOME"), "config.yaml")) + if err != nil { + t.Fatal(err) + } + s := string(body) + for _, want := range []string{"apiVersion: cli.educates.dev/v1alpha1", "kind: EducatesLocalConfig"} { + if !strings.Contains(s, want) { + t.Errorf("init output missing %q:\n%s", want, s) + } + } +} + +func TestLocalConfigInit_ExistingFile_ErrorsWithoutForce(t *testing.T) { + dataHome := t.TempDir() + t.Setenv("EDUCATES_CLI_DATA_HOME", dataHome) + if err := os.WriteFile(filepath.Join(dataHome, "config.yaml"), []byte("existing"), 0o644); err != nil { + t.Fatal(err) + } + + o := &LocalConfigInitOptions{} + err := o.Run(io.Discard) + if err == nil { + t.Fatal("expected error, got nil") + } + if !strings.Contains(err.Error(), "already exists") { + t.Errorf("error %q does not mention 'already exists'", err) + } +} + +func TestLocalConfigInit_Force_Overwrites(t *testing.T) { + dataHome := t.TempDir() + t.Setenv("EDUCATES_CLI_DATA_HOME", dataHome) + if err := os.WriteFile(filepath.Join(dataHome, "config.yaml"), []byte("old"), 0o644); err != nil { + t.Fatal(err) + } + o := &LocalConfigInitOptions{Force: true} + if err := o.Run(io.Discard); err != nil { + t.Fatal(err) + } + body, _ := os.ReadFile(filepath.Join(dataHome, "config.yaml")) + if !strings.Contains(string(body), "EducatesLocalConfig") { + t.Errorf("--force did not overwrite: %q", string(body)) + } +} + +func TestLocalConfigSet_ScalarRoundTrip(t *testing.T) { + dataHome := stageInitConfig(t) + var buf bytes.Buffer + if err := runLocalConfigSet(&buf, "ingress.domain", "workshop.test"); err != nil { + t.Fatalf("set: %v", err) + } + body, _ := os.ReadFile(filepath.Join(dataHome, "config.yaml")) + if !strings.Contains(string(body), "domain: workshop.test") { + t.Errorf("file missing the set value:\n%s", body) + } + + // Round-trip through get. + var out bytes.Buffer + if err := runLocalConfigGet(&out, "ingress.domain"); err != nil { + t.Fatalf("get: %v", err) + } + if got := strings.TrimSpace(out.String()); got != "workshop.test" { + t.Errorf("get ingress.domain = %q, want %q", got, "workshop.test") + } +} + +func TestLocalConfigSet_CoercesBoolAndInt(t *testing.T) { + stageInitConfig(t) + if err := runLocalConfigSet(io.Discard, "lookupService", "false"); err != nil { + t.Fatalf("set bool: %v", err) + } + if err := runLocalConfigSet(io.Discard, "cluster.apiServer.port", "6443"); err != nil { + t.Fatalf("set int: %v", err) + } + + // get should return scalar form. + var b1, b2 bytes.Buffer + _ = runLocalConfigGet(&b1, "lookupService") + _ = runLocalConfigGet(&b2, "cluster.apiServer.port") + if got := strings.TrimSpace(b1.String()); got != "false" { + t.Errorf("lookupService get = %q, want %q", got, "false") + } + if got := strings.TrimSpace(b2.String()); got != "6443" { + t.Errorf("apiServer.port get = %q, want %q", got, "6443") + } +} + +func TestLocalConfigSet_SchemaViolation_Errors(t *testing.T) { + stageInitConfig(t) + // logLevel enum is [debug, info, warn, error]; "trace" rejected. + err := runLocalConfigSet(io.Discard, "operator.logLevel", "trace") + if err == nil { + t.Fatal("expected schema rejection, got nil") + } + if !strings.Contains(err.Error(), "logLevel") { + t.Errorf("error %q does not mention the field path", err) + } +} + +func TestLocalConfigSet_UnknownField_Errors(t *testing.T) { + stageInitConfig(t) + err := runLocalConfigSet(io.Discard, "bogus", "x") + if err == nil { + t.Fatal("expected schema rejection") + } + if !strings.Contains(err.Error(), "bogus") { + t.Errorf("error %q does not mention the unknown field", err) + } +} + +func TestLocalConfigGet_MissingPath_Errors(t *testing.T) { + stageInitConfig(t) + err := runLocalConfigGet(io.Discard, "ingress.domain") + if err == nil { + t.Fatal("expected 'path not found' error on empty config") + } + if !strings.Contains(err.Error(), "not found") { + t.Errorf("error %q does not say 'not found'", err) + } +} + +func TestLocalConfigGet_FullFile_NoArg(t *testing.T) { + stageInitConfig(t) + var buf bytes.Buffer + if err := runLocalConfigGet(&buf, ""); err != nil { + t.Fatalf("get (no arg): %v", err) + } + if !strings.Contains(buf.String(), "EducatesLocalConfig") { + t.Errorf("expected full file output, got: %s", buf.String()) + } +} + +// stageInitConfig sets up $EDUCATES_CLI_DATA_HOME with a freshly init'd +// EducatesLocalConfig at config.yaml. Returns the data home path. +func stageInitConfig(t *testing.T) string { + t.Helper() + dataHome := t.TempDir() + t.Setenv("EDUCATES_CLI_DATA_HOME", dataHome) + if err := (&LocalConfigInitOptions{}).Run(io.Discard); err != nil { + t.Fatal(err) + } + return dataHome +} diff --git a/client-programs/pkg/cmd/local_config_view_cmd.go b/client-programs/pkg/cmd/local_config_view_cmd.go index cbdb22240..92fc2af11 100644 --- a/client-programs/pkg/cmd/local_config_view_cmd.go +++ b/client-programs/pkg/cmd/local_config_view_cmd.go @@ -2,76 +2,47 @@ package cmd import ( "fmt" + "os" + "path/filepath" - "github.com/pkg/errors" "github.com/spf13/cobra" - "github.com/educates/educates-training-platform/client-programs/pkg/config" - "gopkg.in/yaml.v2" -) - -var ( - localConfigViewExample = ` - # View local educates cluster configuration by default. Uses nip.io wildcard domain and Kind as provider config defaults - educates local config view --config NULL - - # View local educates cluster configuration stored. Will show the default if local config file is empty - educates local config view - # View local educates cluster configuration using provided config. If there's secrets for that domain, they will be used - educates local config view --config config.yaml - - # View local educates cluster configuration using provided domain. If there's secrets for that domain, they will be used - educates local config view --domain test.example.com -` + "github.com/educates/educates-training-platform/client-programs/pkg/config" + "github.com/educates/educates-training-platform/client-programs/pkg/utils" ) -type LocalConfigViewOptions struct { - Config string - Domain string +func (p *ProjectInfo) NewLocalConfigViewCmd() *cobra.Command { + c := &cobra.Command{ + Args: cobra.NoArgs, + Use: "view", + Short: "Print /config.yaml, validating it against the EducatesLocalConfig schema", + Long: `Reads /config.yaml, validates it against the +EducatesLocalConfig schema, and prints the raw file contents. + +For programmatic field reads use 'educates local config get [PATH]' — +view's job is to surface the file as the user wrote it (including any +comments) plus assert it would load cleanly at deploy time.`, + RunE: func(cmd *cobra.Command, _ []string) error { + return runLocalConfigView(cmd.OutOrStdout()) + }, + } + return c } -func (o *LocalConfigViewOptions) Run() error { - fullConfig, err := config.ConfigForLocalClusters(o.Config, o.Domain, true) - if err != nil { +func runLocalConfigView(w interface{ Write([]byte) (int, error) }) error { + cfgPath := filepath.Join(utils.GetEducatesHomeDir(), "config.yaml") + if err := config.EnsureLocalConfigFile(utils.GetEducatesHomeDir()); err != nil { return err } - - configData, err := yaml.Marshal(&fullConfig) - - if err != nil { - return errors.Wrap(err, "failed to generate installation config") + // Validate (Load runs the JSON schema check); we discard the typed + // value because view's contract is to surface the raw file. + if _, err := config.LoadLocal(cfgPath); err != nil { + return fmt.Errorf("%s: %w", cfgPath, err) } - - fmt.Print(string(configData)) - - return nil -} - -func (p *ProjectInfo) NewLocalConfigViewCmd() *cobra.Command { - var o LocalConfigViewOptions - - var c = &cobra.Command{ - Args: cobra.NoArgs, - Use: "view", - Short: "View local configuration", - Long: "View local configuration. Uses nip.io wildcard domain and Kind as provider config defaults", - RunE: func(_ *cobra.Command, _ []string) error { return o.Run() }, - Example: localConfigViewExample, + body, err := os.ReadFile(cfgPath) + if err != nil { + return err } - - c.Flags().StringVar( - &o.Domain, - "domain", - "", - "wildcard ingress subdomain name for Educates", - ) - - c.Flags().StringVar( - &o.Config, - "config", - "", - "path to the installation config file for Educates", - ) - - return c + _, err = w.Write(body) + return err } diff --git a/client-programs/pkg/cmd/local_mirror_delete_cmd.go b/client-programs/pkg/cmd/local_mirror_delete_cmd.go index 8ecb53fea..1c61c7106 100644 --- a/client-programs/pkg/cmd/local_mirror_delete_cmd.go +++ b/client-programs/pkg/cmd/local_mirror_delete_cmd.go @@ -3,7 +3,7 @@ package cmd import ( "github.com/spf13/cobra" - "github.com/educates/educates-training-platform/client-programs/pkg/config" + "github.com/educates/educates-training-platform/client-programs/pkg/registry" ) @@ -19,7 +19,7 @@ type LocalMirrorDeleteOptions struct { } func (o *LocalMirrorDeleteOptions) Run() error { - mirrorConfig := &config.RegistryMirrorConfig{ + mirrorConfig := ®istry.MirrorConfig{ Mirror: o.MirrorName, } diff --git a/client-programs/pkg/cmd/local_mirror_deploy_cmd.go b/client-programs/pkg/cmd/local_mirror_deploy_cmd.go index baf03678c..9e03f12df 100644 --- a/client-programs/pkg/cmd/local_mirror_deploy_cmd.go +++ b/client-programs/pkg/cmd/local_mirror_deploy_cmd.go @@ -4,7 +4,7 @@ import ( "github.com/pkg/errors" "github.com/spf13/cobra" - "github.com/educates/educates-training-platform/client-programs/pkg/config" + "github.com/educates/educates-training-platform/client-programs/pkg/registry" ) @@ -32,7 +32,7 @@ type LocalMirrorDeployOptions struct { } func (o *LocalMirrorDeployOptions) Run() error { - mirrorConfig := &config.RegistryMirrorConfig{ + mirrorConfig := ®istry.MirrorConfig{ Mirror: o.MirrorName, URL: o.MirrorURL, Username: o.Username, diff --git a/client-programs/pkg/cmd/local_resolver_deploy_cmd.go b/client-programs/pkg/cmd/local_resolver_deploy_cmd.go index aaf643e7b..cb40fcbe1 100644 --- a/client-programs/pkg/cmd/local_resolver_deploy_cmd.go +++ b/client-programs/pkg/cmd/local_resolver_deploy_cmd.go @@ -1,60 +1,83 @@ package cmd import ( + "fmt" + "path/filepath" + "github.com/spf13/cobra" "github.com/educates/educates-training-platform/client-programs/pkg/config" + "github.com/educates/educates-training-platform/client-programs/pkg/config/v1alpha1" "github.com/educates/educates-training-platform/client-programs/pkg/resolver" + "github.com/educates/educates-training-platform/client-programs/pkg/utils" ) type LocalResolverDeployOptions struct { - Config string - Domain string + Config string + LocalConfig bool + Domain string } func (o *LocalResolverDeployOptions) Run() error { - var fullConfig *config.InstallationConfig - var err error = nil - - if o.Config != "" { - fullConfig, err = config.NewInstallationConfigFromFile(o.Config) - } else { - fullConfig, err = config.NewInstallationConfigFromUserFile() - } - + cfg, err := loadResolverInputs(o.Config, o.LocalConfig) if err != nil { return err } - + domain := cfg.Ingress.Domain if o.Domain != "" { - fullConfig.ClusterIngress.Domain = o.Domain + domain = o.Domain } - - return resolver.DeployResolver(fullConfig.ClusterIngress.Domain, fullConfig.LocalDNSResolver.TargetAddress, fullConfig.LocalDNSResolver.ExtraDomains) + return resolver.DeployResolver(domain, cfg.Resolver.TargetAddress, cfg.Resolver.ExtraDomains) } func (p *ProjectInfo) NewLocalResolverDeployCmd() *cobra.Command { var o LocalResolverDeployOptions - var c = &cobra.Command{ + c := &cobra.Command{ Args: cobra.NoArgs, Use: "deploy", - Short: "Deploys a local DNS resolver", + Short: "Deploys a local DNS resolver (macOS)", RunE: func(_ *cobra.Command, _ []string) error { return o.Run() }, } - - c.Flags().StringVar( - &o.Config, - "config", - "", - "path to the installation config file for Educates", - ) - c.Flags().StringVar( - &o.Domain, - "domain", - "", - "wildcard ingress subdomain name for Educates", - ) - + c.Flags().StringVarP(&o.Config, "config", "c", "", "path to a CLI config file (any kind)") + c.Flags().BoolVar(&o.LocalConfig, "local-config", false, "use /config.yaml") + c.Flags().StringVar(&o.Domain, "domain", "", "override ingress.domain from the config") + c.MarkFlagsMutuallyExclusive("config", "local-config") + c.MarkFlagsOneRequired("config", "local-config") return c } + +// loadResolverInputs loads an EducatesLocalConfig from --config or +// --local-config and returns the parts the resolver helpers need. +// EducatesConfig (escape hatch) is accepted when target.cluster / +// target.resolver are populated. +func loadResolverInputs(configPath string, useLocalConfig bool) (*v1alpha1.EducatesLocalConfig, error) { + var path string + if useLocalConfig { + path = filepath.Join(utils.GetEducatesHomeDir(), "config.yaml") + if err := config.EnsureLocalConfigFile(utils.GetEducatesHomeDir()); err != nil { + return nil, err + } + } else { + path = configPath + } + loaded, err := config.Load(path) + if err != nil { + return nil, err + } + switch c := loaded.(type) { + case *v1alpha1.EducatesLocalConfig: + return c, nil + case *v1alpha1.EducatesConfig: + if c.Target == nil { + return nil, fmt.Errorf("%s: EducatesConfig has no target block; resolver needs target.resolver.*", path) + } + return &v1alpha1.EducatesLocalConfig{ + TypeMeta: v1alpha1.TypeMeta{APIVersion: v1alpha1.APIVersion, Kind: v1alpha1.KindEducatesLocalConfig}, + Cluster: c.Target.Cluster, + Resolver: c.Target.Resolver, + }, nil + default: + return nil, fmt.Errorf("%s: unsupported kind %q for resolver commands", path, loaded.GetKind()) + } +} diff --git a/client-programs/pkg/cmd/local_resolver_update_cmd.go b/client-programs/pkg/cmd/local_resolver_update_cmd.go index 93c0648bc..c75dacf15 100644 --- a/client-programs/pkg/cmd/local_resolver_update_cmd.go +++ b/client-programs/pkg/cmd/local_resolver_update_cmd.go @@ -3,48 +3,34 @@ package cmd import ( "github.com/spf13/cobra" - "github.com/educates/educates-training-platform/client-programs/pkg/config" "github.com/educates/educates-training-platform/client-programs/pkg/resolver" ) type LocalResolverUpdateOptions struct { - Config string - Domain string + Config string + LocalConfig bool } func (o *LocalResolverUpdateOptions) Run() error { - var fullConfig *config.InstallationConfig - var err error = nil - - if o.Config != "" { - fullConfig, err = config.NewInstallationConfigFromFile(o.Config) - } else { - fullConfig, err = config.NewInstallationConfigFromUserFile() - } - + cfg, err := loadResolverInputs(o.Config, o.LocalConfig) if err != nil { return err } - - return resolver.UpdateResolver(fullConfig.ClusterIngress.Domain, fullConfig.LocalDNSResolver.TargetAddress, fullConfig.LocalDNSResolver.ExtraDomains) + return resolver.UpdateResolver(cfg.Ingress.Domain, cfg.Resolver.TargetAddress, cfg.Resolver.ExtraDomains) } func (p *ProjectInfo) NewLocalResolverUpdateCmd() *cobra.Command { var o LocalResolverUpdateOptions - var c = &cobra.Command{ + c := &cobra.Command{ Args: cobra.NoArgs, Use: "update", - Short: "Updates the local DNS resolver", + Short: "Updates the local DNS resolver (macOS)", RunE: func(_ *cobra.Command, _ []string) error { return o.Run() }, } - - c.Flags().StringVar( - &o.Config, - "config", - "", - "path to the installation config file for Educates", - ) - + c.Flags().StringVarP(&o.Config, "config", "c", "", "path to a CLI config file (any kind)") + c.Flags().BoolVar(&o.LocalConfig, "local-config", false, "use /config.yaml") + c.MarkFlagsMutuallyExclusive("config", "local-config") + c.MarkFlagsOneRequired("config", "local-config") return c } diff --git a/client-programs/pkg/cmd/local_secrets_add_ca_gen.go b/client-programs/pkg/cmd/local_secrets_add_ca_gen.go new file mode 100644 index 000000000..8c65ab726 --- /dev/null +++ b/client-programs/pkg/cmd/local_secrets_add_ca_gen.go @@ -0,0 +1,67 @@ +package cmd + +import ( + "crypto/rand" + "crypto/rsa" + "crypto/x509" + "crypto/x509/pkix" + "encoding/pem" + "fmt" + "math/big" + "time" +) + +// generateSelfSignedCA produces a fresh self-signed CA certificate + +// private key suitable for the EducatesLocalConfig laptop flow. +// cert-manager's CA-typed ClusterIssuer signs workshop certs from it. +// +// Choices: +// - RSA 2048 — broad cert-manager + browser compatibility, fast on +// a laptop, no transitive Go-toolchain concerns. +// - 10-year validity — laptops live longer than 1 year, expiry +// surprises are annoying, and the trust is scoped to one user's +// keychain so the wide window is acceptable. +// - CommonName + Organization carry "educates" so the cert is +// visually identifiable in browser cert UIs. +// - KeyUsageCertSign + IsCA + BasicConstraintsValid so cert-manager +// can sign downstream leaf certs. +func generateSelfSignedCA(commonName string) (certPEM, keyPEM []byte, err error) { + priv, err := rsa.GenerateKey(rand.Reader, 2048) + if err != nil { + return nil, nil, fmt.Errorf("generate RSA key: %w", err) + } + + serial, err := rand.Int(rand.Reader, new(big.Int).Lsh(big.NewInt(1), 128)) + if err != nil { + return nil, nil, fmt.Errorf("generate serial: %w", err) + } + + now := time.Now().UTC() + tmpl := &x509.Certificate{ + SerialNumber: serial, + Subject: pkix.Name{ + CommonName: commonName, + Organization: []string{"Educates"}, + }, + NotBefore: now.Add(-1 * time.Hour), + NotAfter: now.AddDate(10, 0, 0), + KeyUsage: x509.KeyUsageCertSign | x509.KeyUsageDigitalSignature, + BasicConstraintsValid: true, + IsCA: true, + } + + derBytes, err := x509.CreateCertificate(rand.Reader, tmpl, tmpl, &priv.PublicKey, priv) + if err != nil { + return nil, nil, fmt.Errorf("create certificate: %w", err) + } + + certPEM = pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: derBytes}) + + keyDER, err := x509.MarshalPKCS8PrivateKey(priv) + if err != nil { + return nil, nil, fmt.Errorf("marshal private key: %w", err) + } + keyPEM = pem.EncodeToMemory(&pem.Block{Type: "PRIVATE KEY", Bytes: keyDER}) + + return certPEM, keyPEM, nil +} diff --git a/client-programs/pkg/cmd/local_secrets_add_ca_test.go b/client-programs/pkg/cmd/local_secrets_add_ca_test.go new file mode 100644 index 000000000..9b5f057f2 --- /dev/null +++ b/client-programs/pkg/cmd/local_secrets_add_ca_test.go @@ -0,0 +1,116 @@ +package cmd + +import ( + "crypto/x509" + "encoding/base64" + "encoding/pem" + "os" + "path/filepath" + "strings" + "testing" + + "github.com/educates/educates-training-platform/client-programs/pkg/secrets" +) + +func TestLocalSecretsAddCa_AutoGen_LookupRoundTrip(t *testing.T) { + t.Setenv("EDUCATES_CLI_DATA_HOME", t.TempDir()) + + o := &LocalSecretsAddCaOptions{IngressDomain: "workshop.test"} + if err := o.Run("workshop.test-ca"); err != nil { + t.Fatalf("Run: %v", err) + } + + // The auto-generated cache file should be discoverable by the + // lookup function (the contract the translator depends on). + got := secrets.LocalCachedSecretForCertificateAuthority("workshop.test") + if got != "workshop.test-ca" { + t.Fatalf("LocalCachedSecretForCertificateAuthority = %q, want %q", got, "workshop.test-ca") + } +} + +func TestLocalSecretsAddCa_AutoGen_ProducesUsableCAPEMs(t *testing.T) { + dataHome := t.TempDir() + t.Setenv("EDUCATES_CLI_DATA_HOME", dataHome) + + o := &LocalSecretsAddCaOptions{IngressDomain: "workshop.test"} + if err := o.Run("workshop.test-ca"); err != nil { + t.Fatalf("Run: %v", err) + } + + body, err := os.ReadFile(filepath.Join(dataHome, "secrets", "workshop.test-ca.yaml")) + if err != nil { + t.Fatal(err) + } + s := string(body) + for _, want := range []string{ + "type: kubernetes.io/tls", + "tls.crt:", + "tls.key:", + "training.educates.dev/domain: workshop.test", + } { + if !strings.Contains(s, want) { + t.Errorf("cache file missing %q:\n%s", want, s) + } + } + + // Pull the base64-encoded PEMs out of the YAML and parse them. + certPEM := extractB64Value(t, s, "tls.crt:") + block, _ := pem.Decode(certPEM) + if block == nil { + t.Fatal("tls.crt: no PEM block decoded") + } + cert, err := x509.ParseCertificate(block.Bytes) + if err != nil { + t.Fatalf("ParseCertificate: %v", err) + } + if !cert.IsCA { + t.Error("cert.IsCA = false, want true (cert-manager requires CA bit set)") + } + if cert.KeyUsage&x509.KeyUsageCertSign == 0 { + t.Error("KeyUsageCertSign missing — cert-manager cannot sign with this CA") + } + + keyPEM := extractB64Value(t, s, "tls.key:") + keyBlock, _ := pem.Decode(keyPEM) + if keyBlock == nil { + t.Fatal("tls.key: no PEM block decoded") + } + if _, err := x509.ParsePKCS8PrivateKey(keyBlock.Bytes); err != nil { + t.Errorf("ParsePKCS8PrivateKey: %v", err) + } +} + +func TestLocalSecretsAddCa_PartialFlags_Errors(t *testing.T) { + t.Setenv("EDUCATES_CLI_DATA_HOME", t.TempDir()) + o := &LocalSecretsAddCaOptions{CertFile: "/nonexistent.crt", IngressDomain: "workshop.test"} + err := o.Run("workshop.test-ca") + if err == nil { + t.Fatal("expected error when only --cert is set without --key") + } + if !strings.Contains(err.Error(), "--cert and --key must be provided together") { + t.Errorf("error %q does not mention both-required rule", err) + } +} + +// extractB64Value finds ` ` in the YAML body and +// returns the decoded bytes. The k8s YAML marshaller writes base64 +// secret data as a single quoted scalar on one line, so a simple +// substring grab works. +func extractB64Value(t *testing.T, body, prefix string) []byte { + t.Helper() + idx := strings.Index(body, prefix) + if idx < 0 { + t.Fatalf("%q not found in YAML", prefix) + } + rest := body[idx+len(prefix):] + end := strings.IndexAny(rest, "\n") + if end < 0 { + end = len(rest) + } + val := strings.Trim(strings.TrimSpace(rest[:end]), `"'`) + decoded, err := base64.StdEncoding.DecodeString(val) + if err != nil { + t.Fatalf("base64 decode %q: %v", prefix, err) + } + return decoded +} diff --git a/client-programs/pkg/cmd/local_secrets_add_cmd.go b/client-programs/pkg/cmd/local_secrets_add_cmd.go index eadd56184..b7f7511d3 100644 --- a/client-programs/pkg/cmd/local_secrets_add_cmd.go +++ b/client-programs/pkg/cmd/local_secrets_add_cmd.go @@ -175,6 +175,7 @@ func (p *ProjectInfo) NewLocalSecretsAddTlsCmd() *cobra.Command { type LocalSecretsAddCaOptions struct { CertFile string + KeyFile string IngressDomain string } @@ -190,14 +191,43 @@ func (o *LocalSecretsAddCaOptions) Run(name string) error { return errors.New("invalid secret name") } - var certificateFileData []byte - - if o.CertFile != "" { - certificateFileData, err = os.ReadFile(o.CertFile) - + // v4 contract: a CA in the local cache is a *signing* CA. The + // CustomCA flow in EducatesLocalConfig hands it to cert-manager, + // which signs workshop certs from it — both tls.crt AND tls.key + // are required. Three input paths: + // + // 1. Both --cert and --key provided: load from disk. + // 2. Neither provided: generate a fresh RSA-2048 self-signed + // CA in-process. Convenient for laptop use; the only + // side-effect on disk is the cached Secret YAML below. + // 3. Only one provided: error (incomplete). + // + // Non-signing CA refs (cert only, for trust distribution) are no + // longer supported here. Use EducatesConfig if you need that. + var certPEM, keyPEM []byte + var generated bool + switch { + case o.CertFile != "" && o.KeyFile != "": + certPEM, err = os.ReadFile(o.CertFile) if err != nil { return errors.Wrapf(err, "failed to read certificate file %s", o.CertFile) } + keyPEM, err = os.ReadFile(o.KeyFile) + if err != nil { + return errors.Wrapf(err, "failed to read key file %s", o.KeyFile) + } + case o.CertFile == "" && o.KeyFile == "": + commonName := "educates-dev-ca" + if o.IngressDomain != "" { + commonName = "educates-dev-ca (" + o.IngressDomain + ")" + } + certPEM, keyPEM, err = generateSelfSignedCA(commonName) + if err != nil { + return errors.Wrap(err, "failed to generate self-signed CA") + } + generated = true + default: + return errors.New("--cert and --key must be provided together (or neither, to auto-generate a self-signed CA)") } secret := &apiv1.Secret{ @@ -205,9 +235,10 @@ func (o *LocalSecretsAddCaOptions) Run(name string) error { Name: name, Annotations: map[string]string{}, }, - // Type: "kubernetes.io/tls", + Type: apiv1.SecretTypeTLS, Data: map[string][]byte{ - "ca.crt": certificateFileData, + "tls.crt": certPEM, + "tls.key": keyPEM, }, } @@ -251,6 +282,19 @@ func (o *LocalSecretsAddCaOptions) Run(name string) error { return errors.Wrapf(err, "unable to close secret file %s", secretFilePath) } + if generated { + fmt.Printf(`Generated a self-signed CA %q and cached it locally. + +Browsers will not trust workshop URLs until this CA is imported into +your operating system trust store. Export the CA certificate with: + + educates local secrets export %s --pem > %s.pem + +then import the PEM file into your trust store. See the quick start +guide in the documentation for per-platform instructions. +`, name, name, name) + } + return nil } @@ -268,7 +312,13 @@ func (p *ProjectInfo) NewLocalSecretsAddCaCmd() *cobra.Command { &o.CertFile, "cert", "", - "path to PEM encoded CA certificate", + "path to PEM-encoded CA certificate (omit both --cert and --key to auto-generate a self-signed CA)", + ) + c.Flags().StringVar( + &o.KeyFile, + "key", + "", + "path to PEM-encoded CA private key (omit both --cert and --key to auto-generate)", ) c.Flags().StringVar( &o.IngressDomain, @@ -277,7 +327,7 @@ func (p *ProjectInfo) NewLocalSecretsAddCaCmd() *cobra.Command { "wildcard ingress domain matching certificate", ) - c.MarkFlagsRequiredTogether("cert") + c.MarkFlagsRequiredTogether("cert", "key") return c } @@ -351,15 +401,15 @@ func (o *LocalSecretsAddDockerRegistryOptions) Run(name string) error { secretFile, err := os.OpenFile(secretFilePath, os.O_RDWR|os.O_CREATE|os.O_TRUNC, os.ModePerm) if err != nil { - return errors.Wrapf(err, "unable to create secret file %s", secretFile) + return errors.Wrapf(err, "unable to create secret file %s", secretFilePath) } if _, err = secretFile.Write(secretData); err != nil { - return errors.Wrapf(err, "unable to write secret file %s", secretFile) + return errors.Wrapf(err, "unable to write secret file %s", secretFilePath) } if err := secretFile.Close(); err != nil { - return errors.Wrapf(err, "unable to close secret file %s", secretFile) + return errors.Wrapf(err, "unable to close secret file %s", secretFilePath) } return nil diff --git a/client-programs/pkg/cmd/local_secrets_export_cmd.go b/client-programs/pkg/cmd/local_secrets_export_cmd.go index a6f237265..8d94438ed 100644 --- a/client-programs/pkg/cmd/local_secrets_export_cmd.go +++ b/client-programs/pkg/cmd/local_secrets_export_cmd.go @@ -1,16 +1,21 @@ package cmd import ( + "fmt" "os" "path" "github.com/pkg/errors" "github.com/spf13/cobra" + apiv1 "k8s.io/api/core/v1" + "sigs.k8s.io/yaml" "github.com/educates/educates-training-platform/client-programs/pkg/utils" ) func (p *ProjectInfo) NewLocalSecretsExportCmd() *cobra.Command { + var pem bool + var c = &cobra.Command{ Args: cobra.ArbitraryArgs, Use: "export [NAME]", @@ -24,6 +29,14 @@ func (p *ProjectInfo) NewLocalSecretsExportCmd() *cobra.Command { return errors.Wrapf(err, "unable to create secrets cache directory") } + if pem { + if len(args) != 1 { + return errors.New("--pem requires exactly one secret name") + } + + return printSecretCertificatePEM(secretsCacheDir, args[0]) + } + err = utils.PrintYamlFilesInDir(secretsCacheDir, args) if err != nil { return errors.Wrapf(err, "unable to read secrets cache directory") @@ -33,5 +46,46 @@ func (p *ProjectInfo) NewLocalSecretsExportCmd() *cobra.Command { }, } + c.Flags().BoolVar( + &pem, + "pem", + false, + "print the secret's certificate as PEM (for importing a CA into a trust store)", + ) + return c } + +// printSecretCertificatePEM writes the certificate of a cached TLS/CA +// secret to stdout as PEM, so it can be redirected to a file and +// imported into an operating system trust store. The private key is +// never printed. +func printSecretCertificatePEM(secretsCacheDir string, name string) error { + secretFilePath := path.Join(secretsCacheDir, name+".yaml") + + secretData, err := os.ReadFile(secretFilePath) + + if err != nil { + if os.IsNotExist(err) { + return errors.Errorf("no secret named %q in the local secrets cache", name) + } + + return errors.Wrapf(err, "unable to read secret file %s", secretFilePath) + } + + var secret apiv1.Secret + + if err := yaml.Unmarshal(secretData, &secret); err != nil { + return errors.Wrapf(err, "unable to parse secret file %s", secretFilePath) + } + + certificate, exists := secret.Data["tls.crt"] + + if !exists || len(certificate) == 0 { + return errors.Errorf("secret %q does not contain a certificate", name) + } + + fmt.Print(string(certificate)) + + return nil +} diff --git a/client-programs/pkg/cmd/local_secrets_import_cmd.go b/client-programs/pkg/cmd/local_secrets_import_cmd.go index e42a0d4b6..037f7d4e1 100644 --- a/client-programs/pkg/cmd/local_secrets_import_cmd.go +++ b/client-programs/pkg/cmd/local_secrets_import_cmd.go @@ -44,7 +44,7 @@ func (o *LocalSecretsImportOptions) Run() error { err = runtime.DecodeInto(decoder, []byte(yamlData), secretObj) if err != nil { - return errors.Wrapf(err, "unable to decode secret %q", i) + return errors.Wrapf(err, "unable to decode secret #%d", i) } // Make sure that the namespace is cleared. diff --git a/client-programs/pkg/config/datahome.go b/client-programs/pkg/config/datahome.go new file mode 100644 index 000000000..ceddd55f0 --- /dev/null +++ b/client-programs/pkg/config/datahome.go @@ -0,0 +1,96 @@ +package config + +import ( + "fmt" + "os" + "path/filepath" +) + +// EnsureLocalConfigFile is the single entry point for commands that +// read /config.yaml. It composes the v3-to-v4 migration +// shim with the user-actionable missing-file diagnostic: +// +// - config.yaml exists → return nil (proceed to Load). +// - config.yaml missing → attempt v3 → v4 migration. If the v3 +// migration writes a fresh config.yaml, return nil. If migration +// refuses (provider isn't laptop-kind), surface that error. +// - config.yaml still missing after migration attempt → return +// MissingLocalConfigError (first-time user / partial init). +func EnsureLocalConfigFile(dataHome string) error { + configPath := filepath.Join(dataHome, "config.yaml") + if _, err := os.Stat(configPath); err == nil { + return nil + } + if err := MaybeMigrateV3(dataHome); err != nil { + return err + } + if _, err := os.Stat(configPath); err == nil { + return nil + } + return MissingLocalConfigError(dataHome) +} + +// MissingLocalConfigError diagnoses why /config.yaml is missing +// and returns a user-actionable error. Three cases: +// +// 1. v3 `values.yaml` exists alongside the missing config.yaml — the user +// is on a pre-v4 data home and needs the migration shim (planned step 10 +// of the phase 5 implementation; not yet landed). +// 2. The data home directory itself doesn't exist — first-time user. +// 3. The directory exists but config.yaml is missing — initialised data +// home (e.g. secrets/ present from past CLI runs) but no v4 config yet. +// +// Returns nil if the data home looks healthy and config.yaml is present; +// callers should not invoke this in that case (the loader handles it). +func MissingLocalConfigError(dataHome string) error { + configPath := filepath.Join(dataHome, "config.yaml") + if _, err := os.Stat(configPath); err == nil { + // Caller misuse — config.yaml does exist. Surface a generic + // message so the bug is visible. + return fmt.Errorf("internal: MissingLocalConfigError called but %s exists", configPath) + } + + v3Values := filepath.Join(dataHome, "values.yaml") + if _, err := os.Stat(v3Values); err == nil { + // EnsureLocalConfigFile would normally have triggered + // MaybeMigrateV3 before reaching this branch; landing here + // means migration refused (non-laptop provider) and the user + // retried without reading that error. Re-state the path + // forward briefly. + return fmt.Errorf(`no v4 config found at %s, but a v3-style values.yaml is present at %s. + +The migration shim only translates laptop-kind installs +(clusterInfrastructure.provider empty or "kind"). Other providers +need a fresh v4 config declared explicitly: + + educates admin platform render --config + +The available v4 kinds live under cli.educates.dev/v1alpha1 +(EducatesLocalConfig, EducatesConfig escape hatch, and the +scenario kinds GKE/EKS/Inline landing in phase 5 step 11).`, + configPath, v3Values) + } + + if _, err := os.Stat(dataHome); os.IsNotExist(err) { + return fmt.Errorf(`no Educates data home found at %s. + +First-time setup: write a minimal config and re-run. + + educates local config init + +Or, with --config , point at any v4 config file: + + educates admin platform render --config `, dataHome) + } + + return fmt.Errorf(`no v4 config found at %s. + +The data home directory exists but config.yaml is missing. Write a +minimal config and re-run: + + educates local config init + +Or point at an explicit v4 config: + + educates admin platform render --config `, configPath) +} diff --git a/client-programs/pkg/config/datahome_test.go b/client-programs/pkg/config/datahome_test.go new file mode 100644 index 000000000..f3cfd8b8d --- /dev/null +++ b/client-programs/pkg/config/datahome_test.go @@ -0,0 +1,77 @@ +package config + +import ( + "os" + "path/filepath" + "strings" + "testing" +) + +func TestMissingLocalConfigError_V3ValuesPresent(t *testing.T) { + dir := t.TempDir() + if err := os.WriteFile(filepath.Join(dir, "values.yaml"), []byte("clusterInfrastructure:\n provider: kind\n"), 0o644); err != nil { + t.Fatal(err) + } + + err := MissingLocalConfigError(dir) + if err == nil { + t.Fatal("expected error") + } + s := err.Error() + for _, want := range []string{"v3-style values.yaml", "migration shim", "EducatesLocalConfig"} { + if !strings.Contains(s, want) { + t.Errorf("error missing hint %q in:\n%s", want, s) + } + } +} + +func TestMissingLocalConfigError_FirstTimeUser(t *testing.T) { + // Point at a path that does NOT exist. + dir := filepath.Join(t.TempDir(), "does-not-exist") + + err := MissingLocalConfigError(dir) + if err == nil { + t.Fatal("expected error") + } + s := err.Error() + for _, want := range []string{"no Educates data home found", "First-time setup", "local config init"} { + if !strings.Contains(s, want) { + t.Errorf("error missing hint %q in:\n%s", want, s) + } + } +} + +func TestMissingLocalConfigError_DirExistsConfigMissing(t *testing.T) { + dir := t.TempDir() + // Drop a sibling subdir to look like a partially-used data home. + if err := os.MkdirAll(filepath.Join(dir, "secrets"), 0o755); err != nil { + t.Fatal(err) + } + + err := MissingLocalConfigError(dir) + if err == nil { + t.Fatal("expected error") + } + s := err.Error() + for _, want := range []string{"data home directory exists but config.yaml is missing", "local config init"} { + if !strings.Contains(s, want) { + t.Errorf("error missing hint %q in:\n%s", want, s) + } + } + if strings.Contains(s, "v3-style values.yaml") { + t.Errorf("should not mention v3 migration when no values.yaml present:\n%s", s) + } +} + +func TestMissingLocalConfigError_ConfigExists_InternalError(t *testing.T) { + // Caller misuse: config.yaml is present, so this function should not + // have been called. Surface a detectable error. + dir := t.TempDir() + if err := os.WriteFile(filepath.Join(dir, "config.yaml"), []byte(""), 0o644); err != nil { + t.Fatal(err) + } + err := MissingLocalConfigError(dir) + if err == nil || !strings.Contains(err.Error(), "internal") { + t.Errorf("expected 'internal:' error for misuse, got %v", err) + } +} diff --git a/client-programs/pkg/config/host.go b/client-programs/pkg/config/host.go deleted file mode 100644 index 49fc6001e..000000000 --- a/client-programs/pkg/config/host.go +++ /dev/null @@ -1,55 +0,0 @@ -package config - -import ( - "fmt" - "net" - - "github.com/pkg/errors" -) - -func HostIP() (string, error) { - ifaces, err := net.Interfaces() - if err != nil { - return "", err - } - for _, iface := range ifaces { - if iface.Flags&net.FlagUp == 0 { - continue - } - if iface.Flags&net.FlagLoopback != 0 { - continue - } - addrs, err := iface.Addrs() - if err != nil { - return "", err - } - for _, addr := range addrs { - var ip net.IP - switch v := addr.(type) { - case *net.IPNet: - ip = v.IP - case *net.IPAddr: - ip = v.IP - } - if ip == nil || ip.IsLoopback() { - continue - } - ip = ip.To4() - if ip == nil { - continue - } - return ip.String(), nil - } - } - return "", errors.New("are you connected to the network?") -} - -func GetHostIpAsDns() string { - localIPAddress, err := HostIP() - - if err != nil { - localIPAddress = "127.0.0.1" - } - - return fmt.Sprintf("%s.nip.io", localIPAddress) -} diff --git a/client-programs/pkg/config/hostinfo/hostinfo.go b/client-programs/pkg/config/hostinfo/hostinfo.go new file mode 100644 index 000000000..9d33f955b --- /dev/null +++ b/client-programs/pkg/config/hostinfo/hostinfo.go @@ -0,0 +1,41 @@ +// Package hostinfo derives runtime host information used by laptop-mode +// CLI defaulting (e.g. host IP → nip.io fallback for ingress.domain). +// +// Kept separate from the translator so the translator stays deterministic +// and unit-testable: anything host-derived flows in via call sites that +// explicitly fetch it. +package hostinfo + +import ( + "fmt" + "net" + "strings" +) + +// DetectHostIP returns the IPv4 address that would be used as the source +// when reaching the outside world. The UDP "fake dial" trick: opening a +// UDP socket toward a routable address makes the OS populate the local +// address with the route's source IP, without sending any packet. +// +// This deliberately does NOT use net.InterfaceAddrs(): on a typical laptop +// that returns five-plus addresses (loopback, multiple interfaces, IPv6 +// link-locals) and we'd guess at which one is reachable from a workshop +// container running in kind. +func DetectHostIP() (string, error) { + conn, err := net.Dial("udp", "8.8.8.8:80") + if err != nil { + return "", fmt.Errorf("detect host IP: %w", err) + } + defer conn.Close() + local := conn.LocalAddr().(*net.UDPAddr) + return local.IP.String(), nil +} + +// NipDomain converts a dotted-quad IPv4 (e.g. 192.168.1.10) into the +// nip.io wildcard subdomain shape (192-168-1-10.nip.io). nip.io serves +// both `1-2-3-4.nip.io` and `1.2.3.4.nip.io`; the dash form survives +// Kubernetes' DNS label length / character restrictions when subdomains +// are prepended (e.g. workshop names). +func NipDomain(ip string) string { + return strings.ReplaceAll(ip, ".", "-") + ".nip.io" +} diff --git a/client-programs/pkg/config/installationconfig.go b/client-programs/pkg/config/installationconfig.go deleted file mode 100644 index f64d7fea6..000000000 --- a/client-programs/pkg/config/installationconfig.go +++ /dev/null @@ -1,504 +0,0 @@ -package config - -import ( - "os" - "path" - - "github.com/educates/educates-training-platform/client-programs/pkg/secrets" - "github.com/educates/educates-training-platform/client-programs/pkg/utils" - "github.com/pkg/errors" - "gopkg.in/yaml.v2" -) - -type VolumeMountConfig struct { - HostPath string `yaml:"hostPath"` - ContainerPath string `yaml:"containerPath"` - ReadOnly *bool `yaml:"readOnly,omitempty"` -} - -type LocalKindClusterConfig struct { - ListenAddress string `yaml:"listenAddress,omitempty"` - ApiServer KindApiServerConfig `yaml:"apiServer,omitempty"` - Networking KindNetworkingConfig `yaml:"networking,omitempty"` - VolumeMounts []VolumeMountConfig `yaml:"volumeMounts,omitempty"` - RegistryMirrors []RegistryMirrorConfig `yaml:"registryMirrors,omitempty"` -} - -type RegistryMirrorConfig struct { - Mirror string `yaml:"mirror"` - URL string `yaml:"url,omitempty"` - Username string `yaml:"username,omitempty"` - Password string `yaml:"password,omitempty"` - Port string `yaml:"port,omitempty"` - BindIP string `yaml:"bindIP,omitempty"` -} - -type KindApiServerConfig struct { - Address string `yaml:"address,omitempty"` - Port int `yaml:"port,omitempty"` -} - -type KindNetworkingConfig struct { - ServiceSubnet string `yaml:"serviceSubnet,omitempty"` - PodSubnet string `yaml:"podSubnet,omitempty"` -} - -type LocalDNSResolverConfig struct { - TargetAddress string `yaml:"targetAddress,omitempty"` - ExtraDomains []string `yaml:"extraDomains,omitempty"` -} - -type AwsClusterInfrastructureIRSARolesConfig struct { - ExternalDns string `yaml:"external-dns"` - CertManager string `yaml:"cert-manager"` -} - -type AwsClusterInfrastructureConfig struct { - AwsId string `yaml:"awsId,omitempty"` - Region string `yaml:"region"` - Route53Zone Route53ZoneConfig `yaml:"route53,omitempty"` - ClusterName string `yaml:"clusterName,omitempty"` - IRSARoles AwsClusterInfrastructureIRSARolesConfig `yaml:"irsaRoles,omitempty"` -} - -type Route53ZoneConfig struct { - HostedZoneId string `yaml:"hostedZone"` -} - -type GcpClusterInfrastructureWorkloadIdentitiesConfig struct { - ExternalDns string `yaml:"external-dns"` - CertManager string `yaml:"cert-manager"` -} - -type CloudDNSConfig struct { - Zone string `yaml:"zone,omitempty"` -} - -type GcpClusterInfrastructureConfig struct { - Project string `yaml:"project,omitempty"` - CloudDNS CloudDNSConfig `yaml:"cloudDNS,omitempty"` - IRSARoles GcpClusterInfrastructureWorkloadIdentitiesConfig `yaml:"workloadIdentity,omitempty"` -} - -type ClusterInfrastructureConfig struct { - // This can be only "kind", "eks", "gke" "custom" for now - Provider string `yaml:"provider"` - AWS AwsClusterInfrastructureConfig `yaml:"aws,omitempty"` - GCP GcpClusterInfrastructureConfig `yaml:"gcp,omitempty"` - CertificateRef CACertificateRefConfig `yaml:"caCertificateRef,omitempty"` -} - -type PackageConfig struct { - Enabled *bool `yaml:"enabled,omitempty"` - Settings map[string]interface{} `yaml:"settings"` -} - -type ClusterPackagesConfig struct { - Contour PackageConfig `yaml:"contour,omitempty"` - CertManager PackageConfig `yaml:"cert-manager,omitempty"` - ExternalDns PackageConfig `yaml:"external-dns,omitempty"` - Certs PackageConfig `yaml:"certs,omitempty"` - Kyverno PackageConfig `yaml:"kyverno,omitempty"` - KappController PackageConfig `yaml:"kapp-controller,omitempty"` - Educates PackageConfig `yaml:"educates,omitempty"` -} - -type TLSCertificateConfig struct { - Certificate string `yaml:"tls.crt"` - PrivateKey string `yaml:"tls.key"` -} - -type TLSCertificateRefConfig struct { - Namespace string `yaml:"namespace"` - Name string `yaml:"name"` -} - -type CACertificateConfig struct { - Certificate string `yaml:"ca.crt"` -} - -type CACertificateRefConfig struct { - Namespace string `yaml:"namespace"` - Name string `yaml:"name"` -} - -type CANodeInjectorConfig struct { - Enabled *bool `yaml:"enabled"` -} - -type ClusterRuntimeConfig struct { - Class string `yaml:"class,omitempty"` -} - -type ClusterIngressConfig struct { - Domain string `yaml:"domain"` - Class string `yaml:"class,omitempty"` - Protocol string `yaml:"protocol,omitempty"` - TLSCertificate TLSCertificateConfig `yaml:"tlsCertificate,omitempty"` - TLSCertificateRef TLSCertificateRefConfig `yaml:"tlsCertificateRef,omitempty"` - CACertificate CACertificateConfig `yaml:"caCertificate,omitempty"` - CACertificateRef CACertificateRefConfig `yaml:"caCertificateRef,omitempty"` - CANodeInjector CANodeInjectorConfig `yaml:"caNodeInjector,omitempty"` -} - -type SessionCookiesConfig struct { - Domain string `yaml:"domain,omitempty"` -} - -type ClusterStorageConfig struct { - Class string `yaml:"class,omitempty"` - User int `yaml:"user,omitempty"` - Group int `yaml:"group,omitempty"` -} - -type ClusterSecurityConfig struct { - PolicyEngine string `yaml:"policyEngine"` -} - -type PullSecretRefConfig struct { - Namespace string `yaml:"namespace"` - Name string `yaml:"name"` -} - -type ClusterSecretsConfig struct { - PullSecretRefs []PullSecretRefConfig `yaml:"pullSecretRefs"` -} - -type SessionManagerConfig struct { - ClusterAdmin bool `yaml:"clusterAdmin,omitempty"` -} - -type UserCredentialsConfig struct { - Username string `yaml:"username"` - Password string `yaml:"password"` -} - -type TrainingPortalCredentialsConfig struct { - Admin UserCredentialsConfig `yaml:"admin,omitempty"` - Robot UserCredentialsConfig `yaml:"robot,omitempty"` -} - -type UserClientConfig struct { - Id string `yaml:"id"` - Secret string `yaml:"secret"` -} - -type TrainingPortalClientsConfig struct { - Robot UserClientConfig `yaml:"robot,omitempty"` -} - -type TrainingPortalConfig struct { - Credentials TrainingPortalCredentialsConfig `yaml:"credentials,omitempty"` - Clients TrainingPortalClientsConfig `yaml:"clients,omitempty"` -} - -type WorkshopSecurityConfig struct { - RulesEngine string `yaml:"rulesEngine"` -} - -type ImageRegistryConfig struct { - Host string `yaml:"host"` - Namespace string `yaml:"namespace"` -} - -type ImageVersionConfig struct { - Name string `yaml:"name"` - Image string `yaml:"image"` -} - -type ProxyCacheConfig struct { - RemoteURL string `yaml:"remoteURL"` - Username string `yaml:"username,omitempty"` - Password string `yaml:"password,omitempty"` -} -type DockerDaemonConfig struct { - NetworkMTU int `yaml:"networkMTU,omitempty"` - Rootless *bool `yaml:"rootless,omitempty"` - Privileged *bool `yaml:"privileged,omitempty"` - ProxyCache ProxyCacheConfig `yaml:"proxyCache,omitempty"` -} - -type ClusterNetworkConfig struct { - BlockCIDRs []string `yaml:"blockCIDRs"` -} - -type GoogleAnayticsConfig struct { - TrackingId string `yaml:"trackingId"` -} - -type ClarityAnayticsConfig struct { - TrackingId string `yaml:"trackingId"` -} - -type AmplitudeAnayticsConfig struct { - TrackingId string `yaml:"trackingId"` -} - -type WebhookAnalyticsConfig struct { - URL string `yaml:"url"` -} - -type WorkshopAnalyticsConfig struct { - Google GoogleAnayticsConfig `yaml:"google,omitempty"` - Clarity ClarityAnayticsConfig `yaml:"clarity,omitempty"` - Amplitude AmplitudeAnayticsConfig `yaml:"amplitude,omitempty"` - Webhook WebhookAnalyticsConfig `yaml:"webhook,omitempty"` -} - -type WebsiteStyleOverridesConfig struct { - Html string `yaml:"html"` - Script string `yaml:"script"` - Style string `yaml:"style"` -} - -type WebsiteHTMLSnippetConfig struct { - HTML string `yaml:"html"` -} - -type ThemeDataRefConfig struct { - Namespace string `yaml:"namespace"` - Name string `yaml:"name"` -} - -type WebsiteStylingConfig struct { - WorkshopDashboard WebsiteStyleOverridesConfig `yaml:"workshopDashboard,omitempty"` - WorkshopInstructions WebsiteStyleOverridesConfig `yaml:"workshopInstructions,omitempty"` - TrainingPortal WebsiteStyleOverridesConfig `yaml:"trainingPortal,omitempty"` - WorkshopStarted WebsiteHTMLSnippetConfig `yaml:"workshopStarted,omitempty"` - WorkshopFinished WebsiteHTMLSnippetConfig `yaml:"workshopFinished,omitempty"` - DefaultTheme string `yaml:"defaultTheme,omitempty"` - ThemeDataRefs []ThemeDataRefConfig `yaml:"themeDataRefs,omitempty"` - FrameAncestors []string `yaml:"frameAncestors,omitempty"` -} - -type ImagePullerConfig struct { - Enabled *bool `yaml:"enabled"` - PrePullImages []string `yaml:"prePullImages,omitempty"` -} - -type LookupServiceConfig struct { - Enabled *bool `yaml:"enabled"` - IngressPrefix string `yaml:"ingressPrefix,omitempty"` -} - -type ClusterEssentialsConfig struct { - ClusterInfrastructure ClusterInfrastructureConfig `yaml:"clusterInfrastructure,omitempty"` - ClusterPackages ClusterPackagesConfig `yaml:"clusterPackages,omitempty"` - ClusterSecurity ClusterSecurityConfig `yaml:"clusterSecurity,omitempty"` -} - -type TrainingPlatformConfig struct { - ClusterSecurity ClusterSecurityConfig `yaml:"clusterSecurity,omitempty"` - ClusterRuntime ClusterRuntimeConfig `yaml:"clusterRuntime,omitempty"` - ClusterIngress ClusterIngressConfig `yaml:"clusterIngress,omitempty"` - SessionCookies SessionCookiesConfig `yaml:"sessionCookies,omitempty"` - ClusterStorage ClusterStorageConfig `yaml:"clusterStorage,omitempty"` - ClusterSecrets ClusterSecretsConfig `yaml:"clusterSecrets,omitempty"` - TrainingPortal TrainingPortalConfig `yaml:"trainingPortal,omitempty"` - WorkshopSecurity WorkshopSecurityConfig `yaml:"workshopSecurity,omitempty"` - SessionManager SessionManagerConfig `yaml:"sessionManager,omitempty"` - ImageRegistry ImageRegistryConfig `yaml:"imageRegistry,omitempty"` - Version string `yaml:"version,omitempty"` - ImageVersions []ImageVersionConfig `yaml:"imageVersions,omitempty"` - DockerDaemon DockerDaemonConfig `yaml:"dockerDaemon,omitempty"` - ClusterNetwork ClusterNetworkConfig `yaml:"clusterNetwork,omitempty"` - WorkshopAnalytics WorkshopAnalyticsConfig `yaml:"workshopAnalytics,omitempty"` - WebsiteStyling WebsiteStylingConfig `yaml:"websiteStyling,omitempty"` - ImagePuller ImagePullerConfig `yaml:"imagePuller,omitempty"` - LookupService LookupServiceConfig `yaml:"lookupService,omitempty"` -} - -type InstallationConfig struct { - Debug *bool `yaml:"debug,omitempty"` - LocalKindCluster LocalKindClusterConfig `yaml:"localKindCluster,omitempty"` - LocalDNSResolver LocalDNSResolverConfig `yaml:"localDNSResolver,omitempty"` - ClusterInfrastructure ClusterInfrastructureConfig `yaml:"clusterInfrastructure,omitempty"` - ClusterPackages ClusterPackagesConfig `yaml:"clusterPackages,omitempty"` - ClusterSecurity ClusterSecurityConfig `yaml:"clusterSecurity,omitempty"` - ClusterRuntime ClusterRuntimeConfig `yaml:"clusterRuntime,omitempty"` - ClusterIngress ClusterIngressConfig `yaml:"clusterIngress,omitempty"` - SessionCookies SessionCookiesConfig `yaml:"sessionCookies,omitempty"` - ClusterStorage ClusterStorageConfig `yaml:"clusterStorage,omitempty"` - ClusterSecrets ClusterSecretsConfig `yaml:"clusterSecrets,omitempty"` - SessionManager SessionManagerConfig `yaml:"sessionManager,omitempty"` - TrainingPortal TrainingPortalConfig `yaml:"trainingPortal,omitempty"` - WorkshopSecurity WorkshopSecurityConfig `yaml:"workshopSecurity,omitempty"` - ImageRegistry ImageRegistryConfig `yaml:"imageRegistry,omitempty"` - Version string `yaml:"version,omitempty"` - ImageVersions []ImageVersionConfig `yaml:"imageVersions,omitempty"` - DockerDaemon DockerDaemonConfig `yaml:"dockerDaemon,omitempty"` - ClusterNetwork ClusterNetworkConfig `yaml:"clusterNetwork,omitempty"` - WorkshopAnalytics WorkshopAnalyticsConfig `yaml:"workshopAnalytics,omitempty"` - WebsiteStyling WebsiteStylingConfig `yaml:"websiteStyling,omitempty"` - ImagePuller ImagePullerConfig `yaml:"imagePuller,omitempty"` - LookupService LookupServiceConfig `yaml:"lookupService,omitempty"` -} - -type EducatesDomainStruct struct { - ClusterIngress ClusterIngressConfig `yaml:"clusterIngress,omitempty"` -} - -const NULL_CONFIG_FILE = "NULL" - -func NewDefaultInstallationConfig() *InstallationConfig { - return &InstallationConfig{ - ClusterInfrastructure: ClusterInfrastructureConfig{ - Provider: "", - }, - ClusterPackages: ClusterPackagesConfig{ - Contour: PackageConfig{ - Enabled: utils.BoolPointer(true), - }, - Kyverno: PackageConfig{ - Enabled: utils.BoolPointer(true), - }, - Educates: PackageConfig{ - Enabled: utils.BoolPointer(true), - }, - }, - ClusterSecurity: ClusterSecurityConfig{ - PolicyEngine: "kyverno", - }, - ClusterIngress: ClusterIngressConfig{ - Domain: GetHostIpAsDns(), - }, - WorkshopSecurity: WorkshopSecurityConfig{ - RulesEngine: "kyverno", - }, - } -} - -func NewInstallationConfigFromUserFile() (*InstallationConfig, error) { - config := &InstallationConfig{} - - valuesFile := path.Join(utils.GetEducatesHomeDir(), "values.yaml") - - data, err := os.ReadFile(valuesFile) - - if err == nil && len(data) != 0 { - if err := yaml.UnmarshalStrict(data, &config); err != nil { - return nil, errors.Wrapf(err, "unable to parse default config file %s", valuesFile) - } - } else { - config = NewDefaultInstallationConfig() - } - - return config, nil -} - -func NewInstallationConfigFromFile(configFile string) (*InstallationConfig, error) { - config := &InstallationConfig{} - - data, err := os.ReadFile(configFile) - - if err != nil { - return nil, errors.Wrapf(err, "failed to read installation config file %s", configFile) - } - - if err := yaml.UnmarshalStrict(data, &config); err != nil { - return nil, errors.Wrapf(err, "unable to parse installation config file %s", configFile) - } - - return config, nil -} - -func ConfigForLocalClusters(configFile string, domain string, local bool) (fullConfig *InstallationConfig, err error) { - if configFile == NULL_CONFIG_FILE { - fullConfig = NewDefaultInstallationConfig() - } else if configFile != "" { - fullConfig, err = NewInstallationConfigFromFile(configFile) - } else { - fullConfig, err = NewInstallationConfigFromUserFile() - } - - if err != nil { - return nil, err - } - - if local { - if fullConfig.ClusterInfrastructure.Provider != "" && - fullConfig.ClusterInfrastructure.Provider != "kind" && - fullConfig.ClusterInfrastructure.Provider != "custom" { - return nil, errors.New("Only kind or custom providers are supported for local clusters. If not provided, will default to kind") - } - - if fullConfig.ClusterInfrastructure.Provider == "" { - fullConfig.ClusterInfrastructure.Provider = "kind" - } - } - - if domain != "" { - fullConfig.ClusterIngress.Domain = domain - } - - // We do resolve domain configuration precedence here - fullConfig.ClusterIngress.Domain = EducatesDomain(fullConfig) - - if local { - // This augments the installation config with the secrets that are cached locally - if secretName := secrets.LocalCachedSecretForIngressDomain(fullConfig.ClusterIngress.Domain); secretName != "" { - fullConfig.ClusterIngress.TLSCertificateRef.Namespace = "educates-secrets" - fullConfig.ClusterIngress.TLSCertificateRef.Name = secretName - } - - if secretName := secrets.LocalCachedSecretForCertificateAuthority(fullConfig.ClusterIngress.Domain); secretName != "" { - fullConfig.ClusterIngress.CACertificateRef.Namespace = "educates-secrets" - fullConfig.ClusterIngress.CACertificateRef.Name = secretName - } - } - - if err := ValidateProvider(fullConfig.ClusterInfrastructure.Provider); err != nil { - return nil, err - } - - return fullConfig, nil -} - -/** - * This function will return the configured educates Domain in the following order: - * 1. If the domain is set in the installation config, it will return that - * 2. If the domain is set in the Educates Package, it will return that - * 4. If none of the above are set, it will return the host IP as a DNS - */ -func EducatesDomain(config *InstallationConfig) string { - if config.ClusterIngress.Domain != "" { - return config.ClusterIngress.Domain - } - // Access config.ClusterPackages.Educates.Settings["ClusterConfig"] and see if there's a value - if educatesDomain, ok := config.ClusterPackages.Educates.Settings["clusterIngress"]; ok { - // Access educatesDomain.(map[string]interface{})["domain"] and return that - p := map[string]interface{}{} - if educatesDomainBytes, err := yaml.Marshal(educatesDomain); err == nil { - yaml.Unmarshal(educatesDomainBytes, &p) - if domain, ok := p["domain"].(string); ok { - return domain - } - } - } - return GetHostIpAsDns() -} - -func PrintConfigToStdout(config *InstallationConfig) error { - data, err := yaml.Marshal(config) - - if err != nil { - return errors.Wrap(err, "failed to marshal installation config") - } - - // fmt.Println("Configuration to be applied:") - // fmt.Println("-------------------------------") - // fmt.Println(string(data)) - os.Stdout.Write(data) - // fmt.Println("###############################") - - return nil -} - -func ValidateProvider(provider string) error { - switch provider { - case "eks", "kind", "gke", "custom", "vcluster", "generic", "minikube", "openshift": - return nil - default: - return errors.New("Invalid ClusterInsfrastructure Provider. Valid values are (eks, gke, kind, custom, vcluster, generic, minikube, openshift)") - } -} diff --git a/client-programs/pkg/config/loader.go b/client-programs/pkg/config/loader.go new file mode 100644 index 000000000..49c3d10e8 --- /dev/null +++ b/client-programs/pkg/config/loader.go @@ -0,0 +1,181 @@ +package config + +import ( + "bytes" + "encoding/json" + "fmt" + "os" + "strings" + + "github.com/educates/educates-training-platform/client-programs/pkg/config/v1alpha1" + "github.com/educates/educates-training-platform/client-programs/pkg/config/v1alpha1/schemas" + "github.com/xeipuuv/gojsonschema" + "gopkg.in/yaml.v2" +) + +// Load reads a CLI config file, validates its apiVersion/kind, runs JSON +// schema validation, then strict-unmarshals into the typed struct. The +// returned value implements v1alpha1.Config; callers type-switch to the +// concrete kind. +func Load(path string) (v1alpha1.Config, error) { + data, err := os.ReadFile(path) + if err != nil { + return nil, fmt.Errorf("read %s: %w", path, err) + } + return LoadBytes(data, path) +} + +// LoadBytes is the path-free variant — useful for stdin and tests. The +// source string is woven into error messages so users can locate the file. +// +// Single-pass: one yaml.Unmarshal → normalise → json.Marshal. The JSON +// bytes drive both schema validation and the typed strict decode (via +// json.Decoder.DisallowUnknownFields, which is the json equivalent of +// yaml.UnmarshalStrict's behaviour around unknown fields). +func LoadBytes(data []byte, source string) (v1alpha1.Config, error) { + jsonData, raw, err := yamlToJSON(data, source) + if err != nil { + return nil, err + } + apiVersion, _ := raw["apiVersion"].(string) + kind, _ := raw["kind"].(string) + if apiVersion == "" || kind == "" { + return nil, fmt.Errorf("%s: missing required field 'apiVersion' or 'kind'", source) + } + if apiVersion != v1alpha1.APIVersion { + return nil, fmt.Errorf("%s: unsupported apiVersion %q (want %q)", source, apiVersion, v1alpha1.APIVersion) + } + + switch kind { + case v1alpha1.KindEducatesLocalConfig: + return decodeAndDefault(jsonData, schemas.EducatesLocalConfig, source, &v1alpha1.EducatesLocalConfig{}, true) + case v1alpha1.KindEducatesConfig: + // Escape-hatch: CR-spec fields are untyped maps; don't reject + // unknown fields inside them (the typed struct only declares + // the envelope; the CR specs are map[string]interface{} that + // json's strict mode would happily accept any keys for anyway). + return decodeAndDefault(jsonData, schemas.EducatesConfig, source, &v1alpha1.EducatesConfig{}, false) + case v1alpha1.KindEducatesInlineConfig: + return decodeAndDefault(jsonData, schemas.EducatesInlineConfig, source, &v1alpha1.EducatesInlineConfig{}, true) + case v1alpha1.KindEducatesGKEConfig: + return decodeAndDefault(jsonData, schemas.EducatesGKEConfig, source, &v1alpha1.EducatesGKEConfig{}, true) + case v1alpha1.KindEducatesEKSConfig: + return decodeAndDefault(jsonData, schemas.EducatesEKSConfig, source, &v1alpha1.EducatesEKSConfig{}, true) + default: + return nil, fmt.Errorf("%s: unknown kind %q for apiVersion %q", source, kind, apiVersion) + } +} + +// LoadLocal is the typed convenience wrapper for callers that only accept +// EducatesLocalConfig (e.g. `educates local config *` commands). +func LoadLocal(path string) (*v1alpha1.EducatesLocalConfig, error) { + cfg, err := Load(path) + if err != nil { + return nil, err + } + local, ok := cfg.(*v1alpha1.EducatesLocalConfig) + if !ok { + return nil, fmt.Errorf("%s: expected kind %q, got %q", + path, v1alpha1.KindEducatesLocalConfig, cfg.GetKind()) + } + return local, nil +} + +// yamlToJSON parses YAML once, normalises yaml.v2's +// map[interface{}]interface{} to map[string]interface{}, then marshals +// to JSON. Returns both the normalised top-level map (for cheap +// apiVersion/kind extraction) and the JSON bytes (for schema +// validation + typed decode). +func yamlToJSON(data []byte, source string) ([]byte, map[string]interface{}, error) { + var raw interface{} + if err := yaml.Unmarshal(data, &raw); err != nil { + return nil, nil, fmt.Errorf("%s: parse YAML: %w", source, err) + } + normalised := normaliseForJSON(raw) + rootMap, _ := normalised.(map[string]interface{}) + if rootMap == nil { + // Empty document or scalar root — keep going; downstream + // schema/decode steps will produce the actionable error. + rootMap = map[string]interface{}{} + } + jsonBytes, err := json.Marshal(normalised) + if err != nil { + return nil, nil, fmt.Errorf("%s: marshal to JSON: %w", source, err) + } + return jsonBytes, rootMap, nil +} + +// decodeAndDefault validates jsonData against schemaBytes, strict-decodes +// (or loose for the escape kind which holds untyped maps), then applies +// any per-kind WithDefaults. +func decodeAndDefault( + jsonData []byte, + schemaBytes []byte, + source string, + target v1alpha1.Config, + strict bool, +) (v1alpha1.Config, error) { + if err := validateAgainstSchema(jsonData, schemaBytes, source); err != nil { + return nil, err + } + dec := json.NewDecoder(bytes.NewReader(jsonData)) + if strict { + dec.DisallowUnknownFields() + } + if err := dec.Decode(target); err != nil { + return nil, fmt.Errorf("%s: %w", source, err) + } + switch t := target.(type) { + case *v1alpha1.EducatesLocalConfig: + t.WithDefaults() + case *v1alpha1.EducatesInlineConfig: + t.WithDefaults() + case *v1alpha1.EducatesGKEConfig: + t.WithDefaults() + case *v1alpha1.EducatesEKSConfig: + t.WithDefaults() + case *v1alpha1.EducatesConfig: + // Escape kind: verbatim passthrough, no defaulting. + } + return target, nil +} + +// validateAgainstSchema runs gojsonschema against the already-marshalled +// JSON bytes (caller has done the YAML→JSON conversion once). +func validateAgainstSchema(jsonData, schemaBytes []byte, source string) error { + loader := gojsonschema.NewBytesLoader(schemaBytes) + docLoader := gojsonschema.NewBytesLoader(jsonData) + result, err := gojsonschema.Validate(loader, docLoader) + if err != nil { + return fmt.Errorf("%s: schema validation error: %w", source, err) + } + if result.Valid() { + return nil + } + var msgs []string + for _, e := range result.Errors() { + msgs = append(msgs, fmt.Sprintf(" - %s: %s", e.Field(), e.Description())) + } + return fmt.Errorf("%s: schema validation failed:\n%s", source, strings.Join(msgs, "\n")) +} + +// normaliseForJSON recursively converts yaml.v2's map[interface{}]interface{} +// into map[string]interface{} so the value can be JSON-marshalled. +func normaliseForJSON(v interface{}) interface{} { + switch x := v.(type) { + case map[interface{}]interface{}: + m := make(map[string]interface{}, len(x)) + for k, val := range x { + m[fmt.Sprint(k)] = normaliseForJSON(val) + } + return m + case []interface{}: + out := make([]interface{}, len(x)) + for i, val := range x { + out[i] = normaliseForJSON(val) + } + return out + default: + return v + } +} diff --git a/client-programs/pkg/config/loader_test.go b/client-programs/pkg/config/loader_test.go new file mode 100644 index 000000000..6eab60e8e --- /dev/null +++ b/client-programs/pkg/config/loader_test.go @@ -0,0 +1,395 @@ +package config + +import ( + "path/filepath" + "strings" + "testing" + + "github.com/educates/educates-training-platform/client-programs/pkg/config/v1alpha1" +) + +func TestLoad_EmptyLocalConfig_AppliesDefaults(t *testing.T) { + cfg, err := Load(filepath.Join("testdata", "local-empty.yaml")) + if err != nil { + t.Fatalf("Load: %v", err) + } + local, ok := cfg.(*v1alpha1.EducatesLocalConfig) + if !ok { + t.Fatalf("expected *EducatesLocalConfig, got %T", cfg) + } + + if got, want := local.Cluster.ListenAddress, "127.0.0.1"; got != want { + t.Errorf("ListenAddress = %q, want %q", got, want) + } + if local.ClusterAdmin == nil || *local.ClusterAdmin != true { + t.Errorf("ClusterAdmin = %v, want true", local.ClusterAdmin) + } + if local.LookupService == nil || *local.LookupService != true { + t.Errorf("LookupService = %v, want true", local.LookupService) + } + if local.ImagePrePuller == nil || *local.ImagePrePuller != false { + t.Errorf("ImagePrePuller = %v, want false", local.ImagePrePuller) + } + if got, want := local.Operator.LogLevel, "info"; got != want { + t.Errorf("Operator.LogLevel = %q, want %q", got, want) + } +} + +func TestLoad_FullLocalConfig_RoundTripsAllFields(t *testing.T) { + cfg, err := Load(filepath.Join("testdata", "local-full.yaml")) + if err != nil { + t.Fatalf("Load: %v", err) + } + local := cfg.(*v1alpha1.EducatesLocalConfig) + + if got, want := local.Cluster.ListenAddress, "192.168.1.10"; got != want { + t.Errorf("ListenAddress = %q, want %q", got, want) + } + if got, want := local.Cluster.ApiServer.Port, 6443; got != want { + t.Errorf("ApiServer.Port = %d, want %d", got, want) + } + if got, want := len(local.Cluster.VolumeMounts), 1; got != want { + t.Fatalf("VolumeMounts len = %d, want %d", got, want) + } + if got, want := local.Cluster.VolumeMounts[0].HostPath, "/tmp/data"; got != want { + t.Errorf("VolumeMounts[0].HostPath = %q, want %q", got, want) + } + if local.ClusterAdmin == nil || *local.ClusterAdmin != false { + t.Errorf("ClusterAdmin = %v, want false (explicit override)", local.ClusterAdmin) + } + if got, want := local.Operator.LogLevel, "debug"; got != want { + t.Errorf("Operator.LogLevel = %q, want %q", got, want) + } + if got, want := local.Ingress.Domain, "workshop.test"; got != want { + t.Errorf("Ingress.Domain = %q, want %q", got, want) + } + if got, want := len(local.Resolver.ExtraDomains), 2; got != want { + t.Errorf("ExtraDomains len = %d, want %d", got, want) + } + if got, want := local.WebsiteStyling.DefaultTheme, "my-theme-data"; got != want { + t.Errorf("WebsiteStyling.DefaultTheme = %q, want %q", got, want) + } +} + +func TestLoad_FullGKEConfig_RoundTripsAllFields(t *testing.T) { + cfg, err := Load(filepath.Join("testdata", "gke-full.yaml")) + if err != nil { + t.Fatalf("Load: %v", err) + } + gke, ok := cfg.(*v1alpha1.EducatesGKEConfig) + if !ok { + t.Fatalf("expected *EducatesGKEConfig, got %T", cfg) + } + + if got, want := gke.GCP.Project, "my-gcp-project"; got != want { + t.Errorf("GCP.Project = %q, want %q", got, want) + } + // Explicit service accounts must survive WithDefaults (no + // project-derived overwrite). + if got, want := gke.GCP.CertManagerServiceAccount, "custom-cert-manager@my-gcp-project.iam.gserviceaccount.com"; got != want { + t.Errorf("GCP.CertManagerServiceAccount = %q, want %q", got, want) + } + if got, want := gke.GCP.ExternalDNSServiceAccount, "custom-external-dns@my-gcp-project.iam.gserviceaccount.com"; got != want { + t.Errorf("GCP.ExternalDNSServiceAccount = %q, want %q", got, want) + } + if got, want := gke.Domain, "academy-01.google.educates.dev"; got != want { + t.Errorf("Domain = %q, want %q", got, want) + } + if got, want := gke.ACME.Email, "ops@example.com"; got != want { + t.Errorf("ACME.Email = %q, want %q", got, want) + } + if got, want := gke.ACME.Server, "https://acme-staging-v02.api.letsencrypt.org/directory"; got != want { + t.Errorf("ACME.Server = %q, want %q", got, want) + } + if !gke.ExternalTLSTermination { + t.Errorf("ExternalTLSTermination = false, want true") + } + // Explicit toggles must override the kind defaults + // (clusterAdmin=false, lookupService=true, imagePrePuller=false). + if gke.ClusterAdmin == nil || *gke.ClusterAdmin != true { + t.Errorf("ClusterAdmin = %v, want true (explicit override)", gke.ClusterAdmin) + } + if gke.LookupService == nil || *gke.LookupService != false { + t.Errorf("LookupService = %v, want false (explicit override)", gke.LookupService) + } + if gke.ImagePrePuller == nil || *gke.ImagePrePuller != true { + t.Errorf("ImagePrePuller = %v, want true (explicit override)", gke.ImagePrePuller) + } + if got, want := gke.WebsiteStyling.DefaultTheme, "my-theme-data"; got != want { + t.Errorf("WebsiteStyling.DefaultTheme = %q, want %q", got, want) + } + if got, want := len(gke.WebsiteStyling.ThemeDataRefs), 1; got != want { + t.Fatalf("ThemeDataRefs len = %d, want %d", got, want) + } + if got, want := gke.WebsiteStyling.ThemeDataRefs[0].Namespace, "educates"; got != want { + t.Errorf("ThemeDataRefs[0].Namespace = %q, want %q", got, want) + } + if got, want := len(gke.SecretPropagation.ImagePullSecretNames), 1; got != want { + t.Errorf("ImagePullSecretNames len = %d, want %d", got, want) + } + if got, want := len(gke.ImageVersions), 1; got != want { + t.Fatalf("ImageVersions len = %d, want %d", got, want) + } + if got, want := gke.ImageVersions[0].Image, "ghcr.io/educates/base-environment:4.0.0"; got != want { + t.Errorf("ImageVersions[0].Image = %q, want %q", got, want) + } + if got, want := gke.Operator.Image.PullPolicy, "IfNotPresent"; got != want { + t.Errorf("Operator.Image.PullPolicy = %q, want %q", got, want) + } + if got, want := len(gke.Operator.ImagePullSecrets), 1; got != want { + t.Errorf("Operator.ImagePullSecrets len = %d, want %d", got, want) + } + if got, want := gke.Operator.LogLevel, "debug"; got != want { + t.Errorf("Operator.LogLevel = %q, want %q", got, want) + } +} + +func TestLoad_FullEKSConfig_RoundTripsAllFields(t *testing.T) { + cfg, err := Load(filepath.Join("testdata", "eks-full.yaml")) + if err != nil { + t.Fatalf("Load: %v", err) + } + eks, ok := cfg.(*v1alpha1.EducatesEKSConfig) + if !ok { + t.Fatalf("expected *EducatesEKSConfig, got %T", cfg) + } + + if got, want := eks.AWS.AccountId, "123456789012"; got != want { + t.Errorf("AWS.AccountId = %q, want %q", got, want) + } + if got, want := eks.AWS.Region, "us-east-1"; got != want { + t.Errorf("AWS.Region = %q, want %q", got, want) + } + if got, want := eks.AWS.Route53HostedZoneId, "Z0123456789ABCDEF"; got != want { + t.Errorf("AWS.Route53HostedZoneId = %q, want %q", got, want) + } + // Explicit role ARNs must survive WithDefaults (no account-derived + // overwrite). + if got, want := eks.AWS.CertManagerRoleARN, "arn:aws:iam::123456789012:role/custom-cert-manager"; got != want { + t.Errorf("AWS.CertManagerRoleARN = %q, want %q", got, want) + } + if got, want := eks.AWS.ExternalDNSRoleARN, "arn:aws:iam::123456789012:role/custom-external-dns"; got != want { + t.Errorf("AWS.ExternalDNSRoleARN = %q, want %q", got, want) + } + if got, want := eks.Domain, "academy-01.workshops.example.com"; got != want { + t.Errorf("Domain = %q, want %q", got, want) + } + if got, want := eks.ACME.Server, "https://acme-staging-v02.api.letsencrypt.org/directory"; got != want { + t.Errorf("ACME.Server = %q, want %q", got, want) + } + if !eks.ExternalTLSTermination { + t.Errorf("ExternalTLSTermination = false, want true") + } + if eks.ClusterAdmin == nil || *eks.ClusterAdmin != true { + t.Errorf("ClusterAdmin = %v, want true (explicit override)", eks.ClusterAdmin) + } + if eks.LookupService == nil || *eks.LookupService != false { + t.Errorf("LookupService = %v, want false (explicit override)", eks.LookupService) + } + if eks.ImagePrePuller == nil || *eks.ImagePrePuller != true { + t.Errorf("ImagePrePuller = %v, want true (explicit override)", eks.ImagePrePuller) + } + if got, want := eks.WebsiteStyling.DefaultTheme, "my-theme-data"; got != want { + t.Errorf("WebsiteStyling.DefaultTheme = %q, want %q", got, want) + } + if got, want := len(eks.SecretPropagation.ImagePullSecretNames), 1; got != want { + t.Errorf("ImagePullSecretNames len = %d, want %d", got, want) + } + if got, want := len(eks.ImageVersions), 1; got != want { + t.Errorf("ImageVersions len = %d, want %d", got, want) + } + if got, want := eks.Operator.Image.PullPolicy, "IfNotPresent"; got != want { + t.Errorf("Operator.Image.PullPolicy = %q, want %q", got, want) + } + if got, want := eks.Operator.LogLevel, "debug"; got != want { + t.Errorf("Operator.LogLevel = %q, want %q", got, want) + } +} + +func TestLoad_FullInlineConfig_RoundTripsAllFields(t *testing.T) { + cfg, err := Load(filepath.Join("testdata", "inline-full.yaml")) + if err != nil { + t.Fatalf("Load: %v", err) + } + inline, ok := cfg.(*v1alpha1.EducatesInlineConfig) + if !ok { + t.Fatalf("expected *EducatesInlineConfig, got %T", cfg) + } + + if got, want := inline.Domain, "workshops.example.com"; got != want { + t.Errorf("Domain = %q, want %q", got, want) + } + if got, want := inline.IngressClassName, "openshift-default"; got != want { + t.Errorf("IngressClassName = %q, want %q", got, want) + } + if got, want := inline.WildcardCertificateSecret, "educates-wildcard-tls"; got != want { + t.Errorf("WildcardCertificateSecret = %q, want %q", got, want) + } + if got, want := inline.CACertificateSecret, "educates-wildcard-ca"; got != want { + t.Errorf("CACertificateSecret = %q, want %q", got, want) + } + if got, want := inline.ClusterIssuerName, "corp-ca-issuer"; got != want { + t.Errorf("ClusterIssuerName = %q, want %q", got, want) + } + if got, want := inline.ImageRegistry.Prefix, "registry.internal.example.com/educates"; got != want { + t.Errorf("ImageRegistry.Prefix = %q, want %q", got, want) + } + if got, want := len(inline.ImageRegistry.PullSecrets), 1; got != want { + t.Errorf("ImageRegistry.PullSecrets len = %d, want %d", got, want) + } + // Explicit engines must override the Kyverno/Kyverno defaults. + if got, want := inline.PolicyEnforcement.ClusterEngine, "PodSecurityStandards"; got != want { + t.Errorf("PolicyEnforcement.ClusterEngine = %q, want %q", got, want) + } + if got, want := inline.PolicyEnforcement.WorkshopEngine, "None"; got != want { + t.Errorf("PolicyEnforcement.WorkshopEngine = %q, want %q", got, want) + } + if !inline.ExternalTLSTermination { + t.Errorf("ExternalTLSTermination = false, want true") + } + if inline.ClusterAdmin == nil || *inline.ClusterAdmin != true { + t.Errorf("ClusterAdmin = %v, want true (explicit override)", inline.ClusterAdmin) + } + if inline.LookupService == nil || *inline.LookupService != false { + t.Errorf("LookupService = %v, want false (explicit override)", inline.LookupService) + } + if inline.ImagePrePuller == nil || *inline.ImagePrePuller != true { + t.Errorf("ImagePrePuller = %v, want true (explicit override)", inline.ImagePrePuller) + } + if got, want := inline.WebsiteStyling.DefaultTheme, "my-theme-data"; got != want { + t.Errorf("WebsiteStyling.DefaultTheme = %q, want %q", got, want) + } + if got, want := len(inline.SecretPropagation.ImagePullSecretNames), 1; got != want { + t.Errorf("ImagePullSecretNames len = %d, want %d", got, want) + } + if got, want := len(inline.ImageVersions), 1; got != want { + t.Errorf("ImageVersions len = %d, want %d", got, want) + } + if got, want := inline.Operator.Image.PullPolicy, "IfNotPresent"; got != want { + t.Errorf("Operator.Image.PullPolicy = %q, want %q", got, want) + } + if got, want := inline.Operator.LogLevel, "debug"; got != want { + t.Errorf("Operator.LogLevel = %q, want %q", got, want) + } +} + +func TestLoad_Errors(t *testing.T) { + cases := []struct { + name string + file string + contains string + }{ + {"unknown-field", "local-unknown-field.yaml", "bogusField"}, + {"bad-enum", "local-bad-loglevel.yaml", "logLevel"}, + {"wrong-apiVersion","wrong-apiversion.yaml", "unsupported apiVersion"}, + {"unknown-kind", "unknown-kind.yaml", "unknown kind"}, + } + for _, tc := range cases { + t.Run(tc.name, func(t *testing.T) { + _, err := Load(filepath.Join("testdata", tc.file)) + if err == nil { + t.Fatalf("Load: expected error, got nil") + } + if !strings.Contains(err.Error(), tc.contains) { + t.Errorf("error %q does not contain %q", err.Error(), tc.contains) + } + }) + } +} + +func TestLoad_MissingFile(t *testing.T) { + _, err := Load(filepath.Join("testdata", "does-not-exist.yaml")) + if err == nil { + t.Fatal("Load: expected error for missing file") + } +} + +func TestLoadLocal_RejectsNonLocalKind(t *testing.T) { + _, err := LoadLocal(filepath.Join("testdata", "escape-minimal.yaml")) + if err == nil { + t.Fatal("LoadLocal: expected error for EducatesConfig kind") + } + if !strings.Contains(err.Error(), "expected kind") { + t.Errorf("error %q does not mention expected kind", err.Error()) + } +} + +func TestLoad_EducatesConfig_Minimal(t *testing.T) { + cfg, err := Load(filepath.Join("testdata", "escape-minimal.yaml")) + if err != nil { + t.Fatalf("Load: %v", err) + } + esc, ok := cfg.(*v1alpha1.EducatesConfig) + if !ok { + t.Fatalf("expected *EducatesConfig, got %T", cfg) + } + if esc.Target != nil { + t.Errorf("Target = %+v, want nil", esc.Target) + } +} + +func TestLoad_EducatesConfig_WithTarget(t *testing.T) { + cfg, err := Load(filepath.Join("testdata", "escape-with-target.yaml")) + if err != nil { + t.Fatalf("Load: %v", err) + } + esc := cfg.(*v1alpha1.EducatesConfig) + if esc.Target == nil { + t.Fatal("Target = nil, want populated") + } + if got, want := esc.Target.Provider, "kind"; got != want { + t.Errorf("Target.Provider = %q, want %q", got, want) + } + if got, want := esc.Operator.LogLevel, "debug"; got != want { + t.Errorf("Operator.LogLevel = %q, want %q (no defaulting for escape kind)", got, want) + } + if esc.SecretsManager == nil { + t.Errorf("SecretsManager = nil, want empty map") + } +} + +func TestLoad_EducatesInlineConfig_Minimal(t *testing.T) { + cfg, err := Load(filepath.Join("testdata", "inline-minimal.yaml")) + if err != nil { + t.Fatalf("Load: %v", err) + } + inline, ok := cfg.(*v1alpha1.EducatesInlineConfig) + if !ok { + t.Fatalf("expected *EducatesInlineConfig, got %T", cfg) + } + if got, want := inline.Domain, "workshop.test"; got != want { + t.Errorf("Domain = %q, want %q", got, want) + } + // Defaults applied. + if got, want := inline.Operator.LogLevel, "info"; got != want { + t.Errorf("Operator.LogLevel = %q, want %q", got, want) + } + if got, want := inline.PolicyEnforcement.ClusterEngine, "Kyverno"; got != want { + t.Errorf("PolicyEnforcement.ClusterEngine default = %q, want %q", got, want) + } +} + +func TestLoad_EducatesInlineConfig_MissingRequired(t *testing.T) { + cfg := []byte("apiVersion: cli.educates.dev/v1alpha1\nkind: EducatesInlineConfig\n") + _, err := LoadBytes(cfg, "test") + if err == nil { + t.Fatal("expected error for missing required fields") + } + // Schema should call out one of the required fields. + for _, want := range []string{"domain", "ingressClassName", "wildcardCertificateSecret"} { + if strings.Contains(err.Error(), want) { + return + } + } + t.Errorf("error %q does not mention any required Inline field", err) +} + +func TestLoad_EducatesConfig_BogusEnvelopeField(t *testing.T) { + _, err := Load(filepath.Join("testdata", "escape-bogus-envelope-field.yaml")) + if err == nil { + t.Fatal("Load: expected error for unknown envelope field") + } + if !strings.Contains(err.Error(), "bogus") { + t.Errorf("error %q does not mention bogus field", err.Error()) + } +} diff --git a/client-programs/pkg/config/migrate.go b/client-programs/pkg/config/migrate.go new file mode 100644 index 000000000..5b91811a4 --- /dev/null +++ b/client-programs/pkg/config/migrate.go @@ -0,0 +1,312 @@ +package config + +import ( + "fmt" + "io" + "os" + "path/filepath" + + "gopkg.in/yaml.v2" + + "github.com/educates/educates-training-platform/client-programs/pkg/config/v1alpha1" +) + +// MaybeMigrateV3 attempts to translate a v3 values.yaml in dataHome +// into a v4 config.yaml in the same dir. Returns nil in three cases: +// +// 1. dataHome has no values.yaml — nothing to migrate (first-time user). +// 2. dataHome has config.yaml — already migrated (or never had v3). +// 3. dataHome has values.yaml + provider ∈ {"", "kind"} — migration +// ran successfully (config.yaml written, values.yaml renamed to +// values.yaml.v3-backup). +// +// Returns a user-actionable error when values.yaml is present without +// config.yaml AND the provider is anything else (gke, eks, openshift, +// etc.): the laptop translator only handles the kind case, so +// non-laptop installs need to be re-declared by hand against the v4 +// kind ladder. +// +// Callers (render, deploy, cluster create) invoke this before falling +// through to MissingLocalConfigError so a successful migration is +// transparent — the user runs the same command they would have on v3, +// it just works on v4 going forward. +// +// Prints a one-line notice on stderr-style output so the user knows +// the migration happened (the design calls for "silent" in the sense +// of "no prompt", not "invisible"). +func MaybeMigrateV3(dataHome string) error { + v3Path := filepath.Join(dataHome, "values.yaml") + v4Path := filepath.Join(dataHome, "config.yaml") + backupPath := filepath.Join(dataHome, "values.yaml.v3-backup") + + if _, err := os.Stat(v4Path); err == nil { + return nil + } + if _, err := os.Stat(v3Path); os.IsNotExist(err) { + return nil + } else if err != nil { + return fmt.Errorf("stat %s: %w", v3Path, err) + } + + body, err := os.ReadFile(v3Path) + if err != nil { + return fmt.Errorf("read %s: %w", v3Path, err) + } + var v3raw map[string]interface{} + if err := yaml.Unmarshal(body, &v3raw); err != nil { + return fmt.Errorf("parse %s as v3 values: %w", v3Path, err) + } + + provider := strV3Path(v3raw, "clusterInfrastructure", "provider") + if provider != "" && provider != "kind" { + return fmt.Errorf(`v3 values.yaml at %s has clusterInfrastructure.provider: %q. + +The v4 CLI's silent migration only handles laptop-kind installs +(provider empty or "kind"). For non-laptop installs, declare a v4 +config explicitly against one of the kinds in +cli.educates.dev/v1alpha1 and rerun with --config : + + - EducatesLocalConfig (laptop kind) + - EducatesInlineConfig (BYO cluster — any provider, pre-existing + cert-manager / ingress / policy engine) + - EducatesGKEConfig (GKE Managed: Workload Identity + ACME + CloudDNS + Contour + Kyverno) + - EducatesEKSConfig (EKS Managed: IRSA + ACME Route53 + + Contour + Kyverno) + - EducatesConfig (escape hatch, full CRD passthrough) + +The original %s file is left untouched; you can keep it as a +reference while re-declaring.`, v3Path, provider, v3Path) + } + + cfg := translateV3ToV4(v3raw) + out, err := yaml.Marshal(cfg) + if err != nil { + return fmt.Errorf("marshal v4 config: %w", err) + } + // Prepend the apiVersion/kind header line so the file reads + // naturally even though yaml.v2's inline TypeMeta marshal works + // fine — keeps the file consistent with what `local config init` + // emits. + if err := os.WriteFile(v4Path, out, 0o644); err != nil { + return fmt.Errorf("write %s: %w", v4Path, err) + } + if err := os.Rename(v3Path, backupPath); err != nil { + return fmt.Errorf("rename %s → %s: %w", v3Path, backupPath, err) + } + + fmt.Fprintf(os.Stderr, "migrated %s → %s; original saved as %s\n", + v3Path, v4Path, backupPath) + + // Warn about v3-shape cached CA Secrets (Opaque + ca.crt) that + // the v4 LocalCachedSecretForCertificateAuthority lookup will + // silently skip. We can't auto-regenerate them — the v3 file + // holds only the cert, not the private key cert-manager needs to + // sign workshop certs — so the user has to re-run + // 'educates local secrets add ca'. + if domain := strV3Path(v3raw, "clusterIngress", "domain"); domain != "" { + warnIfV3CACachePresent(os.Stderr, filepath.Join(dataHome, "secrets"), domain) + } + return nil +} + +// warnIfV3CACachePresent scans the secrets cache for any file shaped +// like the v3 CA cache (Opaque + ca.crt + matching domain annotation) +// and writes a one-time warning to w. Best-effort — failures (no +// secrets dir, unreadable files) silently no-op; the next CLI op +// that needs the CA will give a clear "no cached CA Secret found" +// error anyway. +// +// w is parameterised for tests; production callers pass os.Stderr. +func warnIfV3CACachePresent(w io.Writer, secretsDir, domain string) { + entries, err := os.ReadDir(secretsDir) + if err != nil { + return + } + for _, e := range entries { + if e.IsDir() || filepath.Ext(e.Name()) != ".yaml" { + continue + } + body, err := os.ReadFile(filepath.Join(secretsDir, e.Name())) + if err != nil { + continue + } + var raw map[string]interface{} + if err := yaml.Unmarshal(body, &raw); err != nil { + continue + } + ann := asMap(asMap(raw["metadata"])["annotations"]) + if ann == nil { + continue + } + if d, _ := ann["training.educates.dev/domain"].(string); d != domain { + continue + } + t, _ := raw["type"].(string) + data := asMap(raw["data"]) + if (t == "Opaque" || t == "") && data["ca.crt"] != nil { + fmt.Fprintf(w, `WARNING: cached v3-shape CA Secret detected at %s. +The v4 lookup expects kubernetes.io/tls + tls.crt + tls.key. Re-run: + + educates local secrets add ca %s --domain %s + +to regenerate the cached CA (auto-generated unless you pass --cert/--key). +`, filepath.Join(secretsDir, e.Name()), domain+"-ca", domain) + return + } + } +} + +// translateV3ToV4 builds the v4 EducatesLocalConfig from a v3 values map +// parsed as map[string]interface{}. Missing fields stay zero — the v4 +// schema defaults pick up the rest at load time. +func translateV3ToV4(v3 map[string]interface{}) *v1alpha1.EducatesLocalConfig { + cfg := &v1alpha1.EducatesLocalConfig{ + TypeMeta: v1alpha1.TypeMeta{ + APIVersion: v1alpha1.APIVersion, + Kind: v1alpha1.KindEducatesLocalConfig, + }, + } + + // ingress + cfg.Ingress.Domain = strV3Path(v3, "clusterIngress", "domain") + + // cluster + cfg.Cluster.ListenAddress = strV3Path(v3, "localKindCluster", "listenAddress") + cfg.Cluster.ApiServer.Address = strV3Path(v3, "localKindCluster", "apiServer", "address") + cfg.Cluster.ApiServer.Port = intV3Path(v3, "localKindCluster", "apiServer", "port") + cfg.Cluster.Networking.ServiceSubnet = strV3Path(v3, "localKindCluster", "networking", "serviceSubnet") + cfg.Cluster.Networking.PodSubnet = strV3Path(v3, "localKindCluster", "networking", "podSubnet") + for _, m := range listV3Path(v3, "localKindCluster", "volumeMounts") { + entry := asMap(m) + vm := v1alpha1.VolumeMount{ + HostPath: strMap(entry, "hostPath"), + ContainerPath: strMap(entry, "containerPath"), + } + if v, ok := entry["readOnly"].(bool); ok { + vm.ReadOnly = &v + } + cfg.Cluster.VolumeMounts = append(cfg.Cluster.VolumeMounts, vm) + } + for _, m := range listV3Path(v3, "localKindCluster", "registryMirrors") { + entry := asMap(m) + cfg.Cluster.RegistryMirrors = append(cfg.Cluster.RegistryMirrors, v1alpha1.RegistryMirror{ + Mirror: strMap(entry, "mirror"), + URL: strMap(entry, "url"), + Username: strMap(entry, "username"), + Password: strMap(entry, "password"), + Port: strMap(entry, "port"), + BindIP: strMap(entry, "bindIP"), + }) + } + + // resolver + cfg.Resolver.TargetAddress = strV3Path(v3, "localDNSResolver", "targetAddress") + for _, d := range listV3Path(v3, "localDNSResolver", "extraDomains") { + if s, ok := d.(string); ok { + cfg.Resolver.ExtraDomains = append(cfg.Resolver.ExtraDomains, s) + } + } + + // imageVersions + for _, m := range listV3Path(v3, "imageVersions") { + entry := asMap(m) + cfg.ImageVersions = append(cfg.ImageVersions, v1alpha1.ImageVersion{ + Name: strMap(entry, "name"), + Image: strMap(entry, "image"), + }) + } + + // websiteStyling (narrow subset only) + cfg.WebsiteStyling.DefaultTheme = strV3Path(v3, "websiteStyling", "defaultTheme") + for _, m := range listV3Path(v3, "websiteStyling", "themeDataRefs") { + entry := asMap(m) + cfg.WebsiteStyling.ThemeDataRefs = append(cfg.WebsiteStyling.ThemeDataRefs, v1alpha1.ThemeDataRef{ + Namespace: strMap(entry, "namespace"), + Name: strMap(entry, "name"), + }) + } + + // secretPropagation + for _, s := range listV3Path(v3, "secretPropagation", "imagePullSecretNames") { + if name, ok := s.(string); ok { + cfg.SecretPropagation.ImagePullSecretNames = append(cfg.SecretPropagation.ImagePullSecretNames, name) + } + } + + return cfg +} + +// strV3Path walks v3raw by string keys and returns the leaf as string, +// or "" when any segment is missing / wrong type. +func strV3Path(v3 map[string]interface{}, path ...string) string { + v, ok := walkV3(v3, path...) + if !ok { + return "" + } + s, _ := v.(string) + return s +} + +func intV3Path(v3 map[string]interface{}, path ...string) int { + v, ok := walkV3(v3, path...) + if !ok { + return 0 + } + switch n := v.(type) { + case int: + return n + case int64: + return int(n) + case float64: + return int(n) + } + return 0 +} + +func listV3Path(v3 map[string]interface{}, path ...string) []interface{} { + v, ok := walkV3(v3, path...) + if !ok { + return nil + } + list, _ := v.([]interface{}) + return list +} + +func walkV3(v3 map[string]interface{}, path ...string) (interface{}, bool) { + var cur interface{} = v3 + for _, p := range path { + m := asMap(cur) + if m == nil { + return nil, false + } + v, ok := m[p] + if !ok { + return nil, false + } + cur = v + } + return cur, true +} + +func asMap(v interface{}) map[string]interface{} { + switch x := v.(type) { + case map[string]interface{}: + return x + case map[interface{}]interface{}: + out := make(map[string]interface{}, len(x)) + for k, val := range x { + out[fmt.Sprint(k)] = val + } + return out + } + return nil +} + +func strMap(m map[string]interface{}, key string) string { + if m == nil { + return "" + } + s, _ := m[key].(string) + return s +} diff --git a/client-programs/pkg/config/migrate_test.go b/client-programs/pkg/config/migrate_test.go new file mode 100644 index 000000000..f282e8911 --- /dev/null +++ b/client-programs/pkg/config/migrate_test.go @@ -0,0 +1,254 @@ +package config + +import ( + "bytes" + "os" + "path/filepath" + "strings" + "testing" +) + +const v3KindValues = ` +clusterInfrastructure: + provider: kind +clusterIngress: + domain: educates.test +localKindCluster: + listenAddress: 192.168.1.10 + apiServer: + address: 192.168.1.10 + port: 6443 + networking: + serviceSubnet: 10.96.0.0/12 + podSubnet: 10.244.0.0/16 + volumeMounts: + - hostPath: /tmp/data + containerPath: /data + readOnly: true + registryMirrors: + - mirror: docker.io + url: https://proxy.local +localDNSResolver: + targetAddress: 192.168.1.10 + extraDomains: + - example.test +imageVersions: + - name: "1.0" + image: ghcr.io/educates/example:1.0 +websiteStyling: + defaultTheme: educates-default + themeDataRefs: + - namespace: educates + name: my-theme-data +secretPropagation: + imagePullSecretNames: + - my-pull-secret +clusterSecurity: + policyEngine: pod-security-standards +` + +func TestMaybeMigrateV3_NoState_Noop(t *testing.T) { + dataHome := t.TempDir() + if err := MaybeMigrateV3(dataHome); err != nil { + t.Fatalf("MaybeMigrateV3: %v", err) + } + if _, err := os.Stat(filepath.Join(dataHome, "config.yaml")); err == nil { + t.Error("config.yaml should not have been created from empty data home") + } +} + +func TestMaybeMigrateV3_ConfigYAMLPresent_Noop(t *testing.T) { + dataHome := t.TempDir() + must(t, os.WriteFile(filepath.Join(dataHome, "config.yaml"), []byte("existing"), 0o644)) + must(t, os.WriteFile(filepath.Join(dataHome, "values.yaml"), []byte(v3KindValues), 0o644)) + + if err := MaybeMigrateV3(dataHome); err != nil { + t.Fatalf("MaybeMigrateV3: %v", err) + } + + body := readFile(t, filepath.Join(dataHome, "config.yaml")) + if string(body) != "existing" { + t.Errorf("config.yaml content overwritten: %q", body) + } + if _, err := os.Stat(filepath.Join(dataHome, "values.yaml.v3-backup")); err == nil { + t.Error("v3 backup should not have been created when config.yaml already present") + } +} + +func TestMaybeMigrateV3_KindProvider_Migrates(t *testing.T) { + dataHome := t.TempDir() + must(t, os.WriteFile(filepath.Join(dataHome, "values.yaml"), []byte(v3KindValues), 0o644)) + + if err := MaybeMigrateV3(dataHome); err != nil { + t.Fatalf("MaybeMigrateV3: %v", err) + } + + // values.yaml renamed. + if _, err := os.Stat(filepath.Join(dataHome, "values.yaml")); err == nil { + t.Error("values.yaml should have been renamed") + } + if _, err := os.Stat(filepath.Join(dataHome, "values.yaml.v3-backup")); err != nil { + t.Errorf("values.yaml.v3-backup missing: %v", err) + } + + // config.yaml should load cleanly via the v4 loader. + cfgPath := filepath.Join(dataHome, "config.yaml") + cfg, err := LoadLocal(cfgPath) + if err != nil { + t.Fatalf("LoadLocal on migrated file: %v", err) + } + + // Spot-check a representative scattering of fields across the + // translation table; full coverage is the schema's job at load. + if got, want := cfg.Ingress.Domain, "educates.test"; got != want { + t.Errorf("Ingress.Domain = %q, want %q", got, want) + } + if got, want := cfg.Cluster.ApiServer.Port, 6443; got != want { + t.Errorf("Cluster.ApiServer.Port = %d, want %d", got, want) + } + if got := len(cfg.Cluster.VolumeMounts); got != 1 { + t.Fatalf("VolumeMounts len = %d, want 1", got) + } + if cfg.Cluster.VolumeMounts[0].ReadOnly == nil || !*cfg.Cluster.VolumeMounts[0].ReadOnly { + t.Errorf("VolumeMounts[0].ReadOnly = %v, want true", cfg.Cluster.VolumeMounts[0].ReadOnly) + } + if got, want := cfg.Resolver.TargetAddress, "192.168.1.10"; got != want { + t.Errorf("Resolver.TargetAddress = %q, want %q", got, want) + } + if got := len(cfg.Resolver.ExtraDomains); got != 1 { + t.Errorf("ExtraDomains len = %d, want 1", got) + } + if got, want := cfg.WebsiteStyling.DefaultTheme, "educates-default"; got != want { + t.Errorf("DefaultTheme = %q, want %q", got, want) + } + if got, want := len(cfg.WebsiteStyling.ThemeDataRefs), 1; got != want { + t.Errorf("ThemeDataRefs len = %d, want %d", got, want) + } +} + +func TestMaybeMigrateV3_EmptyProvider_Migrates(t *testing.T) { + dataHome := t.TempDir() + must(t, os.WriteFile(filepath.Join(dataHome, "values.yaml"), + []byte("clusterIngress:\n domain: workshop.test\n"), 0o644)) + + if err := MaybeMigrateV3(dataHome); err != nil { + t.Fatalf("MaybeMigrateV3: %v", err) + } + if _, err := os.Stat(filepath.Join(dataHome, "config.yaml")); err != nil { + t.Errorf("config.yaml not written: %v", err) + } +} + +func TestMaybeMigrateV3_GKEProvider_Refuses(t *testing.T) { + dataHome := t.TempDir() + must(t, os.WriteFile(filepath.Join(dataHome, "values.yaml"), + []byte("clusterInfrastructure:\n provider: gke\n"), 0o644)) + + err := MaybeMigrateV3(dataHome) + if err == nil { + t.Fatal("expected refuse-with-clear-error for gke provider") + } + for _, want := range []string{"gke", "values.yaml", "EducatesGKEConfig"} { + if !strings.Contains(err.Error(), want) { + t.Errorf("error %q missing hint %q", err, want) + } + } + // Original file left untouched. + if _, err := os.Stat(filepath.Join(dataHome, "values.yaml")); err != nil { + t.Errorf("values.yaml should have been left alone: %v", err) + } + if _, err := os.Stat(filepath.Join(dataHome, "config.yaml")); err == nil { + t.Error("config.yaml should not have been written") + } +} + +func TestEnsureLocalConfigFile_MigratesAndPasses(t *testing.T) { + dataHome := t.TempDir() + must(t, os.WriteFile(filepath.Join(dataHome, "values.yaml"), []byte(v3KindValues), 0o644)) + + if err := EnsureLocalConfigFile(dataHome); err != nil { + t.Fatalf("EnsureLocalConfigFile: %v", err) + } + if _, err := os.Stat(filepath.Join(dataHome, "config.yaml")); err != nil { + t.Errorf("config.yaml missing after Ensure: %v", err) + } +} + +func TestWarnIfV3CACachePresent_OpaqueCACertOnly_Warns(t *testing.T) { + dataHome := t.TempDir() + secretsDir := filepath.Join(dataHome, "secrets") + must(t, os.MkdirAll(secretsDir, 0o755)) + v3CASecret := `apiVersion: v1 +kind: Secret +metadata: + name: workshop.test-ca + annotations: + training.educates.dev/domain: workshop.test +type: Opaque +data: + ca.crt: dGVzdA== +` + must(t, os.WriteFile(filepath.Join(secretsDir, "workshop.test-ca.yaml"), []byte(v3CASecret), 0o644)) + + var buf bytes.Buffer + warnIfV3CACachePresent(&buf, secretsDir, "workshop.test") + + s := buf.String() + for _, want := range []string{"v3-shape CA Secret detected", "kubernetes.io/tls + tls.crt + tls.key", "educates local secrets add ca workshop.test-ca --domain workshop.test"} { + if !strings.Contains(s, want) { + t.Errorf("warning missing %q in:\n%s", want, s) + } + } +} + +func TestWarnIfV3CACachePresent_TLSShape_NoWarn(t *testing.T) { + dataHome := t.TempDir() + secretsDir := filepath.Join(dataHome, "secrets") + must(t, os.MkdirAll(secretsDir, 0o755)) + // v4-shape — kubernetes.io/tls — should NOT warn. + v4Secret := `apiVersion: v1 +kind: Secret +metadata: + name: workshop.test-ca + annotations: + training.educates.dev/domain: workshop.test +type: kubernetes.io/tls +data: + tls.crt: dGVzdA== + tls.key: dGVzdA== +` + must(t, os.WriteFile(filepath.Join(secretsDir, "workshop.test-ca.yaml"), []byte(v4Secret), 0o644)) + + var buf bytes.Buffer + warnIfV3CACachePresent(&buf, secretsDir, "workshop.test") + if buf.Len() != 0 { + t.Errorf("v4-shape Secret should not warn, got:\n%s", buf.String()) + } +} + +func TestEnsureLocalConfigFile_NoMigrationNeeded_SurfacesMissingError(t *testing.T) { + dataHome := t.TempDir() + err := EnsureLocalConfigFile(dataHome) + if err == nil { + t.Fatal("expected MissingLocalConfigError for empty data home") + } + if !strings.Contains(err.Error(), "config init") { + t.Errorf("expected local config init hint, got %q", err) + } +} + +func must(t *testing.T, err error) { + t.Helper() + if err != nil { + t.Fatal(err) + } +} + +func readFile(t *testing.T, path string) []byte { + t.Helper() + b, err := os.ReadFile(path) + if err != nil { + t.Fatal(err) + } + return b +} diff --git a/client-programs/pkg/config/testdata/eks-full.yaml b/client-programs/pkg/config/testdata/eks-full.yaml new file mode 100644 index 000000000..62c5d0c5d --- /dev/null +++ b/client-programs/pkg/config/testdata/eks-full.yaml @@ -0,0 +1,44 @@ +apiVersion: cli.educates.dev/v1alpha1 +kind: EducatesEKSConfig + +aws: + accountId: "123456789012" + region: us-east-1 + route53HostedZoneId: Z0123456789ABCDEF + certManagerRoleARN: arn:aws:iam::123456789012:role/custom-cert-manager + externalDNSRoleARN: arn:aws:iam::123456789012:role/custom-external-dns + +domain: academy-01.workshops.example.com + +acme: + email: ops@example.com + server: https://acme-staging-v02.api.letsencrypt.org/directory + +externalTLSTermination: true + +clusterAdmin: true +lookupService: false +imagePrePuller: true + +websiteStyling: + defaultTheme: my-theme-data + themeDataRefs: + - namespace: educates + name: my-theme-data + +secretPropagation: + imagePullSecretNames: + - my-pull-secret + +imageVersions: + - name: base-environment + image: ghcr.io/educates/base-environment:4.0.0 + +operator: + image: + repository: ghcr.io/educates/educates-operator + tag: 4.0.0 + pullPolicy: IfNotPresent + imagePullSecrets: + - operator-pull-secret + logLevel: debug diff --git a/client-programs/pkg/config/testdata/eks-minimal.yaml b/client-programs/pkg/config/testdata/eks-minimal.yaml new file mode 100644 index 000000000..eb516c44a --- /dev/null +++ b/client-programs/pkg/config/testdata/eks-minimal.yaml @@ -0,0 +1,12 @@ +apiVersion: cli.educates.dev/v1alpha1 +kind: EducatesEKSConfig + +aws: + accountId: "123456789012" + region: us-east-1 + route53HostedZoneId: Z0123456789ABCDEF + +domain: academy-01.workshops.example.com + +acme: + email: ops@example.com diff --git a/client-programs/pkg/config/testdata/escape-bogus-envelope-field.yaml b/client-programs/pkg/config/testdata/escape-bogus-envelope-field.yaml new file mode 100644 index 000000000..3922babc1 --- /dev/null +++ b/client-programs/pkg/config/testdata/escape-bogus-envelope-field.yaml @@ -0,0 +1,3 @@ +apiVersion: cli.educates.dev/v1alpha1 +kind: EducatesConfig +bogus: true diff --git a/client-programs/pkg/config/testdata/escape-minimal.yaml b/client-programs/pkg/config/testdata/escape-minimal.yaml new file mode 100644 index 000000000..6bc867fc5 --- /dev/null +++ b/client-programs/pkg/config/testdata/escape-minimal.yaml @@ -0,0 +1,2 @@ +apiVersion: cli.educates.dev/v1alpha1 +kind: EducatesConfig diff --git a/client-programs/pkg/config/testdata/escape-with-target.yaml b/client-programs/pkg/config/testdata/escape-with-target.yaml new file mode 100644 index 000000000..ffb3f9281 --- /dev/null +++ b/client-programs/pkg/config/testdata/escape-with-target.yaml @@ -0,0 +1,17 @@ +apiVersion: cli.educates.dev/v1alpha1 +kind: EducatesConfig + +target: + provider: kind + cluster: + listenAddress: 127.0.0.1 + resolver: + targetAddress: 127.0.0.1 + +operator: + image: + repository: ghcr.io/educates/educates-operator + tag: 4.0.0 + logLevel: debug + +secretsManager: {} diff --git a/client-programs/pkg/config/testdata/gke-full.yaml b/client-programs/pkg/config/testdata/gke-full.yaml new file mode 100644 index 000000000..071a3b756 --- /dev/null +++ b/client-programs/pkg/config/testdata/gke-full.yaml @@ -0,0 +1,42 @@ +apiVersion: cli.educates.dev/v1alpha1 +kind: EducatesGKEConfig + +gcp: + project: my-gcp-project + certManagerServiceAccount: custom-cert-manager@my-gcp-project.iam.gserviceaccount.com + externalDNSServiceAccount: custom-external-dns@my-gcp-project.iam.gserviceaccount.com + +domain: academy-01.google.educates.dev + +acme: + email: ops@example.com + server: https://acme-staging-v02.api.letsencrypt.org/directory + +externalTLSTermination: true + +clusterAdmin: true +lookupService: false +imagePrePuller: true + +websiteStyling: + defaultTheme: my-theme-data + themeDataRefs: + - namespace: educates + name: my-theme-data + +secretPropagation: + imagePullSecretNames: + - my-pull-secret + +imageVersions: + - name: base-environment + image: ghcr.io/educates/base-environment:4.0.0 + +operator: + image: + repository: ghcr.io/educates/educates-operator + tag: 4.0.0 + pullPolicy: IfNotPresent + imagePullSecrets: + - operator-pull-secret + logLevel: debug diff --git a/client-programs/pkg/config/testdata/gke-minimal.yaml b/client-programs/pkg/config/testdata/gke-minimal.yaml new file mode 100644 index 000000000..cfcfc7dc0 --- /dev/null +++ b/client-programs/pkg/config/testdata/gke-minimal.yaml @@ -0,0 +1,10 @@ +apiVersion: cli.educates.dev/v1alpha1 +kind: EducatesGKEConfig + +gcp: + project: my-gcp-project + +domain: academy-01.google.educates.dev + +acme: + email: ops@example.com diff --git a/client-programs/pkg/config/testdata/inline-full.yaml b/client-programs/pkg/config/testdata/inline-full.yaml new file mode 100644 index 000000000..fe1c4c919 --- /dev/null +++ b/client-programs/pkg/config/testdata/inline-full.yaml @@ -0,0 +1,46 @@ +apiVersion: cli.educates.dev/v1alpha1 +kind: EducatesInlineConfig + +domain: workshops.example.com +ingressClassName: openshift-default +wildcardCertificateSecret: educates-wildcard-tls +caCertificateSecret: educates-wildcard-ca +clusterIssuerName: corp-ca-issuer + +imageRegistry: + prefix: registry.internal.example.com/educates + pullSecrets: + - internal-registry-pull + +policyEnforcement: + clusterEngine: PodSecurityStandards + workshopEngine: None + +externalTLSTermination: true + +clusterAdmin: true +lookupService: false +imagePrePuller: true + +websiteStyling: + defaultTheme: my-theme-data + themeDataRefs: + - namespace: educates + name: my-theme-data + +secretPropagation: + imagePullSecretNames: + - my-pull-secret + +imageVersions: + - name: base-environment + image: ghcr.io/educates/base-environment:4.0.0 + +operator: + image: + repository: ghcr.io/educates/educates-operator + tag: 4.0.0 + pullPolicy: IfNotPresent + imagePullSecrets: + - operator-pull-secret + logLevel: debug diff --git a/client-programs/pkg/config/testdata/inline-minimal.yaml b/client-programs/pkg/config/testdata/inline-minimal.yaml new file mode 100644 index 000000000..cf1e20cff --- /dev/null +++ b/client-programs/pkg/config/testdata/inline-minimal.yaml @@ -0,0 +1,6 @@ +apiVersion: cli.educates.dev/v1alpha1 +kind: EducatesInlineConfig + +domain: workshop.test +ingressClassName: contour +wildcardCertificateSecret: educates-wildcard-tls diff --git a/client-programs/pkg/config/testdata/inline-openshift.yaml b/client-programs/pkg/config/testdata/inline-openshift.yaml new file mode 100644 index 000000000..aa3fc58e9 --- /dev/null +++ b/client-programs/pkg/config/testdata/inline-openshift.yaml @@ -0,0 +1,16 @@ +apiVersion: cli.educates.dev/v1alpha1 +kind: EducatesInlineConfig + +domain: workshops.example.com +ingressClassName: openshift-default +wildcardCertificateSecret: educates-wildcard-tls +caCertificateSecret: educates-wildcard-ca + +policyEnforcement: + clusterEngine: OpenShiftSCC + workshopEngine: None + +imageRegistry: + prefix: registry.internal.example.com/educates + pullSecrets: + - internal-registry-pull diff --git a/client-programs/pkg/config/testdata/local-bad-loglevel.yaml b/client-programs/pkg/config/testdata/local-bad-loglevel.yaml new file mode 100644 index 000000000..d0dc34590 --- /dev/null +++ b/client-programs/pkg/config/testdata/local-bad-loglevel.yaml @@ -0,0 +1,4 @@ +apiVersion: cli.educates.dev/v1alpha1 +kind: EducatesLocalConfig +operator: + logLevel: trace diff --git a/client-programs/pkg/config/testdata/local-empty.yaml b/client-programs/pkg/config/testdata/local-empty.yaml new file mode 100644 index 000000000..227299e5b --- /dev/null +++ b/client-programs/pkg/config/testdata/local-empty.yaml @@ -0,0 +1,2 @@ +apiVersion: cli.educates.dev/v1alpha1 +kind: EducatesLocalConfig diff --git a/client-programs/pkg/config/testdata/local-full.yaml b/client-programs/pkg/config/testdata/local-full.yaml new file mode 100644 index 000000000..416581519 --- /dev/null +++ b/client-programs/pkg/config/testdata/local-full.yaml @@ -0,0 +1,56 @@ +apiVersion: cli.educates.dev/v1alpha1 +kind: EducatesLocalConfig + +cluster: + listenAddress: 192.168.1.10 + registryListenAddress: 192.168.1.10 + apiServer: + address: 192.168.1.10 + port: 6443 + networking: + serviceSubnet: 10.96.0.0/12 + podSubnet: 10.244.0.0/16 + volumeMounts: + - hostPath: /tmp/data + containerPath: /data + readOnly: true + registryMirrors: + - mirror: docker.io + url: https://my-proxy.local + port: "5002" + bindIP: 192.168.1.10 + +resolver: + targetAddress: 192.168.1.10 + extraDomains: + - example.test + - workshop.test + +ingress: + domain: workshop.test + +clusterAdmin: false +lookupService: false +imagePrePuller: true + +websiteStyling: + defaultTheme: my-theme-data + themeDataRefs: + - namespace: educates + name: my-theme-data + +secretPropagation: + imagePullSecretNames: + - my-pull-secret + +imageVersions: + - name: "1.0" + image: ghcr.io/educates/example:1.0 + +operator: + image: + repository: ghcr.io/educates/educates-operator + tag: 4.0.0 + imagePullSecrets: + - operator-pull-secret + logLevel: debug diff --git a/client-programs/pkg/config/testdata/local-unknown-field.yaml b/client-programs/pkg/config/testdata/local-unknown-field.yaml new file mode 100644 index 000000000..25c5b5426 --- /dev/null +++ b/client-programs/pkg/config/testdata/local-unknown-field.yaml @@ -0,0 +1,4 @@ +apiVersion: cli.educates.dev/v1alpha1 +kind: EducatesLocalConfig +clusterAdmin: true +bogusField: 42 diff --git a/client-programs/pkg/config/testdata/unknown-kind.yaml b/client-programs/pkg/config/testdata/unknown-kind.yaml new file mode 100644 index 000000000..bb7b5edb8 --- /dev/null +++ b/client-programs/pkg/config/testdata/unknown-kind.yaml @@ -0,0 +1,2 @@ +apiVersion: cli.educates.dev/v1alpha1 +kind: EducatesNotARealKind diff --git a/client-programs/pkg/config/testdata/wrong-apiversion.yaml b/client-programs/pkg/config/testdata/wrong-apiversion.yaml new file mode 100644 index 000000000..fcab4ff2d --- /dev/null +++ b/client-programs/pkg/config/testdata/wrong-apiversion.yaml @@ -0,0 +1,2 @@ +apiVersion: cli.educates.dev/v1beta1 +kind: EducatesLocalConfig diff --git a/client-programs/pkg/config/translator/eks.go b/client-programs/pkg/config/translator/eks.go new file mode 100644 index 000000000..076e5ac21 --- /dev/null +++ b/client-programs/pkg/config/translator/eks.go @@ -0,0 +1,83 @@ +package translator + +import ( + "github.com/educates/educates-training-platform/client-programs/pkg/config/v1alpha1" +) + +// TranslateEKS converts EducatesEKSConfig into the deployable output. +// ECC.spec is mode: Managed with the EKS-prod stack: BundledContour +// (LoadBalancer envoy), BundledCertManager with ACME-DNS01-Route53, +// BundledExternalDNS with Route53, BundledKyverno. +func TranslateEKS(cfg *v1alpha1.EducatesEKSConfig, _ Options) (*Output, error) { + out := &Output{ + OperatorChartValues: operatorChartValuesFor(cfg.Operator), + EducatesClusterConfig: wrapCR(apiVersionConfig, "EducatesClusterConfig", eksECCSpec(cfg)), + SecretsManager: wrapCR(apiVersionPlatform, "SecretsManager", scenarioSecretsManagerSpec(cfg.Operator.LogLevel, cfg.ImageVersions)), + SessionManager: wrapCR(apiVersionPlatform, "SessionManager", scenarioSessionManagerSpec(cfg.Operator.LogLevel, cfg.WebsiteStyling, cfg.ImagePrePuller, cfg.ImageVersions, cfg.ExternalTLSTermination)), + } + if cfg.LookupService != nil && *cfg.LookupService { + out.LookupService = wrapCR(apiVersionPlatform, "LookupService", scenarioLookupServiceSpec(cfg.Operator.LogLevel, cfg.ImageVersions)) + } + return out, nil +} + +// eksECCSpec builds the Managed-mode ECC.spec for EKS. Mirrors the GKE +// shape but with Route53 in place of CloudDNS, and IRSA roles in place +// of WI service-account emails. +func eksECCSpec(cfg *v1alpha1.EducatesEKSConfig) map[string]interface{} { + route53 := map[string]interface{}{ + "hostedZoneID": cfg.AWS.Route53HostedZoneId, + "region": cfg.AWS.Region, + "iamRoleARN": cfg.AWS.CertManagerRoleARN, + } + acme := map[string]interface{}{ + "email": cfg.ACME.Email, + "solvers": map[string]interface{}{ + "dns01": map[string]interface{}{ + "provider": "Route53", + "route53": route53, + }, + }, + } + if cfg.ACME.Server != "" { + acme["server"] = cfg.ACME.Server + } + + return map[string]interface{}{ + "mode": "Managed", + "ingress": map[string]interface{}{ + "domain": cfg.Domain, + "ingressClassName": "contour", + "controller": map[string]interface{}{ + "provider": "BundledContour", + "bundledContour": map[string]interface{}{ + "envoyServiceType": "LoadBalancer", + }, + }, + "certificates": map[string]interface{}{ + "provider": "BundledCertManager", + "bundledCertManager": map[string]interface{}{ + "issuerType": "ACME", + "acme": acme, + }, + }, + }, + "dns": map[string]interface{}{ + "provider": "BundledExternalDNS", + "bundledExternalDNS": map[string]interface{}{ + "provider": "Route53", + "sources": []interface{}{"service"}, + "route53": map[string]interface{}{ + "hostedZoneID": cfg.AWS.Route53HostedZoneId, + "region": cfg.AWS.Region, + "iamRoleARN": cfg.AWS.ExternalDNSRoleARN, + }, + }, + }, + "policyEnforcement": map[string]interface{}{ + "clusterPolicy": map[string]interface{}{"engine": "Kyverno"}, + "workshopPolicy": map[string]interface{}{"engine": "Kyverno"}, + "kyverno": map[string]interface{}{"provider": "Bundled"}, + }, + } +} diff --git a/client-programs/pkg/config/translator/eks_test.go b/client-programs/pkg/config/translator/eks_test.go new file mode 100644 index 000000000..0b4adb618 --- /dev/null +++ b/client-programs/pkg/config/translator/eks_test.go @@ -0,0 +1,91 @@ +package translator + +import ( + "strings" + "testing" + + "github.com/educates/educates-training-platform/client-programs/pkg/config/v1alpha1" +) + +func TestTranslateEKS_Minimal_InvariantsAndIRSARoleDefaults(t *testing.T) { + cfg := loadCfg(t, "eks-minimal.yaml").(*v1alpha1.EducatesEKSConfig) + out, err := Translate(cfg, Options{}) + if err != nil { + t.Fatalf("Translate: %v", err) + } + + spec := out.EducatesClusterConfig["spec"].(map[string]interface{}) + if got, want := spec["mode"], "Managed"; got != want { + t.Errorf("spec.mode = %v, want %v", got, want) + } + + dns01 := spec["ingress"].(map[string]interface{})["certificates"].(map[string]interface{})["bundledCertManager"].(map[string]interface{})["acme"].(map[string]interface{})["solvers"].(map[string]interface{})["dns01"].(map[string]interface{}) + if got, want := dns01["provider"], "Route53"; got != want { + t.Errorf("dns01.provider = %v, want %v", got, want) + } + route53 := dns01["route53"].(map[string]interface{}) + if got, want := route53["hostedZoneID"], "Z0123456789ABCDEF"; got != want { + t.Errorf("route53.hostedZoneID = %v, want %v", got, want) + } + if got, want := route53["region"], "us-east-1"; got != want { + t.Errorf("route53.region = %v, want %v", got, want) + } + if got, want := route53["iamRoleARN"], "arn:aws:iam::123456789012:role/educates-cert-manager"; got != want { + t.Errorf("cert-manager iamRoleARN default = %v, want %v", got, want) + } + + bundledDNS := spec["dns"].(map[string]interface{})["bundledExternalDNS"].(map[string]interface{}) + externalRoute53 := bundledDNS["route53"].(map[string]interface{}) + if got, want := externalRoute53["iamRoleARN"], "arn:aws:iam::123456789012:role/educates-external-dns"; got != want { + t.Errorf("external-dns iamRoleARN default = %v, want %v", got, want) + } + + if got, want := spec["policyEnforcement"].(map[string]interface{})["clusterPolicy"].(map[string]interface{})["engine"], "Kyverno"; got != want { + t.Errorf("clusterPolicy.engine = %v, want %v", got, want) + } +} + +func TestTranslateEKS_OverrideRoles_RoundTrips(t *testing.T) { + yaml := `apiVersion: cli.educates.dev/v1alpha1 +kind: EducatesEKSConfig +aws: + accountId: "123456789012" + region: us-east-1 + route53HostedZoneId: Z0123456789ABCDEF + certManagerRoleARN: arn:aws:iam::123456789012:role/custom-cm + externalDNSRoleARN: arn:aws:iam::123456789012:role/custom-edns +domain: academy-01.workshops.example.com +acme: + email: ops@example.com +` + out, err := translateBytes(t, []byte(yaml)) + if err != nil { + t.Fatal(err) + } + spec := out.EducatesClusterConfig["spec"].(map[string]interface{}) + r53 := spec["ingress"].(map[string]interface{})["certificates"].(map[string]interface{})["bundledCertManager"].(map[string]interface{})["acme"].(map[string]interface{})["solvers"].(map[string]interface{})["dns01"].(map[string]interface{})["route53"].(map[string]interface{}) + if got, want := r53["iamRoleARN"], "arn:aws:iam::123456789012:role/custom-cm"; got != want { + t.Errorf("user-provided role = %v, want %v (defaulting should NOT override)", got, want) + } +} + +func TestTranslateEKS_RenderRoundTripsAsValidYAML(t *testing.T) { + cfg := loadCfg(t, "eks-minimal.yaml").(*v1alpha1.EducatesEKSConfig) + out, _ := Translate(cfg, Options{}) + crs, err := RenderCRs(out) + if err != nil { + t.Fatal(err) + } + s := string(crs) + for _, want := range []string{ + "mode: Managed", + "provider: Route53", + "hostedZoneID: Z0123456789ABCDEF", + "iamRoleARN: arn:aws:iam::123456789012:role/educates-cert-manager", + "iamRoleARN: arn:aws:iam::123456789012:role/educates-external-dns", + } { + if !strings.Contains(s, want) { + t.Errorf("rendered output missing %q", want) + } + } +} diff --git a/client-programs/pkg/config/translator/escape.go b/client-programs/pkg/config/translator/escape.go new file mode 100644 index 000000000..db4ec37a8 --- /dev/null +++ b/client-programs/pkg/config/translator/escape.go @@ -0,0 +1,72 @@ +package translator + +import ( + "github.com/educates/educates-training-platform/client-programs/pkg/config/v1alpha1" +) + +// TranslateEscape converts EducatesConfig (the escape-hatch kind) into the +// deployable output. Pure mechanical YAML slicing: every spec block is +// passed through verbatim. No defaults, no invariants, no field-level +// mapping. +// +// LookupService is omitted from output when the user omitted it from the +// config — its presence is the deploy signal. +func TranslateEscape(cfg *v1alpha1.EducatesConfig) *Output { + out := &Output{ + OperatorChartValues: operatorChartValuesFor(cfg.Operator), + EducatesClusterConfig: wrapCR(apiVersionConfig, "EducatesClusterConfig", normaliseSpec(cfg.EducatesClusterConfig)), + SecretsManager: wrapCR(apiVersionPlatform, "SecretsManager", normaliseSpec(cfg.SecretsManager)), + SessionManager: wrapCR(apiVersionPlatform, "SessionManager", normaliseSpec(cfg.SessionManager)), + } + if cfg.LookupService != nil { + out.LookupService = wrapCR(apiVersionPlatform, "LookupService", normaliseSpec(cfg.LookupService)) + } + return out +} + +// normaliseSpec converts yaml.v2's map[interface{}]interface{} values +// inside a parsed CR spec into map[string]interface{} so the renderer can +// emit them with deterministic key ordering. Identity for already-string- +// keyed maps and primitives. +func normaliseSpec(m map[string]interface{}) map[string]interface{} { + if m == nil { + return nil + } + out := make(map[string]interface{}, len(m)) + for k, v := range m { + out[k] = normaliseValue(v) + } + return out +} + +func normaliseValue(v interface{}) interface{} { + switch x := v.(type) { + case map[interface{}]interface{}: + out := make(map[string]interface{}, len(x)) + for k, val := range x { + out[toString(k)] = normaliseValue(val) + } + return out + case map[string]interface{}: + out := make(map[string]interface{}, len(x)) + for k, val := range x { + out[k] = normaliseValue(val) + } + return out + case []interface{}: + out := make([]interface{}, len(x)) + for i, val := range x { + out[i] = normaliseValue(val) + } + return out + default: + return v + } +} + +func toString(v interface{}) string { + if s, ok := v.(string); ok { + return s + } + return "" +} diff --git a/client-programs/pkg/config/translator/gke.go b/client-programs/pkg/config/translator/gke.go new file mode 100644 index 000000000..bdb143e61 --- /dev/null +++ b/client-programs/pkg/config/translator/gke.go @@ -0,0 +1,136 @@ +package translator + +import ( + "github.com/educates/educates-training-platform/client-programs/pkg/config/v1alpha1" +) + +// TranslateGKE converts EducatesGKEConfig into the deployable output. +// ECC.spec is mode: Managed with the full GKE-prod stack: BundledContour +// (LoadBalancer envoy), BundledCertManager with ACME-DNS01-CloudDNS, +// BundledExternalDNS with CloudDNS, BundledKyverno. +// +// opts is accepted for signature uniformity with TranslateLocal; the +// CASecret fields are not consumed (ACME does its own cert lifecycle). +func TranslateGKE(cfg *v1alpha1.EducatesGKEConfig, _ Options) (*Output, error) { + out := &Output{ + OperatorChartValues: operatorChartValuesFor(cfg.Operator), + EducatesClusterConfig: wrapCR(apiVersionConfig, "EducatesClusterConfig", gkeECCSpec(cfg)), + SecretsManager: wrapCR(apiVersionPlatform, "SecretsManager", scenarioSecretsManagerSpec(cfg.Operator.LogLevel, cfg.ImageVersions)), + SessionManager: wrapCR(apiVersionPlatform, "SessionManager", scenarioSessionManagerSpec(cfg.Operator.LogLevel, cfg.WebsiteStyling, cfg.ImagePrePuller, cfg.ImageVersions, cfg.ExternalTLSTermination)), + } + if cfg.LookupService != nil && *cfg.LookupService { + out.LookupService = wrapCR(apiVersionPlatform, "LookupService", scenarioLookupServiceSpec(cfg.Operator.LogLevel, cfg.ImageVersions)) + } + return out, nil +} + +// gkeECCSpec builds the Managed-mode ECC.spec for GKE. +func gkeECCSpec(cfg *v1alpha1.EducatesGKEConfig) map[string]interface{} { + cloudDNS := map[string]interface{}{ + "project": cfg.GCP.Project, + "workloadIdentityServiceAccount": cfg.GCP.CertManagerServiceAccount, + } + acme := map[string]interface{}{ + "email": cfg.ACME.Email, + "solvers": map[string]interface{}{ + "dns01": map[string]interface{}{ + "provider": "CloudDNS", + "cloudDNS": cloudDNS, + }, + }, + } + if cfg.ACME.Server != "" { + acme["server"] = cfg.ACME.Server + } + + return map[string]interface{}{ + "mode": "Managed", + "ingress": map[string]interface{}{ + "domain": cfg.Domain, + "ingressClassName": "contour", + "controller": map[string]interface{}{ + "provider": "BundledContour", + "bundledContour": map[string]interface{}{ + "envoyServiceType": "LoadBalancer", + }, + }, + "certificates": map[string]interface{}{ + "provider": "BundledCertManager", + "bundledCertManager": map[string]interface{}{ + "issuerType": "ACME", + "acme": acme, + }, + }, + }, + "dns": map[string]interface{}{ + "provider": "BundledExternalDNS", + "bundledExternalDNS": map[string]interface{}{ + "provider": "CloudDNS", + "sources": []interface{}{"service"}, + "cloudDNS": map[string]interface{}{ + "project": cfg.GCP.Project, + "workloadIdentityServiceAccount": cfg.GCP.ExternalDNSServiceAccount, + }, + }, + }, + "policyEnforcement": map[string]interface{}{ + "clusterPolicy": map[string]interface{}{"engine": "Kyverno"}, + "workshopPolicy": map[string]interface{}{"engine": "Kyverno"}, + "kyverno": map[string]interface{}{"provider": "Bundled"}, + }, + } +} + +// scenarioSecretsManagerSpec is the shared body used by SecretsManager — +// logLevel plus the routed "secrets-manager" image override; the +// operator derives everything else from chart defaults + ECC.status. +func scenarioSecretsManagerSpec(logLevel string, ivs []v1alpha1.ImageVersion) map[string]interface{} { + spec := map[string]interface{}{} + if logLevel != "" { + spec["logLevel"] = logLevel + } + if ref := componentImageRef(ivs, "secrets-manager"); ref != nil { + spec["image"] = ref + } + return spec +} + +// scenarioLookupServiceSpec is shared by every scenario kind that +// emits LookupService. An imageVersions entry named "lookup-service" +// routes here as spec.image. +func scenarioLookupServiceSpec(logLevel string, ivs []v1alpha1.ImageVersion) map[string]interface{} { + spec := map[string]interface{}{ + "ingress": map[string]interface{}{"prefix": "lookup"}, + } + if logLevel != "" { + spec["logLevel"] = logLevel + } + if ref := componentImageRef(ivs, "lookup-service"); ref != nil { + spec["image"] = ref + } + return spec +} + +// scenarioSessionManagerSpec is the cloud-scenario-shaped SessionManager +// builder. Mirrors localSessionManagerSpec minus the laptop-specific +// storage.storageGroup / network.blockedCidrs invariants. +func scenarioSessionManagerSpec(logLevel string, ws v1alpha1.LocalWebsiteStylingConfig, ipp *bool, imageVersions []v1alpha1.ImageVersion, externalTLS bool) map[string]interface{} { + spec := map[string]interface{}{} + if logLevel != "" { + spec["logLevel"] = logLevel + } + if externalTLS { + spec["ingressOverrides"] = map[string]interface{}{"protocol": "https"} + } + if ws.DefaultTheme != "" { + spec["defaultTheme"] = ws.DefaultTheme + } + if len(ws.ThemeDataRefs) > 0 { + spec["themes"] = themesFromDataRefs(ws.ThemeDataRefs) + } + if ipp != nil { + spec["imagePrePuller"] = map[string]interface{}{"enabled": *ipp} + } + applySessionManagerImageOverrides(spec, imageVersions) + return spec +} diff --git a/client-programs/pkg/config/translator/gke_test.go b/client-programs/pkg/config/translator/gke_test.go new file mode 100644 index 000000000..9b4192be2 --- /dev/null +++ b/client-programs/pkg/config/translator/gke_test.go @@ -0,0 +1,146 @@ +package translator + +import ( + "strings" + "testing" + + "github.com/educates/educates-training-platform/client-programs/pkg/config/v1alpha1" +) + +func TestTranslateGKE_Minimal_InvariantsAndProjectDefaults(t *testing.T) { + cfg := loadCfg(t, "gke-minimal.yaml").(*v1alpha1.EducatesGKEConfig) + out, err := Translate(cfg, Options{}) + if err != nil { + t.Fatalf("Translate: %v", err) + } + + spec := out.EducatesClusterConfig["spec"].(map[string]interface{}) + if got, want := spec["mode"], "Managed"; got != want { + t.Errorf("spec.mode = %v, want %v", got, want) + } + + ingress := spec["ingress"].(map[string]interface{}) + if got, want := ingress["domain"], "academy-01.google.educates.dev"; got != want { + t.Errorf("ingress.domain = %v, want %v", got, want) + } + controller := ingress["controller"].(map[string]interface{}) + bundled := controller["bundledContour"].(map[string]interface{}) + if got, want := bundled["envoyServiceType"], "LoadBalancer"; got != want { + t.Errorf("envoyServiceType = %v, want %v (cloud invariant)", got, want) + } + + bcm := ingress["certificates"].(map[string]interface{})["bundledCertManager"].(map[string]interface{}) + if got, want := bcm["issuerType"], "ACME"; got != want { + t.Errorf("issuerType = %v, want %v", got, want) + } + acme := bcm["acme"].(map[string]interface{}) + if got, want := acme["email"], "ops@example.com"; got != want { + t.Errorf("acme.email = %v, want %v", got, want) + } + dns01 := acme["solvers"].(map[string]interface{})["dns01"].(map[string]interface{}) + if got, want := dns01["provider"], "CloudDNS"; got != want { + t.Errorf("solvers.dns01.provider = %v, want %v", got, want) + } + cloudDNS := dns01["cloudDNS"].(map[string]interface{}) + if got, want := cloudDNS["project"], "my-gcp-project"; got != want { + t.Errorf("cloudDNS.project = %v, want %v", got, want) + } + // WI service-account default derives from project. + if got, want := cloudDNS["workloadIdentityServiceAccount"], "cert-manager@my-gcp-project.iam.gserviceaccount.com"; got != want { + t.Errorf("certmanager WI SA default = %v, want %v", got, want) + } + + dns := spec["dns"].(map[string]interface{}) + bundledDNS := dns["bundledExternalDNS"].(map[string]interface{}) + externalDNSCloudDNS := bundledDNS["cloudDNS"].(map[string]interface{}) + if got, want := externalDNSCloudDNS["workloadIdentityServiceAccount"], "external-dns@my-gcp-project.iam.gserviceaccount.com"; got != want { + t.Errorf("external-dns WI SA default = %v, want %v", got, want) + } + + // Kyverno invariant present. + pe := spec["policyEnforcement"].(map[string]interface{}) + if got := pe["clusterPolicy"].(map[string]interface{})["engine"]; got != "Kyverno" { + t.Errorf("clusterPolicy.engine = %v, want Kyverno", got) + } +} + +func TestTranslateGKE_OverrideServiceAccounts_RoundTrips(t *testing.T) { + yaml := `apiVersion: cli.educates.dev/v1alpha1 +kind: EducatesGKEConfig +gcp: + project: my-gcp-project + certManagerServiceAccount: custom-cm@my-gcp-project.iam.gserviceaccount.com + externalDNSServiceAccount: custom-edns@my-gcp-project.iam.gserviceaccount.com +domain: academy-01.google.educates.dev +acme: + email: ops@example.com +` + out, err := translateBytes(t, []byte(yaml)) + if err != nil { + t.Fatal(err) + } + spec := out.EducatesClusterConfig["spec"].(map[string]interface{}) + cloudDNS := spec["ingress"].(map[string]interface{})["certificates"].(map[string]interface{})["bundledCertManager"].(map[string]interface{})["acme"].(map[string]interface{})["solvers"].(map[string]interface{})["dns01"].(map[string]interface{})["cloudDNS"].(map[string]interface{}) + if got, want := cloudDNS["workloadIdentityServiceAccount"], "custom-cm@my-gcp-project.iam.gserviceaccount.com"; got != want { + t.Errorf("user-provided WI SA = %v, want %v (defaulting should NOT override)", got, want) + } +} + +func TestTranslateGKE_RenderRoundTripsAsValidYAML(t *testing.T) { + cfg := loadCfg(t, "gke-minimal.yaml").(*v1alpha1.EducatesGKEConfig) + out, _ := Translate(cfg, Options{}) + crs, err := RenderCRs(out) + if err != nil { + t.Fatal(err) + } + s := string(crs) + for _, want := range []string{ + "mode: Managed", + "envoyServiceType: LoadBalancer", + "issuerType: ACME", + "provider: CloudDNS", + "workloadIdentityServiceAccount: cert-manager@my-gcp-project", + } { + if !strings.Contains(s, want) { + t.Errorf("rendered output missing %q", want) + } + } +} + +// externalTLSTermination asserts the public edge is https when TLS is +// terminated at an external load balancer — it must surface as the +// SessionManager ingressOverrides protocol, and stay absent otherwise. +func TestTranslateGKE_ExternalTLSTermination_SetsSessionManagerProtocol(t *testing.T) { + out, err := translateBytes(t, []byte(` +apiVersion: cli.educates.dev/v1alpha1 +kind: EducatesGKEConfig +gcp: + project: my-gcp-project +domain: academy-01.google.educates.dev +acme: + email: ops@example.com +externalTLSTermination: true +`)) + if err != nil { + t.Fatalf("translate: %v", err) + } + spec := out.SessionManager["spec"].(map[string]interface{}) + overrides, ok := spec["ingressOverrides"].(map[string]interface{}) + if !ok { + t.Fatalf("sessionManager spec.ingressOverrides missing: %v", spec) + } + if got, want := overrides["protocol"], "https"; got != want { + t.Errorf("ingressOverrides.protocol = %v, want %v", got, want) + } + + // Default (field unset) must not emit the override. + cfg := loadCfg(t, "gke-minimal.yaml").(*v1alpha1.EducatesGKEConfig) + out, err = Translate(cfg, Options{}) + if err != nil { + t.Fatalf("Translate: %v", err) + } + spec = out.SessionManager["spec"].(map[string]interface{}) + if _, present := spec["ingressOverrides"]; present { + t.Errorf("ingressOverrides unexpectedly present without externalTLSTermination: %v", spec) + } +} diff --git a/client-programs/pkg/config/translator/inline.go b/client-programs/pkg/config/translator/inline.go new file mode 100644 index 000000000..e1c442915 --- /dev/null +++ b/client-programs/pkg/config/translator/inline.go @@ -0,0 +1,157 @@ +package translator + +import ( + "github.com/educates/educates-training-platform/client-programs/pkg/config/v1alpha1" +) + +// TranslateInline converts EducatesInlineConfig into the deployable +// output. ECC.spec is mode: Inline; everything funnels under spec.inline. +// No cluster services are installed by the operator. +// +// opts.CASecretName is ignored — Inline mode brings its own CA reference +// via the optional caCertificateSecret field. The signature stays uniform +// with TranslateLocal so the dispatcher in Translate() doesn't have to +// special-case. +func TranslateInline(cfg *v1alpha1.EducatesInlineConfig, _ Options) (*Output, error) { + out := &Output{ + OperatorChartValues: inlineOperatorChartValues(cfg), + EducatesClusterConfig: wrapCR(apiVersionConfig, "EducatesClusterConfig", inlineECCSpec(cfg)), + SecretsManager: wrapCR(apiVersionPlatform, "SecretsManager", inlineSecretsManagerSpec(cfg)), + SessionManager: wrapCR(apiVersionPlatform, "SessionManager", inlineSessionManagerSpec(cfg)), + } + if cfg.LookupService != nil && *cfg.LookupService { + out.LookupService = wrapCR(apiVersionPlatform, "LookupService", inlineLookupServiceSpec(cfg)) + } + return out, nil +} + +func inlineOperatorChartValues(cfg *v1alpha1.EducatesInlineConfig) map[string]interface{} { + return operatorChartValuesFor(cfg.Operator) +} + +// inlineECCSpec builds the mode: Inline ECC.spec. The CRD's CEL rule +// forbids any of the Managed-mode top-level fields when mode is Inline, +// so the spec is strictly {mode, inline}. +func inlineECCSpec(cfg *v1alpha1.EducatesInlineConfig) map[string]interface{} { + ingress := map[string]interface{}{ + "domain": cfg.Domain, + "ingressClassName": cfg.IngressClassName, + "wildcardCertificateSecretRef": map[string]interface{}{ + "name": cfg.WildcardCertificateSecret, + }, + } + if cfg.CACertificateSecret != "" { + ingress["caCertificateSecretRef"] = map[string]interface{}{"name": cfg.CACertificateSecret} + } + if cfg.ClusterIssuerName != "" { + ingress["clusterIssuerRef"] = map[string]interface{}{"name": cfg.ClusterIssuerName} + } + + inline := map[string]interface{}{ + "ingress": ingress, + "policyEnforcement": map[string]interface{}{ + "clusterPolicyEngine": cfg.PolicyEnforcement.ClusterEngine, + "workshopPolicyEngine": cfg.PolicyEnforcement.WorkshopEngine, + }, + } + if cfg.ImageRegistry.Prefix != "" || len(cfg.ImageRegistry.PullSecrets) > 0 { + ir := map[string]interface{}{} + if cfg.ImageRegistry.Prefix != "" { + ir["prefix"] = cfg.ImageRegistry.Prefix + } + if len(cfg.ImageRegistry.PullSecrets) > 0 { + refs := make([]interface{}, len(cfg.ImageRegistry.PullSecrets)) + for i, n := range cfg.ImageRegistry.PullSecrets { + refs[i] = map[string]interface{}{"name": n} + } + ir["pullSecrets"] = refs + } + inline["imageRegistry"] = ir + } + + return map[string]interface{}{ + "mode": "Inline", + "inline": inline, + } +} + +func inlineSecretsManagerSpec(cfg *v1alpha1.EducatesInlineConfig) map[string]interface{} { + spec := map[string]interface{}{} + if cfg.Operator.LogLevel != "" { + spec["logLevel"] = cfg.Operator.LogLevel + } + if ref := componentImageRef(cfg.ImageVersions, "secrets-manager"); ref != nil { + spec["image"] = ref + } + return spec +} + +func inlineLookupServiceSpec(cfg *v1alpha1.EducatesInlineConfig) map[string]interface{} { + spec := map[string]interface{}{ + "ingress": map[string]interface{}{"prefix": "lookup"}, + } + if cfg.Operator.LogLevel != "" { + spec["logLevel"] = cfg.Operator.LogLevel + } + if ref := componentImageRef(cfg.ImageVersions, "lookup-service"); ref != nil { + spec["image"] = ref + } + return spec +} + +// inlineSessionManagerSpec mirrors localSessionManagerSpec but drops the +// storage/blockedCidrs invariants — Inline mode runs on user clusters +// where storage classes and network rules are the cluster operator's +// concern, not Educates'. The cloud-metadata blockedCidrs are still +// relevant on cloud installs, but for laptop-derived defaults that's a +// local-scenario assumption we don't carry into BYO. +func inlineSessionManagerSpec(cfg *v1alpha1.EducatesInlineConfig) map[string]interface{} { + spec := map[string]interface{}{} + if cfg.Operator.LogLevel != "" { + spec["logLevel"] = cfg.Operator.LogLevel + } + if cfg.ExternalTLSTermination { + spec["ingressOverrides"] = map[string]interface{}{"protocol": "https"} + } + if cfg.WebsiteStyling.DefaultTheme != "" { + spec["defaultTheme"] = cfg.WebsiteStyling.DefaultTheme + } + if len(cfg.WebsiteStyling.ThemeDataRefs) > 0 { + spec["themes"] = themesFromDataRefs(cfg.WebsiteStyling.ThemeDataRefs) + } + if cfg.ImagePrePuller != nil { + spec["imagePrePuller"] = map[string]interface{}{"enabled": *cfg.ImagePrePuller} + } + applySessionManagerImageOverrides(spec, cfg.ImageVersions) + return spec +} + +// operatorChartValuesFor is the shared operator chart values builder. +// Inline + Local both call it; GKE/EKS will too in 11b/11c. +func operatorChartValuesFor(op v1alpha1.LocalOperatorConfig) map[string]interface{} { + values := map[string]interface{}{} + if op.Image.Repository != "" || op.Image.Tag != "" || op.Image.PullPolicy != "" { + image := map[string]interface{}{} + if op.Image.Repository != "" { + image["repository"] = op.Image.Repository + } + if op.Image.Tag != "" { + image["tag"] = op.Image.Tag + } + if op.Image.PullPolicy != "" { + image["pullPolicy"] = op.Image.PullPolicy + } + values["image"] = image + } + if len(op.ImagePullSecrets) > 0 { + secrets := make([]interface{}, len(op.ImagePullSecrets)) + for i, name := range op.ImagePullSecrets { + secrets[i] = map[string]interface{}{"name": name} + } + values["imagePullSecrets"] = secrets + } + if op.LogLevel != "" { + values["logLevel"] = op.LogLevel + } + return values +} diff --git a/client-programs/pkg/config/translator/inline_test.go b/client-programs/pkg/config/translator/inline_test.go new file mode 100644 index 000000000..db06f055d --- /dev/null +++ b/client-programs/pkg/config/translator/inline_test.go @@ -0,0 +1,133 @@ +package translator + +import ( + "strings" + "testing" + + "github.com/educates/educates-training-platform/client-programs/pkg/config/v1alpha1" +) + +func TestTranslateInline_Minimal_ModeInline(t *testing.T) { + cfg := loadCfg(t, "inline-minimal.yaml").(*v1alpha1.EducatesInlineConfig) + out, err := Translate(cfg, Options{}) // Inline ignores CASecret*; no opts needed + if err != nil { + t.Fatalf("Translate: %v", err) + } + + spec := out.EducatesClusterConfig["spec"].(map[string]interface{}) + if got, want := spec["mode"], "Inline"; got != want { + t.Errorf("spec.mode = %v, want %v", got, want) + } + // CEL forbids the Managed-mode top-level fields under Inline; ensure + // the translator doesn't accidentally emit any. + for _, forbidden := range []string{"ingress", "dns", "policyEnforcement", "imageRegistry", "infrastructure"} { + if _, set := spec[forbidden]; set { + t.Errorf("spec.%s set in Inline mode (forbidden by CRD CEL)", forbidden) + } + } + + inline := spec["inline"].(map[string]interface{}) + ingress := inline["ingress"].(map[string]interface{}) + if got, want := ingress["domain"], "workshop.test"; got != want { + t.Errorf("inline.ingress.domain = %v, want %v", got, want) + } + if got, want := ingress["ingressClassName"], "contour"; got != want { + t.Errorf("inline.ingress.ingressClassName = %v, want %v", got, want) + } + wildcardRef := ingress["wildcardCertificateSecretRef"].(map[string]interface{}) + if got, want := wildcardRef["name"], "educates-wildcard-tls"; got != want { + t.Errorf("wildcardCertificateSecretRef.name = %v, want %v", got, want) + } + if _, set := ingress["caCertificateSecretRef"]; set { + t.Errorf("caCertificateSecretRef set when not provided in config") + } + + // Default policy is Kyverno (matches CRD kubebuilder default). + pe := inline["policyEnforcement"].(map[string]interface{}) + if got, want := pe["clusterPolicyEngine"], "Kyverno"; got != want { + t.Errorf("clusterPolicyEngine default = %v, want %v", got, want) + } + if got, want := pe["workshopPolicyEngine"], "Kyverno"; got != want { + t.Errorf("workshopPolicyEngine default = %v, want %v", got, want) + } +} + +func TestTranslateInline_OpenShift_FullFieldPassthrough(t *testing.T) { + cfg := loadCfg(t, "inline-openshift.yaml").(*v1alpha1.EducatesInlineConfig) + out, err := Translate(cfg, Options{}) + if err != nil { + t.Fatalf("Translate: %v", err) + } + + inline := out.EducatesClusterConfig["spec"].(map[string]interface{})["inline"].(map[string]interface{}) + ingress := inline["ingress"].(map[string]interface{}) + if got, want := ingress["caCertificateSecretRef"].(map[string]interface{})["name"], "educates-wildcard-ca"; got != want { + t.Errorf("caCertificateSecretRef.name = %v, want %v", got, want) + } + + pe := inline["policyEnforcement"].(map[string]interface{}) + if got, want := pe["clusterPolicyEngine"], "OpenShiftSCC"; got != want { + t.Errorf("clusterPolicyEngine = %v, want %v", got, want) + } + if got, want := pe["workshopPolicyEngine"], "None"; got != want { + t.Errorf("workshopPolicyEngine = %v, want %v", got, want) + } + + ir := inline["imageRegistry"].(map[string]interface{}) + if got, want := ir["prefix"], "registry.internal.example.com/educates"; got != want { + t.Errorf("imageRegistry.prefix = %v, want %v", got, want) + } + pullSecrets := ir["pullSecrets"].([]interface{}) + if len(pullSecrets) != 1 { + t.Fatalf("pullSecrets len = %d, want 1", len(pullSecrets)) + } + if got, want := pullSecrets[0].(map[string]interface{})["name"], "internal-registry-pull"; got != want { + t.Errorf("pullSecrets[0].name = %v, want %v (k8s {name:} shape)", got, want) + } +} + +func TestTranslateInline_RenderRoundTripsAsValidYAML(t *testing.T) { + cfg := loadCfg(t, "inline-openshift.yaml").(*v1alpha1.EducatesInlineConfig) + out, _ := Translate(cfg, Options{}) + crs, err := RenderCRs(out) + if err != nil { + t.Fatalf("RenderCRs: %v", err) + } + s := string(crs) + for _, want := range []string{ + "mode: Inline", + "domain: workshops.example.com", + "clusterPolicyEngine: OpenShiftSCC", + "kind: EducatesClusterConfig", + "kind: SecretsManager", + "kind: SessionManager", + } { + if !strings.Contains(s, want) { + t.Errorf("rendered output missing %q", want) + } + } +} + +// Inline-mode BYO clusters behind a corporate load balancer use the +// same externalTLSTermination assertion as the cloud kinds. +func TestTranslateInline_ExternalTLSTermination_SetsSessionManagerProtocol(t *testing.T) { + out, err := translateBytes(t, []byte(` +apiVersion: cli.educates.dev/v1alpha1 +kind: EducatesInlineConfig +domain: workshops.example.com +ingressClassName: contour +wildcardCertificateSecret: wildcard-tls +externalTLSTermination: true +`)) + if err != nil { + t.Fatalf("translate: %v", err) + } + spec := out.SessionManager["spec"].(map[string]interface{}) + overrides, ok := spec["ingressOverrides"].(map[string]interface{}) + if !ok { + t.Fatalf("sessionManager spec.ingressOverrides missing: %v", spec) + } + if got, want := overrides["protocol"], "https"; got != want { + t.Errorf("ingressOverrides.protocol = %v, want %v", got, want) + } +} diff --git a/client-programs/pkg/config/translator/local.go b/client-programs/pkg/config/translator/local.go new file mode 100644 index 000000000..7b1449eab --- /dev/null +++ b/client-programs/pkg/config/translator/local.go @@ -0,0 +1,181 @@ +package translator + +import ( + "fmt" + + "github.com/educates/educates-training-platform/client-programs/pkg/config/v1alpha1" +) + +// TranslateLocal converts EducatesLocalConfig into the deployable output. +// +// Translator invariants applied here (per the locked Phase 5 design): +// - mode: Managed +// - ingress.ingressClassName: contour +// - ingress.controller.provider: BundledContour +// - ingress.certificates.provider: BundledCertManager +// - ingress.certificates.bundledCertManager.issuerType: CustomCA +// - policyEnforcement: BundledKyverno (cluster + workshop) +// +// The CustomCA caCertificateRef name and namespace come from opts — the +// caller (typically the cmd code) looks them up by domain via +// secrets.LocalCachedSecretForCertificateAuthority and supplies them +// here. Returns an error when opts.CASecretName is empty: the install +// cannot complete without a CA, so failing at translate time prevents +// late surprises at deploy time. +// +// Static field defaults (clusterAdmin true, lookupService true, +// imagePrePuller false, operator.logLevel info, cluster.listenAddress +// 127.0.0.1) have already been applied by EducatesLocalConfig.WithDefaults() +// at load time. +// +// Environment-dependent defaults are NOT applied here: +// - ingress.domain stays empty unless the caller set it (host-IP nip.io +// defaulting belongs upstream of the translator). +// - operator.image.tag stays as-is (CLI-binary-version defaulting +// belongs in command code that has access to the build info). +func TranslateLocal(cfg *v1alpha1.EducatesLocalConfig, opts Options) (*Output, error) { + if opts.CASecretName == "" { + return nil, fmt.Errorf("translator: CustomCA Secret name is required for EducatesLocalConfig; the caller must look it up by ingress.domain from the local secrets cache before translating") + } + out := &Output{ + OperatorChartValues: operatorChartValuesFor(cfg.Operator), + EducatesClusterConfig: wrapCR(apiVersionConfig, "EducatesClusterConfig", localECCSpec(cfg, opts)), + SecretsManager: wrapCR(apiVersionPlatform, "SecretsManager", localSecretsManagerSpec(cfg)), + SessionManager: wrapCR(apiVersionPlatform, "SessionManager", localSessionManagerSpec(cfg)), + } + if cfg.LookupService != nil && *cfg.LookupService { + out.LookupService = wrapCR(apiVersionPlatform, "LookupService", localLookupServiceSpec(cfg)) + } + return out, nil +} + +// localECCSpec builds the EducatesClusterConfig.spec for Local mode. +// Always Managed; always BundledContour + CustomCA cert-manager. +// caCertificateRef.name and (optionally) .namespace come from opts — +// the caller looked them up by ingress.domain in the local secrets cache. +func localECCSpec(cfg *v1alpha1.EducatesLocalConfig, opts Options) map[string]interface{} { + caRef := map[string]interface{}{"name": opts.CASecretName} + if opts.CASecretNamespace != "" { + caRef["namespace"] = opts.CASecretNamespace + } + + ingress := map[string]interface{}{ + "ingressClassName": "contour", + "controller": map[string]interface{}{ + "provider": "BundledContour", + // kind has no in-cluster LoadBalancer. Envoy is exposed as a + // ClusterIP Service, and the operator pairs ClusterIP with + // host ports (80/443) so the kind node's mapped 80/443 reach + // Envoy directly — the v3 kind topology. + "bundledContour": map[string]interface{}{ + "envoyServiceType": "ClusterIP", + }, + }, + "certificates": map[string]interface{}{ + "provider": "BundledCertManager", + "bundledCertManager": map[string]interface{}{ + "issuerType": "CustomCA", + "customCA": map[string]interface{}{ + "caCertificateRef": caRef, + }, + }, + }, + } + if cfg.Ingress.Domain != "" { + ingress["domain"] = cfg.Ingress.Domain + } + + spec := map[string]interface{}{ + "mode": "Managed", + "ingress": ingress, + // BundledKyverno invariant. clusterPolicy.engine and + // workshopPolicy.engine both default to Kyverno via kubebuilder + // markers, and kyverno.provider defaults to Bundled, but the + // PolicyEnforcement.{Cluster,Workshop}Policy fields are +required + // so the block must be present explicitly. + "policyEnforcement": map[string]interface{}{ + "clusterPolicy": map[string]interface{}{"engine": "Kyverno"}, + "workshopPolicy": map[string]interface{}{"engine": "Kyverno"}, + "kyverno": map[string]interface{}{"provider": "Bundled"}, + }, + } + return spec +} + +// localSecretsManagerSpec — near-empty spec; the operator derives +// image/resources from chart defaults + ECC status. An imageVersions +// entry named "secrets-manager" routes here as spec.image (the +// component has its own CR; it is not part of SessionManager's image +// inventory). +func localSecretsManagerSpec(cfg *v1alpha1.EducatesLocalConfig) map[string]interface{} { + spec := map[string]interface{}{} + if cfg.Operator.LogLevel != "" { + spec["logLevel"] = cfg.Operator.LogLevel + } + if ref := componentImageRef(cfg.ImageVersions, "secrets-manager"); ref != nil { + spec["image"] = ref + } + return spec +} + +// localLookupServiceSpec — minimal; ingress.prefix=lookup is the conventional +// hostname segment. An imageVersions entry named "lookup-service" routes +// here as spec.image. +func localLookupServiceSpec(cfg *v1alpha1.EducatesLocalConfig) map[string]interface{} { + spec := map[string]interface{}{ + "ingress": map[string]interface{}{ + "prefix": "lookup", + }, + } + if cfg.Operator.LogLevel != "" { + spec["logLevel"] = cfg.Operator.LogLevel + } + if ref := componentImageRef(cfg.ImageVersions, "lookup-service"); ref != nil { + spec["image"] = ref + } + return spec +} + +// localSessionManagerSpec carries the session-manager runtime knobs the +// CLI surfaces in the narrow EducatesLocalConfig shape. +// +// Locked invariants applied here: +// - storage.storageGroup: 1 +// - network.blockedCidrs: cloud metadata endpoints +// (169.254.169.254/32 covers AWS/GCP/Azure IMDS; +// fd00:ec2::254/128 covers AWS IMDS over IPv6). +// +// TODO(phase4-followup): clusterAdmin and secretPropagation have no +// landing field in the current SessionManager CRD. They are dropped here +// pending the CRD additions tracked in the v4 development plan. The +// operator will need spec.clusterAdmin (bool) and spec.secretPropagation +// (imagePullSecretNames list) before this translator can wire them up. +func localSessionManagerSpec(cfg *v1alpha1.EducatesLocalConfig) map[string]interface{} { + spec := map[string]interface{}{ + "storage": map[string]interface{}{ + "storageGroup": 1, + }, + "network": map[string]interface{}{ + "blockedCidrs": []interface{}{ + "169.254.169.254/32", + "fd00:ec2::254/128", + }, + }, + } + if cfg.Operator.LogLevel != "" { + spec["logLevel"] = cfg.Operator.LogLevel + } + if cfg.WebsiteStyling.DefaultTheme != "" { + spec["defaultTheme"] = cfg.WebsiteStyling.DefaultTheme + } + if len(cfg.WebsiteStyling.ThemeDataRefs) > 0 { + spec["themes"] = themesFromDataRefs(cfg.WebsiteStyling.ThemeDataRefs) + } + if cfg.ImagePrePuller != nil { + spec["imagePrePuller"] = map[string]interface{}{ + "enabled": *cfg.ImagePrePuller, + } + } + applySessionManagerImageOverrides(spec, cfg.ImageVersions) + return spec +} diff --git a/client-programs/pkg/config/translator/render.go b/client-programs/pkg/config/translator/render.go new file mode 100644 index 000000000..42ac4e920 --- /dev/null +++ b/client-programs/pkg/config/translator/render.go @@ -0,0 +1,72 @@ +package translator + +import ( + "bytes" + "encoding/json" + "fmt" + + "gopkg.in/yaml.v3" +) + +// RenderCRs serialises the four (or three) platform CRs in Output as a +// single multi-document YAML stream, in deploy order: +// 1. EducatesClusterConfig +// 2. SecretsManager +// 3. LookupService (omitted when nil) +// 4. SessionManager +// +// The order matches the controller dependency chain: ECC must be Ready +// before SecretsManager reconciles; SecretsManager must be Ready before +// SessionManager. LookupService is independent of SessionManager. +// +// yaml.v3 is used so the output has stable, alphabetical key ordering +// (yaml.v2 emits Go-map iteration order, which is randomised). +func RenderCRs(out *Output) ([]byte, error) { + docs := []map[string]interface{}{out.EducatesClusterConfig, out.SecretsManager} + if out.LookupService != nil { + docs = append(docs, out.LookupService) + } + docs = append(docs, out.SessionManager) + + var buf bytes.Buffer + enc := yaml.NewEncoder(&buf) + enc.SetIndent(2) + for _, doc := range docs { + if err := enc.Encode(doc); err != nil { + return nil, fmt.Errorf("encode CR %q: %w", doc["kind"], err) + } + } + if err := enc.Close(); err != nil { + return nil, err + } + return buf.Bytes(), nil +} + +// RenderOperatorValues serialises OperatorChartValues as a YAML values +// file, suitable for `helm install -f`. Empty map renders as "{}\n". +func RenderOperatorValues(out *Output) ([]byte, error) { + if out.OperatorChartValues == nil { + return []byte("{}\n"), nil + } + // Round-trip through JSON so key ordering is alphabetical (Go maps + // in YAML emit in iteration order; round-trip through encoding/json + // then yaml.v3 gives us a stable shape). + raw, err := json.Marshal(out.OperatorChartValues) + if err != nil { + return nil, err + } + var generic interface{} + if err := json.Unmarshal(raw, &generic); err != nil { + return nil, err + } + var buf bytes.Buffer + enc := yaml.NewEncoder(&buf) + enc.SetIndent(2) + if err := enc.Encode(generic); err != nil { + return nil, err + } + if err := enc.Close(); err != nil { + return nil, err + } + return buf.Bytes(), nil +} diff --git a/client-programs/pkg/config/translator/translator.go b/client-programs/pkg/config/translator/translator.go new file mode 100644 index 000000000..c78d24220 --- /dev/null +++ b/client-programs/pkg/config/translator/translator.go @@ -0,0 +1,160 @@ +// Package translator converts a CLI config kind into the deployable +// outputs: operator chart values + the four platform CRs +// (EducatesClusterConfig, SecretsManager, LookupService, SessionManager). +// +// Each kind has a Translate* method returning *Output. One renderer +// serialises Output to YAML. +// +// Defaulting of environment-dependent fields (e.g. ingress.domain from +// host IP, operator.image.tag from CLI binary version) does NOT happen +// here. Translate consumes whatever the loader produced + any caller-side +// pre-translate defaulting. This keeps the translator deterministic and +// unit-testable. +package translator + +import ( + "fmt" + "strings" + + "github.com/educates/educates-training-platform/client-programs/pkg/config/v1alpha1" +) + +// Output is the internal representation produced by every Translate*. The +// renderer serialises it to YAML. +// +// Each CR map carries the full resource (apiVersion + kind + metadata + +// spec). Nil means "do not deploy" for LookupService; the other three are +// always present for both scenario and escape kinds. +type Output struct { + OperatorChartValues map[string]interface{} + EducatesClusterConfig map[string]interface{} + SecretsManager map[string]interface{} + LookupService map[string]interface{} // nil = not deployed + SessionManager map[string]interface{} +} + +// Options carries caller-side inputs that are too environmental for the +// translator to compute on its own. +type Options struct { + // CASecretName is the name of the Secret in CASecretNamespace that + // holds the CustomCA's tls.crt + tls.key. Looked up by domain at + // the call site (typically via secrets.LocalCachedSecretForCertificateAuthority). + // Required for TranslateLocal; ignored for TranslateEscape (which + // passes user-declared CRs through verbatim). + CASecretName string + + // CASecretNamespace is the namespace of the CA Secret. Empty means + // the operator namespace. For laptop-mode installs aligned with v3, + // the caller sets this to "educates-secrets". + CASecretNamespace string +} + +// Translate dispatches on kind. Returns ErrUnknownKind if the loaded +// config is one this translator does not yet handle (e.g. the GKE/EKS/ +// Inline scenario kinds, which land later in Phase 5). +func Translate(cfg v1alpha1.Config, opts Options) (*Output, error) { + switch c := cfg.(type) { + case *v1alpha1.EducatesLocalConfig: + return TranslateLocal(c, opts) + case *v1alpha1.EducatesInlineConfig: + return TranslateInline(c, opts) + case *v1alpha1.EducatesGKEConfig: + return TranslateGKE(c, opts) + case *v1alpha1.EducatesEKSConfig: + return TranslateEKS(c, opts) + case *v1alpha1.EducatesConfig: + return TranslateEscape(c), nil + default: + return nil, fmt.Errorf("translator: unknown kind %q", cfg.GetKind()) + } +} + +// wrapCR returns a fully-formed CR resource map for the given platform +// apiVersion/kind/spec. metadata.name is always "cluster" — the four +// platform CRs are singletons. +func wrapCR(apiVersion, kind string, spec map[string]interface{}) map[string]interface{} { + if spec == nil { + spec = map[string]interface{}{} + } + return map[string]interface{}{ + "apiVersion": apiVersion, + "kind": kind, + "metadata": map[string]interface{}{"name": "cluster"}, + "spec": spec, + } +} + +// themesFromDataRefs translates CLI-level themeDataRefs (Secret +// name+namespace pairs) into the SessionManager CRD's themes list — +// one Secret-sourced Theme per ref, named after its backing Secret. +// (An earlier {"dataRefs": [...]} shape predated the CRD's +// ThemeSource secretRef field and never matched the schema.) +func themesFromDataRefs(refs []v1alpha1.ThemeDataRef) []interface{} { + themes := make([]interface{}, len(refs)) + for i, r := range refs { + themes[i] = map[string]interface{}{ + "name": r.Name, + "source": map[string]interface{}{ + "type": "Secret", + "secretRef": map[string]interface{}{ + "name": r.Name, + "namespace": r.Namespace, + }, + }, + } + } + return themes +} + +// splitImageRef splits a full image reference into repository and tag +// on the last ':' after the last '/'. A reference without a tag comes +// back with an empty tag (the charts fall through to Chart.AppVersion). +// Digest-pinned references cannot round-trip through repository+tag +// shaped CR fields and are returned whole as the repository. +func splitImageRef(ref string) (repository, tag string) { + if strings.Contains(ref, "@") { + return ref, "" + } + slash := strings.LastIndex(ref, "/") + if colon := strings.LastIndex(ref, ":"); colon > slash { + return ref[:colon], ref[colon+1:] + } + return ref, "" +} + +// componentImageRef returns the ImageRef-shaped {repository, tag} map +// for the named imageVersions entry, or nil when absent. Used to route +// the "secrets-manager" and "lookup-service" entries onto their own +// CRs' spec.image — those two components are not part of the +// SessionManager chart's image inventory, so an overrides entry there +// would be silently ignored. +func componentImageRef(ivs []v1alpha1.ImageVersion, name string) map[string]interface{} { + for _, iv := range ivs { + if iv.Name == name { + repo, tag := splitImageRef(iv.Image) + return map[string]interface{}{"repository": repo, "tag": tag} + } + } + return nil +} + +// applySessionManagerImageOverrides sets spec.images.overrides from +// the imageVersions entries, excluding the names routed to other CRs +// by componentImageRef. +func applySessionManagerImageOverrides(spec map[string]interface{}, ivs []v1alpha1.ImageVersion) { + overrides := make([]interface{}, 0, len(ivs)) + for _, iv := range ivs { + if iv.Name == "secrets-manager" || iv.Name == "lookup-service" { + continue + } + overrides = append(overrides, map[string]interface{}{"name": iv.Name, "image": iv.Image}) + } + if len(overrides) > 0 { + spec["images"] = map[string]interface{}{"overrides": overrides} + } +} + +const ( + apiVersionConfig = "config.educates.dev/v1alpha1" + apiVersionPlatform = "platform.educates.dev/v1alpha1" +) diff --git a/client-programs/pkg/config/translator/translator_test.go b/client-programs/pkg/config/translator/translator_test.go new file mode 100644 index 000000000..5312fc148 --- /dev/null +++ b/client-programs/pkg/config/translator/translator_test.go @@ -0,0 +1,464 @@ +package translator + +import ( + "path/filepath" + "strings" + "testing" + + "github.com/educates/educates-training-platform/client-programs/pkg/config" + "github.com/educates/educates-training-platform/client-programs/pkg/config/v1alpha1" +) + +func loadCfg(t *testing.T, fixture string) v1alpha1.Config { + t.Helper() + cfg, err := config.Load(filepath.Join("..", "testdata", fixture)) + if err != nil { + t.Fatalf("Load %s: %v", fixture, err) + } + return cfg +} + +// testOpts supplies a non-empty CA secret name so EducatesLocalConfig +// translation doesn't fail validation. Cluster-side secrets cache +// integration is exercised by the command-level tests. +func testOpts() Options { + return Options{CASecretName: "test-ca", CASecretNamespace: "educates-secrets"} +} + +// translateBytes is a load+translate helper for tests that build YAML +// inline (rather than referencing a testdata file). Shorter than +// writing every variant fixture to disk. +func translateBytes(t *testing.T, b []byte) (*Output, error) { + t.Helper() + cfg, err := config.LoadBytes(b, "inline-test") + if err != nil { + return nil, err + } + return Translate(cfg, Options{}) +} + +func TestTranslateLocal_EmptyConfig_AppliesInvariants(t *testing.T) { + cfg := loadCfg(t, "local-empty.yaml") + out, err := Translate(cfg, testOpts()) + if err != nil { + t.Fatalf("Translate: %v", err) + } + + ecc := out.EducatesClusterConfig + if got, want := ecc["apiVersion"], "config.educates.dev/v1alpha1"; got != want { + t.Errorf("ECC apiVersion = %v, want %v", got, want) + } + if got, want := ecc["kind"], "EducatesClusterConfig"; got != want { + t.Errorf("ECC kind = %v, want %v", got, want) + } + + spec := ecc["spec"].(map[string]interface{}) + if got, want := spec["mode"], "Managed"; got != want { + t.Errorf("spec.mode = %v, want %v", got, want) + } + + ingress := spec["ingress"].(map[string]interface{}) + if got, want := ingress["ingressClassName"], "contour"; got != want { + t.Errorf("ingress.ingressClassName = %v, want %v", got, want) + } + if _, set := ingress["domain"]; set { + t.Errorf("ingress.domain set unexpectedly: %v (host-IP defaulting belongs upstream)", ingress["domain"]) + } + + certs := ingress["certificates"].(map[string]interface{}) + if got, want := certs["provider"], "BundledCertManager"; got != want { + t.Errorf("certificates.provider = %v, want %v", got, want) + } + cm := certs["bundledCertManager"].(map[string]interface{}) + if got, want := cm["issuerType"], "CustomCA"; got != want { + t.Errorf("issuerType = %v, want %v", got, want) + } + + // Defaults from WithDefaults flow through: LookupService=true → present; + // imagePrePuller=false → SessionManager has imagePrePuller.enabled: false; + // logLevel=info → on every spec. + if out.LookupService == nil { + t.Error("LookupService = nil, want present (default lookupService=true)") + } + sm := out.SessionManager["spec"].(map[string]interface{}) + if got, want := sm["logLevel"], "info"; got != want { + t.Errorf("SessionManager logLevel = %v, want %v", got, want) + } + ipp := sm["imagePrePuller"].(map[string]interface{}) + if got, want := ipp["enabled"], false; got != want { + t.Errorf("imagePrePuller.enabled = %v, want %v", got, want) + } +} + +// TestTranslateLocal_AllLockedInvariants is the regression backstop for +// the locked Phase 5 invariants. Every row here corresponds to a single +// bullet in the "Translator invariants" section of the locked design +// (see ~/.claude/plans/reflective-dazzling-finch.md and the project +// memory). A row failing means either the translator silently dropped +// the invariant (bug; restore it) or the design changed (update the +// row + the design doc together). +// +// Adding a new locked invariant should land both a translator change +// AND a row here in the same commit. +func TestTranslateLocal_AllLockedInvariants(t *testing.T) { + cfg := loadCfg(t, "local-empty.yaml") + out, err := Translate(cfg, testOpts()) + if err != nil { + t.Fatalf("Translate: %v", err) + } + + cases := []struct { + cr string + path string // dotted path under .spec + want interface{} + }{ + // EducatesClusterConfig invariants + {"EducatesClusterConfig", "mode", "Managed"}, + {"EducatesClusterConfig", "ingress.ingressClassName", "contour"}, + {"EducatesClusterConfig", "ingress.controller.provider", "BundledContour"}, + {"EducatesClusterConfig", "ingress.controller.bundledContour.envoyServiceType", "ClusterIP"}, + {"EducatesClusterConfig", "ingress.certificates.provider", "BundledCertManager"}, + {"EducatesClusterConfig", "ingress.certificates.bundledCertManager.issuerType", "CustomCA"}, + {"EducatesClusterConfig", "policyEnforcement.clusterPolicy.engine", "Kyverno"}, + {"EducatesClusterConfig", "policyEnforcement.workshopPolicy.engine", "Kyverno"}, + {"EducatesClusterConfig", "policyEnforcement.kyverno.provider", "Bundled"}, + + // SessionManager invariants + {"SessionManager", "storage.storageGroup", 1}, + } + specs := map[string]map[string]interface{}{ + "EducatesClusterConfig": out.EducatesClusterConfig["spec"].(map[string]interface{}), + "SessionManager": out.SessionManager["spec"].(map[string]interface{}), + } + for _, tc := range cases { + t.Run(tc.cr+":"+tc.path, func(t *testing.T) { + got, ok := getNested(specs[tc.cr], tc.path) + if !ok { + t.Fatalf("invariant missing: %s.spec.%s (translator dropped it?)", tc.cr, tc.path) + } + if got != tc.want { + t.Errorf("invariant value drift: %s.spec.%s = %v (%T), want %v (%T)", + tc.cr, tc.path, got, got, tc.want, tc.want) + } + }) + } + + // blockedCidrs is a list — assert separately so a single missing + // CIDR shows up cleanly. + netRaw, ok := getNested(specs["SessionManager"], "network.blockedCidrs") + if !ok { + t.Fatal("invariant missing: SessionManager.spec.network.blockedCidrs") + } + cidrs, ok := netRaw.([]interface{}) + if !ok { + t.Fatalf("network.blockedCidrs type = %T, want []interface{}", netRaw) + } + for _, want := range []string{"169.254.169.254/32", "fd00:ec2::254/128"} { + found := false + for _, c := range cidrs { + if c == want { + found = true + break + } + } + if !found { + t.Errorf("blockedCidrs missing %q (got %v)", want, cidrs) + } + } +} + +// getNested walks a nested map[string]interface{} by dotted path. +// Returns (value, true) on hit, (nil, false) when any segment is +// missing or the intermediate node isn't a map. +func getNested(root map[string]interface{}, path string) (interface{}, bool) { + segs := strings.Split(path, ".") + var cur interface{} = root + for _, s := range segs { + m, ok := cur.(map[string]interface{}) + if !ok { + return nil, false + } + v, exists := m[s] + if !exists { + return nil, false + } + cur = v + } + return cur, true +} + +func TestTranslateLocal_EmptyConfig_AppliesBundledKyvernoInvariant(t *testing.T) { + cfg := loadCfg(t, "local-empty.yaml") + out, err := Translate(cfg, testOpts()) + if err != nil { + t.Fatalf("Translate: %v", err) + } + spec := out.EducatesClusterConfig["spec"].(map[string]interface{}) + pe, ok := spec["policyEnforcement"].(map[string]interface{}) + if !ok { + t.Fatalf("spec.policyEnforcement = %v, want map (BundledKyverno invariant)", spec["policyEnforcement"]) + } + if got := pe["clusterPolicy"].(map[string]interface{})["engine"]; got != "Kyverno" { + t.Errorf("clusterPolicy.engine = %v, want Kyverno", got) + } + if got := pe["workshopPolicy"].(map[string]interface{})["engine"]; got != "Kyverno" { + t.Errorf("workshopPolicy.engine = %v, want Kyverno", got) + } + if got := pe["kyverno"].(map[string]interface{})["provider"]; got != "Bundled" { + t.Errorf("kyverno.provider = %v, want Bundled", got) + } +} + +func TestTranslateLocal_LookupServiceDisabled_OmitsCR(t *testing.T) { + cfg := loadCfg(t, "local-full.yaml") // sets lookupService: false + out, _ := Translate(cfg, testOpts()) + if out.LookupService != nil { + t.Errorf("LookupService = %v, want nil", out.LookupService) + } +} + +func TestTranslateLocal_FullConfig_OperatorChartValues(t *testing.T) { + cfg := loadCfg(t, "local-full.yaml") + out, _ := Translate(cfg, testOpts()) + + values := out.OperatorChartValues + image := values["image"].(map[string]interface{}) + if got, want := image["repository"], "ghcr.io/educates/educates-operator"; got != want { + t.Errorf("image.repository = %v, want %v", got, want) + } + if got, want := image["tag"], "4.0.0"; got != want { + t.Errorf("image.tag = %v, want %v", got, want) + } + + secrets := values["imagePullSecrets"].([]interface{}) + if len(secrets) != 1 { + t.Fatalf("imagePullSecrets len = %d, want 1", len(secrets)) + } + if got, want := secrets[0].(map[string]interface{})["name"], "operator-pull-secret"; got != want { + t.Errorf("imagePullSecrets[0].name = %v, want %v (k8s [{name:}] shape)", got, want) + } + + if got, want := values["logLevel"], "debug"; got != want { + t.Errorf("operator logLevel = %v, want %v", got, want) + } +} + +func TestTranslateLocal_FullConfig_SessionManagerFields(t *testing.T) { + cfg := loadCfg(t, "local-full.yaml") + out, _ := Translate(cfg, testOpts()) + sm := out.SessionManager["spec"].(map[string]interface{}) + + if got, want := sm["defaultTheme"], "my-theme-data"; got != want { + t.Errorf("defaultTheme = %v, want %v", got, want) + } + themes := sm["themes"].([]interface{}) + if len(themes) != 1 { + t.Fatalf("themes len = %d", len(themes)) + } + theme := themes[0].(map[string]interface{}) + source := theme["source"].(map[string]interface{}) + if got, want := source["type"], "Secret"; got != want { + t.Errorf("source.type = %v, want %v", got, want) + } + secretRef := source["secretRef"].(map[string]interface{}) + if got, want := secretRef["namespace"], "educates"; got != want { + t.Errorf("secretRef.namespace = %v, want %v", got, want) + } + if got, want := theme["name"], secretRef["name"]; got != want { + t.Errorf("theme.name = %v, want backing Secret name %v", got, want) + } + + ipp := sm["imagePrePuller"].(map[string]interface{}) + if got, want := ipp["enabled"], true; got != want { + t.Errorf("imagePrePuller.enabled = %v, want true", got) + } + + images := sm["images"].(map[string]interface{}) + overrides := images["overrides"].([]interface{}) + if len(overrides) != 1 { + t.Fatalf("overrides len = %d", len(overrides)) + } +} + +func TestTranslateEscape_Minimal_Passthrough(t *testing.T) { + cfg := loadCfg(t, "escape-minimal.yaml") + out, err := Translate(cfg, testOpts()) + if err != nil { + t.Fatalf("Translate: %v", err) + } + + // All 4 CRs present, all specs empty (no fields declared by user). + for _, kind := range []struct { + name string + got map[string]interface{} + }{ + {"ECC", out.EducatesClusterConfig}, + {"SecretsManager", out.SecretsManager}, + {"SessionManager", out.SessionManager}, + } { + if kind.got == nil { + t.Errorf("%s: nil, want present", kind.name) + } + } + // LookupService omitted (cfg.LookupService is nil). + if out.LookupService != nil { + t.Errorf("LookupService = %v, want nil", out.LookupService) + } + // No CLI-side defaults: operator chart values are empty. + if len(out.OperatorChartValues) != 0 { + t.Errorf("OperatorChartValues = %v, want empty (no defaulting on escape kind)", out.OperatorChartValues) + } +} + +func TestTranslateEscape_WithTarget_PassesAllSections(t *testing.T) { + cfg := loadCfg(t, "escape-with-target.yaml") + out, _ := Translate(cfg, testOpts()) + + if got, want := out.OperatorChartValues["logLevel"], "debug"; got != want { + t.Errorf("operator logLevel = %v, want %v", got, want) + } + // SecretsManager spec is {} from the fixture; still wrapped. + if out.SecretsManager["spec"] == nil { + t.Errorf("SecretsManager.spec = nil, want {}") + } +} + +func TestRender_CRs_MultiDocYAML(t *testing.T) { + cfg := loadCfg(t, "local-empty.yaml") + out, _ := Translate(cfg, testOpts()) + yamlBytes, err := RenderCRs(out) + if err != nil { + t.Fatalf("RenderCRs: %v", err) + } + + s := string(yamlBytes) + // Multi-doc: 3 docs (ECC + SecretsManager + SessionManager since + // LookupService default is true → 4 docs). Each doc starts at the + // beginning of a line. Count occurrences of "kind:" at line start + // — yaml.v3 emits one per top-level map. + if got := strings.Count(s, "\nkind:") + strings.Count(s, "kind:"); got < 4 { + t.Errorf("expected at least 4 'kind:' lines (4 CRs), got %d in:\n%s", got, s) + } + for _, kind := range []string{"EducatesClusterConfig", "SecretsManager", "LookupService", "SessionManager"} { + if !strings.Contains(s, "kind: "+kind) { + t.Errorf("output missing kind %s:\n%s", kind, s) + } + } + // metadata.name: cluster on each CR. + if got := strings.Count(s, "name: cluster"); got < 4 { + t.Errorf("expected at least 4 'name: cluster' lines, got %d", got) + } +} + +func TestRender_OperatorValues_Empty(t *testing.T) { + cfg := loadCfg(t, "local-empty.yaml") + out, _ := Translate(cfg, testOpts()) + values, err := RenderOperatorValues(out) + if err != nil { + t.Fatalf("RenderOperatorValues: %v", err) + } + // Empty local config has no operator overrides → just "{}\n". + // (logLevel comes from WithDefaults, so actually it will have logLevel: info.) + s := string(values) + if !strings.Contains(s, "logLevel: info") { + t.Errorf("expected logLevel: info in values, got:\n%s", s) + } +} + +func TestRender_OperatorValues_Full(t *testing.T) { + cfg := loadCfg(t, "local-full.yaml") + out, _ := Translate(cfg, testOpts()) + values, _ := RenderOperatorValues(out) + s := string(values) + for _, want := range []string{ + "repository: ghcr.io/educates/educates-operator", + "tag: 4.0.0", + "logLevel: debug", + "name: operator-pull-secret", + } { + if !strings.Contains(s, want) { + t.Errorf("values missing %q:\n%s", want, s) + } + } +} + +func TestTranslateLocal_RoutesComponentImageOverrides(t *testing.T) { + cfg := &v1alpha1.EducatesLocalConfig{ + ImageVersions: []v1alpha1.ImageVersion{ + {Name: "secrets-manager", Image: "localhost:5001/educates-secrets-manager:latest"}, + {Name: "lookup-service", Image: "localhost:5001/educates-lookup-service:latest"}, + {Name: "training-portal", Image: "localhost:5001/educates-training-portal:latest"}, + }, + } + cfg.WithDefaults() // lookupService defaults to enabled + + out, err := TranslateLocal(cfg, testOpts()) + if err != nil { + t.Fatalf("TranslateLocal: %v", err) + } + + smgr := out.SecretsManager["spec"].(map[string]interface{}) + image, ok := smgr["image"].(map[string]interface{}) + if !ok { + t.Fatal("secrets-manager entry did not land on SecretsManager.spec.image") + } + if image["repository"] != "localhost:5001/educates-secrets-manager" || image["tag"] != "latest" { + t.Errorf("SecretsManager.spec.image = %v", image) + } + + lsvc := out.LookupService["spec"].(map[string]interface{}) + image, ok = lsvc["image"].(map[string]interface{}) + if !ok { + t.Fatal("lookup-service entry did not land on LookupService.spec.image") + } + if image["repository"] != "localhost:5001/educates-lookup-service" || image["tag"] != "latest" { + t.Errorf("LookupService.spec.image = %v", image) + } + + sm := out.SessionManager["spec"].(map[string]interface{}) + overrides := sm["images"].(map[string]interface{})["overrides"].([]interface{}) + if len(overrides) != 1 { + t.Fatalf("SessionManager overrides should hold only training-portal, got %v", overrides) + } + if overrides[0].(map[string]interface{})["name"] != "training-portal" { + t.Errorf("overrides[0] = %v", overrides[0]) + } +} + +// TestTranslateLocal_DevCLIDefaults_EndToEnd is the dev-build contract: +// ApplyCLIDefaults with a non-semver version followed by translation +// must point every platform component at the compiled-in registry. +func TestTranslateLocal_DevCLIDefaults_EndToEnd(t *testing.T) { + cfg := (&v1alpha1.EducatesLocalConfig{}).WithDefaults().ApplyCLIDefaults("latest", "localhost:5001") + + out, err := TranslateLocal(cfg, testOpts()) + if err != nil { + t.Fatalf("TranslateLocal: %v", err) + } + + values := out.OperatorChartValues["image"].(map[string]interface{}) + if values["repository"] != "localhost:5001/educates-operator" || values["tag"] != "latest" { + t.Errorf("operator chart image = %v", values) + } + + smgr := out.SecretsManager["spec"].(map[string]interface{}) + if image, ok := smgr["image"].(map[string]interface{}); !ok || image["tag"] != "latest" { + t.Errorf("SecretsManager.spec.image = %v", smgr["image"]) + } + + sm := out.SessionManager["spec"].(map[string]interface{}) + overrides := sm["images"].(map[string]interface{})["overrides"].([]interface{}) + found := map[string]string{} + for _, o := range overrides { + m := o.(map[string]interface{}) + found[m["name"].(string)] = m["image"].(string) + } + for _, name := range []string{"session-manager", "training-portal", "base-environment", "pause-container", "node-ca-injector"} { + if found[name] != "localhost:5001/educates-"+name+":latest" { + t.Errorf("SessionManager override %s = %q", name, found[name]) + } + } + if _, present := found["secrets-manager"]; present { + t.Error("secrets-manager leaked into SessionManager overrides instead of routing to its CR") + } +} diff --git a/client-programs/pkg/config/v1alpha1/eks.go b/client-programs/pkg/config/v1alpha1/eks.go new file mode 100644 index 000000000..1b1be8b0d --- /dev/null +++ b/client-programs/pkg/config/v1alpha1/eks.go @@ -0,0 +1,113 @@ +package v1alpha1 + +const KindEducatesEKSConfig = "EducatesEKSConfig" + +// EducatesEKSConfig is the EKS production scenario kind. All cluster +// services are operator-installed and authenticated via IRSA (IAM Roles +// for Service Accounts) — no static credentials anywhere. +// +// Locked invariants applied by TranslateEKS: +// - mode: Managed +// - ingress.ingressClassName: contour +// - ingress.controller.provider: BundledContour +// bundledContour.envoyServiceType: LoadBalancer +// - ingress.certificates.provider: BundledCertManager +// - ingress.certificates.bundledCertManager.issuerType: ACME +// acme.solvers.dns01.provider: Route53 +// - dns.provider: BundledExternalDNS +// bundledExternalDNS.provider: Route53 +// - policyEnforcement: BundledKyverno (cluster + workshop) +type EducatesEKSConfig struct { + TypeMeta `yaml:",inline"` + + // AWS carries the account + Route53 + IAM role configuration. + // accountId, region, and route53HostedZoneId are required; both IRSA + // role ARNs default from accountId when empty. + AWS AWSConfig `yaml:"aws"` + + // Domain is the wildcard ingress subdomain. Required. + Domain string `yaml:"domain"` + + // ACME carries the cert-manager ACME config. Required: email. + // (Shared shape with EducatesGKEConfig.) + ACME ACMEConfig `yaml:"acme"` + + // ExternalTLSTermination asserts that TLS for the ingress domain is + // terminated outside the cluster (cloud load balancer or proxy + // forwarding plain HTTP inward). Generated portal and workshop URLs + // use https regardless of in-cluster certificate presence. Maps to + // SessionManager.spec.ingressOverrides.protocol: https. + ExternalTLSTermination bool `yaml:"externalTLSTermination,omitempty"` + + // Top-level toggles shared with EducatesLocalConfig. Defaults: + // clusterAdmin=false, lookupService=true, imagePrePuller=false. + ClusterAdmin *bool `yaml:"clusterAdmin,omitempty"` + LookupService *bool `yaml:"lookupService,omitempty"` + ImagePrePuller *bool `yaml:"imagePrePuller,omitempty"` + WebsiteStyling LocalWebsiteStylingConfig `yaml:"websiteStyling,omitempty"` + SecretPropagation LocalSecretPropagationConfig `yaml:"secretPropagation,omitempty"` + ImageVersions []ImageVersion `yaml:"imageVersions,omitempty"` + Operator LocalOperatorConfig `yaml:"operator,omitempty"` +} + +// AWSConfig is the AWS envelope for EducatesEKSConfig. +type AWSConfig struct { + // AccountId is the 12-digit AWS account that owns the Route53 zone + // and the IRSA IAM roles. Required. + AccountId string `yaml:"accountId"` + + // Region is the AWS region. Required (Route53 hosted-zone API + // calls and ACME-DNS01 challenges go through this region). + Region string `yaml:"region"` + + // Route53HostedZoneId names the Route53 hosted zone for the + // wildcard domain. Required. + Route53HostedZoneId string `yaml:"route53HostedZoneId"` + + // CertManagerRoleARN is the IAM role assumed by the cert-manager + // K8s ServiceAccount via IRSA. Empty defaults to + // arn:aws:iam:::role/educates-cert-manager. + CertManagerRoleARN string `yaml:"certManagerRoleARN,omitempty"` + + // ExternalDNSRoleARN is the IAM role assumed by the external-dns + // K8s ServiceAccount via IRSA. Empty defaults to + // arn:aws:iam:::role/educates-external-dns. + ExternalDNSRoleARN string `yaml:"externalDNSRoleARN,omitempty"` +} + +func (c *EducatesEKSConfig) WithDefaults() *EducatesEKSConfig { + if c.ClusterAdmin == nil { + f := false + c.ClusterAdmin = &f + } + if c.LookupService == nil { + t := true + c.LookupService = &t + } + if c.ImagePrePuller == nil { + f := false + c.ImagePrePuller = &f + } + if c.Operator.LogLevel == "" { + c.Operator.LogLevel = "info" + } + if c.AWS.AccountId != "" { + if c.AWS.CertManagerRoleARN == "" { + c.AWS.CertManagerRoleARN = "arn:aws:iam::" + c.AWS.AccountId + ":role/educates-cert-manager" + } + if c.AWS.ExternalDNSRoleARN == "" { + c.AWS.ExternalDNSRoleARN = "arn:aws:iam::" + c.AWS.AccountId + ":role/educates-external-dns" + } + } + return c +} + +func (c *EducatesEKSConfig) ApplyCLIDefaults(projectVersion, imageRepository string) *EducatesEKSConfig { + if c.Operator.Image.Repository == "" && imageRepository != "" { + c.Operator.Image.Repository = imageRepository + "/educates-operator" + } + if c.Operator.Image.Tag == "" && projectVersion != "" { + c.Operator.Image.Tag = projectVersion + } + return c +} diff --git a/client-programs/pkg/config/v1alpha1/escape.go b/client-programs/pkg/config/v1alpha1/escape.go new file mode 100644 index 000000000..e3b0e3e25 --- /dev/null +++ b/client-programs/pkg/config/v1alpha1/escape.go @@ -0,0 +1,45 @@ +package v1alpha1 + +const KindEducatesConfig = "EducatesConfig" + +// EducatesConfig is the escape-hatch CLI config kind. Its body mirrors the +// four platform CRDs verbatim (layout B1: section keys = camelCase CRD kind, +// body = CR .spec). The CLI wraps apiVersion/kind/metadata.name at translate +// time and applies the result without further transformation. +// +// Per the locked design: +// - No CLI-inferred defaults (no host-IP nip.io, no auto-injected TLS). +// - No invariants. Every CRD field is settable. +// - Static CRD defaults still apply at apply-time via apiserver defaulting. +// +// The CR-spec sections are passed through as untyped maps; the schema (not +// Go types) is the source of truth for their shape. +type EducatesConfig struct { + TypeMeta `yaml:",inline"` + + // Target carries CLI-side-effect inputs (kind cluster bootstrap + + // macOS resolver). Optional; when absent the CLI just applies the + // declared CRs with no side effects. provider drives which side + // effects run. + Target *EducatesConfigTarget `yaml:"target,omitempty"` + + // Operator chart values surface — same fields as on every scenario kind. + Operator LocalOperatorConfig `yaml:"operator,omitempty"` + + // CR-spec passthrough sections. Untyped on purpose: the JSON schema + // (generated from the CRDs) is the source of truth for field shape. + // Omitted LookupService means it is not deployed. + EducatesClusterConfig map[string]interface{} `yaml:"educatesClusterConfig,omitempty"` + SecretsManager map[string]interface{} `yaml:"secretsManager,omitempty"` + LookupService map[string]interface{} `yaml:"lookupService,omitempty"` + SessionManager map[string]interface{} `yaml:"sessionManager,omitempty"` +} + +// EducatesConfigTarget carries CLI-side-effect inputs. cluster/resolver +// reuse the same Go types as EducatesLocalConfig so the kind cluster + macOS +// resolver code paths can accept either kind interchangeably. +type EducatesConfigTarget struct { + Provider string `yaml:"provider,omitempty"` + Cluster LocalClusterConfig `yaml:"cluster,omitempty"` + Resolver LocalResolverConfig `yaml:"resolver,omitempty"` +} diff --git a/client-programs/pkg/config/v1alpha1/gke.go b/client-programs/pkg/config/v1alpha1/gke.go new file mode 100644 index 000000000..5dadc0d63 --- /dev/null +++ b/client-programs/pkg/config/v1alpha1/gke.go @@ -0,0 +1,125 @@ +package v1alpha1 + +const KindEducatesGKEConfig = "EducatesGKEConfig" + +// EducatesGKEConfig is the GKE production scenario kind. All cluster +// services are operator-installed and authenticated via Workload +// Identity — no static credentials anywhere. +// +// Locked invariants applied by TranslateGKE: +// - mode: Managed +// - ingress.ingressClassName: contour +// - ingress.controller.provider: BundledContour +// bundledContour.envoyServiceType: LoadBalancer +// - ingress.certificates.provider: BundledCertManager +// - ingress.certificates.bundledCertManager.issuerType: ACME +// acme.solvers.dns01.provider: CloudDNS +// - dns.provider: BundledExternalDNS +// bundledExternalDNS.provider: CloudDNS +// - policyEnforcement: BundledKyverno (cluster + workshop) +// +// User-provided fields are narrow on purpose. Power users who need +// non-WI auth, alternate Contour envoyServiceType, or different policy +// engines drop to the EducatesConfig escape hatch. +type EducatesGKEConfig struct { + TypeMeta `yaml:",inline"` + + // GCP carries the project + service-account configuration. project + // is required; both WI service-account emails default from project + // when empty. + GCP GCPConfig `yaml:"gcp"` + + // Domain is the wildcard ingress subdomain. Required. + Domain string `yaml:"domain"` + + // ACME carries the cert-manager ACME config. email is required; + // server defaults to Let's Encrypt production at CRD level. + ACME ACMEConfig `yaml:"acme"` + + // ExternalTLSTermination asserts that TLS for the ingress domain is + // terminated outside the cluster (cloud load balancer or proxy + // forwarding plain HTTP inward). Generated portal and workshop URLs + // use https regardless of in-cluster certificate presence. Maps to + // SessionManager.spec.ingressOverrides.protocol: https. + ExternalTLSTermination bool `yaml:"externalTLSTermination,omitempty"` + + // Top-level toggles shared with EducatesLocalConfig. Defaults per + // the locked design: clusterAdmin=false, lookupService=true, + // imagePrePuller=false. + ClusterAdmin *bool `yaml:"clusterAdmin,omitempty"` + LookupService *bool `yaml:"lookupService,omitempty"` + ImagePrePuller *bool `yaml:"imagePrePuller,omitempty"` + WebsiteStyling LocalWebsiteStylingConfig `yaml:"websiteStyling,omitempty"` + SecretPropagation LocalSecretPropagationConfig `yaml:"secretPropagation,omitempty"` + ImageVersions []ImageVersion `yaml:"imageVersions,omitempty"` + Operator LocalOperatorConfig `yaml:"operator,omitempty"` +} + +// GCPConfig is the GCP envelope for EducatesGKEConfig. +type GCPConfig struct { + // Project is the GCP project that owns the CloudDNS zone and the + // Workload Identity service accounts. Required. + Project string `yaml:"project"` + + // CertManagerServiceAccount is the GCP service-account email bound + // to the cert-manager K8s ServiceAccount via Workload Identity. + // Empty defaults to cert-manager@.iam.gserviceaccount.com. + CertManagerServiceAccount string `yaml:"certManagerServiceAccount,omitempty"` + + // ExternalDNSServiceAccount is the GCP service-account email bound + // to the external-dns K8s ServiceAccount via Workload Identity. + // Empty defaults to external-dns@.iam.gserviceaccount.com. + ExternalDNSServiceAccount string `yaml:"externalDNSServiceAccount,omitempty"` +} + +// ACMEConfig is the user-controllable ACME surface — email + optional +// server override. The solver provider (CloudDNS for GKE, Route53 for +// EKS) is an invariant of the kind, not user-controlled here. +type ACMEConfig struct { + // Email is the contact address registered with the ACME server. + // Required. + Email string `yaml:"email"` + + // Server is the ACME directory URL. Empty defers to the CRD + // default (Let's Encrypt production). + Server string `yaml:"server,omitempty"` +} + +// WithDefaults applies static + project-derived defaults. +func (c *EducatesGKEConfig) WithDefaults() *EducatesGKEConfig { + if c.ClusterAdmin == nil { + f := false + c.ClusterAdmin = &f + } + if c.LookupService == nil { + t := true + c.LookupService = &t + } + if c.ImagePrePuller == nil { + f := false + c.ImagePrePuller = &f + } + if c.Operator.LogLevel == "" { + c.Operator.LogLevel = "info" + } + if c.GCP.Project != "" { + if c.GCP.CertManagerServiceAccount == "" { + c.GCP.CertManagerServiceAccount = "cert-manager@" + c.GCP.Project + ".iam.gserviceaccount.com" + } + if c.GCP.ExternalDNSServiceAccount == "" { + c.GCP.ExternalDNSServiceAccount = "external-dns@" + c.GCP.Project + ".iam.gserviceaccount.com" + } + } + return c +} + +// ApplyCLIDefaults mirrors EducatesLocalConfig's CLI-binary defaulting. +func (c *EducatesGKEConfig) ApplyCLIDefaults(projectVersion, imageRepository string) *EducatesGKEConfig { + if c.Operator.Image.Repository == "" && imageRepository != "" { + c.Operator.Image.Repository = imageRepository + "/educates-operator" + } + if c.Operator.Image.Tag == "" && projectVersion != "" { + c.Operator.Image.Tag = projectVersion + } + return c +} diff --git a/client-programs/pkg/config/v1alpha1/inline.go b/client-programs/pkg/config/v1alpha1/inline.go new file mode 100644 index 000000000..600bf0c2c --- /dev/null +++ b/client-programs/pkg/config/v1alpha1/inline.go @@ -0,0 +1,119 @@ +package v1alpha1 + +const KindEducatesInlineConfig = "EducatesInlineConfig" + +// EducatesInlineConfig is the BYO scenario kind. The user asserts that +// cert-manager (or a wildcard cert), an ingress controller, and a policy +// engine already exist on the cluster, and Educates uses them via +// EducatesClusterConfig.spec.inline references. +// +// Locked invariants applied by TranslateInline: +// - EducatesClusterConfig.spec.mode: Inline +// - All values flow under spec.inline; spec.{ingress,dns, +// policyEnforcement,imageRegistry} stay unset (forbidden by CEL +// on the CRD). +// +// No target.provider: Inline mode is provider-agnostic by design. +// EducatesInlineConfig is accepted by render and deploy but not by +// 'local cluster create' (which is kind-only). +type EducatesInlineConfig struct { + TypeMeta `yaml:",inline"` + + // Domain is the wildcard ingress subdomain. Required. + Domain string `yaml:"domain"` + + // IngressClassName names the IngressClass routing to the BYO + // controller (e.g. "contour", "openshift-default"). Required. + IngressClassName string `yaml:"ingressClassName"` + + // WildcardCertificateSecret names a kubernetes.io/tls Secret in the + // operator namespace with keys tls.crt + tls.key, valid for + // *.. Required. + WildcardCertificateSecret string `yaml:"wildcardCertificateSecret"` + + // CACertificateSecret optionally names a Secret with the ca.crt + // key for the CA chain that issued the wildcard. Workshops mount it + // when they need to trust outbound calls to private endpoints. + CACertificateSecret string `yaml:"caCertificateSecret,omitempty"` + + // ClusterIssuerName is informational — when a cert-manager + // ClusterIssuer signed the wildcard, this name surfaces in status. + // Optional. + ClusterIssuerName string `yaml:"clusterIssuerName,omitempty"` + + // ImageRegistry optionally rewrites workshop image refs to live + // behind an in-cluster mirror and supplies pull credentials. + ImageRegistry InlineImageRegistry `yaml:"imageRegistry,omitempty"` + + // PolicyEnforcement names the engines the cluster already enforces. + // Defaults: clusterEngine=Kyverno, workshopEngine=Kyverno. + PolicyEnforcement InlinePolicyEnforcement `yaml:"policyEnforcement,omitempty"` + + // ExternalTLSTermination asserts that TLS for the ingress domain is + // terminated outside the cluster (corporate load balancer or proxy + // forwarding plain HTTP inward). Generated portal and workshop URLs + // use https regardless of in-cluster certificate presence. Maps to + // SessionManager.spec.ingressOverrides.protocol: https. + ExternalTLSTermination bool `yaml:"externalTLSTermination,omitempty"` + + // Top-level toggles shared with EducatesLocalConfig. + ClusterAdmin *bool `yaml:"clusterAdmin,omitempty"` + LookupService *bool `yaml:"lookupService,omitempty"` + ImagePrePuller *bool `yaml:"imagePrePuller,omitempty"` + WebsiteStyling LocalWebsiteStylingConfig `yaml:"websiteStyling,omitempty"` + SecretPropagation LocalSecretPropagationConfig `yaml:"secretPropagation,omitempty"` + ImageVersions []ImageVersion `yaml:"imageVersions,omitempty"` + Operator LocalOperatorConfig `yaml:"operator,omitempty"` +} + +type InlineImageRegistry struct { + Prefix string `yaml:"prefix,omitempty"` + PullSecrets []string `yaml:"pullSecrets,omitempty"` +} + +type InlinePolicyEnforcement struct { + // ClusterEngine enum: Kyverno | PodSecurityStandards | OpenShiftSCC | None. + ClusterEngine string `yaml:"clusterEngine,omitempty"` + // WorkshopEngine enum: Kyverno | None. + WorkshopEngine string `yaml:"workshopEngine,omitempty"` +} + +// WithDefaults applies static defaults that are independent of host +// environment. Operator.logLevel mirrors EducatesLocalConfig. Policy +// engines default to Kyverno (matches CRD kubebuilder defaults). +func (c *EducatesInlineConfig) WithDefaults() *EducatesInlineConfig { + if c.ClusterAdmin == nil { + f := false + c.ClusterAdmin = &f + } + if c.LookupService == nil { + t := true + c.LookupService = &t + } + if c.ImagePrePuller == nil { + f := false + c.ImagePrePuller = &f + } + if c.Operator.LogLevel == "" { + c.Operator.LogLevel = "info" + } + if c.PolicyEnforcement.ClusterEngine == "" { + c.PolicyEnforcement.ClusterEngine = "Kyverno" + } + if c.PolicyEnforcement.WorkshopEngine == "" { + c.PolicyEnforcement.WorkshopEngine = "Kyverno" + } + return c +} + +// ApplyCLIDefaults mirrors EducatesLocalConfig's CLI-binary defaulting +// for operator.image. +func (c *EducatesInlineConfig) ApplyCLIDefaults(projectVersion, imageRepository string) *EducatesInlineConfig { + if c.Operator.Image.Repository == "" && imageRepository != "" { + c.Operator.Image.Repository = imageRepository + "/educates-operator" + } + if c.Operator.Image.Tag == "" && projectVersion != "" { + c.Operator.Image.Tag = projectVersion + } + return c +} diff --git a/client-programs/pkg/config/v1alpha1/local.go b/client-programs/pkg/config/v1alpha1/local.go new file mode 100644 index 000000000..a8746334d --- /dev/null +++ b/client-programs/pkg/config/v1alpha1/local.go @@ -0,0 +1,226 @@ +package v1alpha1 + +import "regexp" + +// EducatesLocalConfig is the laptop-kind-cluster scenario kind. Empty file +// (apiVersion + kind only) is valid; defaults fill in everything else. +// +// Hard exclusions (escalate to EducatesConfig escape hatch): mode, +// target.provider, dns, ACME, imageRegistry.prefix, cluster-service +// discriminators, analytics, dockerDaemon.*, storage.*, network.blockCIDRs, +// workshops.frameAncestors, debug. +type EducatesLocalConfig struct { + TypeMeta `yaml:",inline"` + + Cluster LocalClusterConfig `yaml:"cluster,omitempty"` + Resolver LocalResolverConfig `yaml:"resolver,omitempty"` + Ingress LocalIngressConfig `yaml:"ingress,omitempty"` + ClusterAdmin *bool `yaml:"clusterAdmin,omitempty"` + LookupService *bool `yaml:"lookupService,omitempty"` + ImagePrePuller *bool `yaml:"imagePrePuller,omitempty"` + WebsiteStyling LocalWebsiteStylingConfig `yaml:"websiteStyling,omitempty"` + SecretPropagation LocalSecretPropagationConfig `yaml:"secretPropagation,omitempty"` + ImageVersions []ImageVersion `yaml:"imageVersions,omitempty"` + Operator LocalOperatorConfig `yaml:"operator,omitempty"` +} + +type LocalClusterConfig struct { + ListenAddress string `yaml:"listenAddress,omitempty"` + RegistryListenAddress string `yaml:"registryListenAddress,omitempty"` + ApiServer ApiServerConfig `yaml:"apiServer,omitempty"` + Networking NetworkingConfig `yaml:"networking,omitempty"` + VolumeMounts []VolumeMount `yaml:"volumeMounts,omitempty"` + RegistryMirrors []RegistryMirror `yaml:"registryMirrors,omitempty"` +} + +type ApiServerConfig struct { + Address string `yaml:"address,omitempty"` + Port int `yaml:"port,omitempty"` +} + +type NetworkingConfig struct { + ServiceSubnet string `yaml:"serviceSubnet,omitempty"` + PodSubnet string `yaml:"podSubnet,omitempty"` +} + +type VolumeMount struct { + HostPath string `yaml:"hostPath"` + ContainerPath string `yaml:"containerPath"` + ReadOnly *bool `yaml:"readOnly,omitempty"` +} + +// RegistryMirror is the user-declared pull-through cache surface. The +// always-on localhost:5001 mirror is implicit and not represented here. +type RegistryMirror struct { + Mirror string `yaml:"mirror"` + URL string `yaml:"url,omitempty"` + Username string `yaml:"username,omitempty"` + Password string `yaml:"password,omitempty"` + Port string `yaml:"port,omitempty"` + BindIP string `yaml:"bindIP,omitempty"` +} + +type LocalResolverConfig struct { + TargetAddress string `yaml:"targetAddress,omitempty"` + ExtraDomains []string `yaml:"extraDomains,omitempty"` +} + +type LocalIngressConfig struct { + Domain string `yaml:"domain,omitempty"` +} + +// LocalWebsiteStylingConfig is the narrow subset exposed by EducatesLocalConfig. +// Full styling surface (per-page overrides, HTML snippets) is escape-hatch only. +type LocalWebsiteStylingConfig struct { + DefaultTheme string `yaml:"defaultTheme,omitempty"` + ThemeDataRefs []ThemeDataRef `yaml:"themeDataRefs,omitempty"` +} + +type ThemeDataRef struct { + Namespace string `yaml:"namespace"` + Name string `yaml:"name"` +} + +type LocalSecretPropagationConfig struct { + ImagePullSecretNames []string `yaml:"imagePullSecretNames,omitempty"` +} + +type ImageVersion struct { + Name string `yaml:"name"` + Image string `yaml:"image"` +} + +type LocalOperatorConfig struct { + Image OperatorImage `yaml:"image,omitempty"` + ImagePullSecrets []string `yaml:"imagePullSecrets,omitempty"` + LogLevel string `yaml:"logLevel,omitempty"` +} + +type OperatorImage struct { + Repository string `yaml:"repository,omitempty"` + Tag string `yaml:"tag,omitempty"` + // PullPolicy maps to the chart's image.pullPolicy. Empty lets the + // chart auto-derive it (Always for floating tags like develop, + // IfNotPresent otherwise). Set to "Always" for local-registry + // development where the tag (e.g. :dev) is rebuilt under the same + // name on each push. + PullPolicy string `yaml:"pullPolicy,omitempty"` +} + +// Static defaults — independent of host environment. Applied after YAML +// unmarshal, before validation. +// +// Two further layers of defaulting are applied by callers (typically the +// command code, not the loader): +// +// - ApplyCLIDefaults uses the CLI binary's compiled-in version/registry +// to fill operator.image.{repository,tag} when empty. Deterministic +// per CLI binary, so safe for GitOps. +// - ApplyHostDefaults uses the laptop's host IP to fill ingress.domain +// with a nip.io fallback. Host-specific, NOT safe for GitOps; only +// applied when the user opted into laptop-convenience mode +// (`--local-config`). +func (c *EducatesLocalConfig) WithDefaults() *EducatesLocalConfig { + if c.Cluster.ListenAddress == "" { + c.Cluster.ListenAddress = "127.0.0.1" + } + if c.ClusterAdmin == nil { + t := true + c.ClusterAdmin = &t + } + if c.LookupService == nil { + t := true + c.LookupService = &t + } + if c.ImagePrePuller == nil { + f := false + c.ImagePrePuller = &f + } + if c.Operator.LogLevel == "" { + c.Operator.LogLevel = "info" + } + return c +} + +// LocalDevImageNames is the set of platform images a dev-built CLI +// defaults to its compiled-in registry — exactly the images the root +// Makefile's `build-core-images` produces. Workshop language images +// (jdk*, conda) are deliberately excluded: their chart defaults point +// at published images that exist, so optional-workshop flows keep +// working in a dev cluster; a developer who builds them locally adds +// explicit imageVersions entries, which always win. +var LocalDevImageNames = []string{ + "session-manager", + "training-portal", + "base-environment", + "docker-registry", + "pause-container", + "secrets-manager", + "tunnel-manager", + "image-cache", + "assets-server", + "lookup-service", + "node-ca-injector", +} + +// semverRe matches release versions as stamped by the release +// workflow: X.Y.Z with optional pre-release/build suffix, optional +// leading v. Anything else ("latest", "develop", "dev", ad-hoc +// PACKAGE_VERSION values) identifies a developer-built CLI. +var semverRe = regexp.MustCompile(`^v?\d+\.\d+\.\d+(-[0-9A-Za-z.-]+)?(\+[0-9A-Za-z.-]+)?$`) + +// isDevVersion reports whether the CLI binary's compiled-in version +// identifies a developer build. Release binaries are always stamped +// with a semver tag (including pre-releases like 4.0.0-alpha.1), so +// "not semver" is exactly "not built by the release pipeline". +func isDevVersion(v string) bool { + return !semverRe.MatchString(v) +} + +// ApplyCLIDefaults fills in image defaults from the CLI binary's +// compiled-in version/registry. Deterministic per CLI binary; the +// output is reproducible as long as the same CLI version is used. +// +// All binaries: operator.image.{repository,tag} default to +// `/educates-operator` : projectVersion (matching +// `installer/charts/educates-installer/values.yaml`). +// +// Developer binaries only (non-semver version, e.g. `latest` from +// `make`): every LocalDevImageNames entry the user didn't override is +// defaulted to `/educates-:`, +// so a locally built image set deploys with zero manual config. +// Release binaries (semver-stamped) skip this entirely and behave as +// before. User-supplied imageVersions entries always win. +func (c *EducatesLocalConfig) ApplyCLIDefaults(projectVersion, imageRepository string) *EducatesLocalConfig { + if c.Operator.Image.Repository == "" && imageRepository != "" { + c.Operator.Image.Repository = imageRepository + "/educates-operator" + } + if c.Operator.Image.Tag == "" && projectVersion != "" { + c.Operator.Image.Tag = projectVersion + } + if projectVersion != "" && imageRepository != "" && isDevVersion(projectVersion) { + if c.Operator.Image.PullPolicy == "" { + // Dev tags are rebuilt under the same name on every push; + // the chart only auto-derives Always for well-known + // floating tags (latest/develop/...), so pin it here. + c.Operator.Image.PullPolicy = "Always" + } + present := make(map[string]bool, len(c.ImageVersions)) + for _, iv := range c.ImageVersions { + present[iv.Name] = true + } + for _, name := range LocalDevImageNames { + if !present[name] { + c.ImageVersions = append(c.ImageVersions, ImageVersion{ + Name: name, + Image: imageRepository + "/educates-" + name + ":" + projectVersion, + }) + } + } + } + return c +} + +// Host-derived defaulting (e.g. ingress.domain ← .nip.io) is +// done at the caller, not on the type — the host probe is an external +// effect that doesn't belong on a value type. See pkg/config/hostinfo. diff --git a/client-programs/pkg/config/v1alpha1/local_test.go b/client-programs/pkg/config/v1alpha1/local_test.go new file mode 100644 index 000000000..5faa5879d --- /dev/null +++ b/client-programs/pkg/config/v1alpha1/local_test.go @@ -0,0 +1,71 @@ +package v1alpha1 + +import "testing" + +func TestIsDevVersion(t *testing.T) { + release := []string{"4.0.0", "4.0.0-alpha.1", "v1.2.3", "1.2.3+build.7", "0.0.1-rc.2"} + for _, v := range release { + if isDevVersion(v) { + t.Errorf("isDevVersion(%q) = true, want false (release)", v) + } + } + dev := []string{"latest", "develop", "dev", "main", "sha-abc1234", "4.0", ""} + for _, v := range dev { + if !isDevVersion(v) { + t.Errorf("isDevVersion(%q) = false, want true (dev)", v) + } + } +} + +func TestApplyCLIDefaults_DevBuild(t *testing.T) { + c := (&EducatesLocalConfig{ + ImageVersions: []ImageVersion{ + {Name: "session-manager", Image: "example.com/custom/session-manager:hacking"}, + }, + }).ApplyCLIDefaults("latest", "localhost:5001") + + if c.Operator.Image.Repository != "localhost:5001/educates-operator" { + t.Errorf("operator repository = %q", c.Operator.Image.Repository) + } + if c.Operator.Image.Tag != "latest" { + t.Errorf("operator tag = %q", c.Operator.Image.Tag) + } + if c.Operator.Image.PullPolicy != "Always" { + t.Errorf("operator pullPolicy = %q, want Always in dev mode", c.Operator.Image.PullPolicy) + } + + if len(c.ImageVersions) != len(LocalDevImageNames) { + t.Fatalf("imageVersions has %d entries, want %d (one per LocalDevImageNames, user entry deduped)", + len(c.ImageVersions), len(LocalDevImageNames)) + } + byName := map[string]string{} + for _, iv := range c.ImageVersions { + byName[iv.Name] = iv.Image + } + if byName["session-manager"] != "example.com/custom/session-manager:hacking" { + t.Errorf("user-supplied session-manager override was clobbered: %q", byName["session-manager"]) + } + if byName["training-portal"] != "localhost:5001/educates-training-portal:latest" { + t.Errorf("training-portal default = %q", byName["training-portal"]) + } + if byName["secrets-manager"] != "localhost:5001/educates-secrets-manager:latest" { + t.Errorf("secrets-manager default = %q", byName["secrets-manager"]) + } +} + +func TestApplyCLIDefaults_ReleaseBuild(t *testing.T) { + c := (&EducatesLocalConfig{}).ApplyCLIDefaults("4.0.0-alpha.1", "ghcr.io/educates") + + if c.Operator.Image.Repository != "ghcr.io/educates/educates-operator" { + t.Errorf("operator repository = %q", c.Operator.Image.Repository) + } + if c.Operator.Image.Tag != "4.0.0-alpha.1" { + t.Errorf("operator tag = %q", c.Operator.Image.Tag) + } + if c.Operator.Image.PullPolicy != "" { + t.Errorf("operator pullPolicy = %q, want empty (chart auto-derives) for release builds", c.Operator.Image.PullPolicy) + } + if len(c.ImageVersions) != 0 { + t.Errorf("release build appended imageVersions defaults: %v", c.ImageVersions) + } +} diff --git a/client-programs/pkg/config/v1alpha1/schemas/EducatesAnyConfig.schema.json b/client-programs/pkg/config/v1alpha1/schemas/EducatesAnyConfig.schema.json new file mode 100644 index 000000000..3208b3ff1 --- /dev/null +++ b/client-programs/pkg/config/v1alpha1/schemas/EducatesAnyConfig.schema.json @@ -0,0 +1,13 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "$id": "https://schemas.educates.dev/cli/v1alpha1/EducatesAnyConfig.json", + "title": "EducatesAnyConfig", + "description": "Any cli.educates.dev/v1alpha1 Educates CLI config kind. Umbrella schema for editor integrations that match by filename (SchemaStore): each kind carries a `kind` const, so exactly one branch validates. Not embedded in the CLI — the CLI validates against the per-kind schemas directly. Add a $ref here whenever a new config kind ships.", + "oneOf": [ + { "$ref": "https://schemas.educates.dev/cli/v1alpha1/EducatesLocalConfig.json" }, + { "$ref": "https://schemas.educates.dev/cli/v1alpha1/EducatesGKEConfig.json" }, + { "$ref": "https://schemas.educates.dev/cli/v1alpha1/EducatesEKSConfig.json" }, + { "$ref": "https://schemas.educates.dev/cli/v1alpha1/EducatesInlineConfig.json" }, + { "$ref": "https://schemas.educates.dev/cli/v1alpha1/EducatesConfig.json" } + ] +} diff --git a/client-programs/pkg/config/v1alpha1/schemas/EducatesConfig.schema.json b/client-programs/pkg/config/v1alpha1/schemas/EducatesConfig.schema.json new file mode 100644 index 000000000..0bab6cc20 --- /dev/null +++ b/client-programs/pkg/config/v1alpha1/schemas/EducatesConfig.schema.json @@ -0,0 +1,1487 @@ +{ + "$defs": { + "EducatesClusterConfigSpec": { + "description": "EducatesClusterConfigSpec defines the desired state of\nEducatesClusterConfig.\n\nCEL invariants (structural):\n - spec.mode is immutable; switching modes requires delete + recreate.\n - When mode is Inline, the Managed-mode top-level fields\n (infrastructure, ingress, dns, policyEnforcement, imageRegistry)\n are forbidden.\n - When mode is Managed, spec.inline is forbidden.", + "properties": { + "dns": { + "description": "dns configures DNS management in Managed mode; ignored in Inline\nmode.", + "properties": { + "bundledExternalDNS": { + "description": "BundledExternalDNSConfig configures the operator-installed\nexternal-dns chart. v1alpha1 supports Route53 and CloudDNS; other\nproviders (Cloudflare, AzureDNS, etc.) surface \"not yet supported\"\nvalidation errors.\n\nCEL invariants:\n - provider==Route53 requires route53 to be set and forbids cloudDNS.\n - provider==CloudDNS requires cloudDNS to be set and forbids route53.", + "properties": { + "cloudDNS": { + "description": "ExternalDNSCloudDNSConfig configures the GCP CloudDNS provider for\nthe operator-installed external-dns.\n\nCredentials are supplied via *exactly one* of:\n - CredentialsSecretRef: a Secret in the operator namespace with\n key `credentials.json` containing the GCP service-account\n JSON key.\n - WorkloadIdentityServiceAccount: a GCP service-account email\n bound to the external-dns ServiceAccount via the\n `iam.gke.io/gcp-service-account` annotation. Preferred on GKE.", + "properties": { + "credentialsSecretRef": { + "description": "LocalObjectReference is a reference to a Kubernetes object by name in\nthe operator namespace. Cluster-scoped references (e.g., ClusterIssuer,\nIngressClass) also use this shape.", + "properties": { + "name": { + "description": "name of the referent.", + "type": "string" + } + }, + "required": [ + "name" + ], + "type": "object" + }, + "project": { + "type": "string" + }, + "workloadIdentityServiceAccount": { + "type": "string" + } + }, + "required": [ + "project" + ], + "type": "object" + }, + "provider": { + "allOf": [ + { + "enum": [ + "Route53", + "CloudDNS", + "Cloudflare", + "AzureDNS" + ] + }, + { + "enum": [ + "Route53", + "CloudDNS" + ] + } + ], + "description": "provider selects which DNS provider external-dns publishes\nrecords to. Reuses the DNS01Provider enum for vocabulary\nconsistency with cert-manager's solver config; validation\nrejects Cloudflare/AzureDNS for now.", + "type": "string" + }, + "route53": { + "description": "ExternalDNSRoute53Config configures the AWS Route53 provider for\nthe operator-installed external-dns. HostedZoneID is required to\nscope external-dns to a specific zone — running unscoped is a\nproduction footgun (a broad IAM role plus no zone filter can\nsilently rewrite records across the entire account).\n\nCredentials are supplied via *exactly one* of:\n - CredentialsSecretRef: a Secret in the operator namespace with\n keys `aws_access_key_id` and `aws_secret_access_key`.\n - IAMRoleARN: an IRSA / Pod Identity role assumed via the\n external-dns ServiceAccount's `eks.amazonaws.com/role-arn`\n annotation. Preferred on EKS.\n\nCEL elsewhere enforces the exactly-one rule; the operator\nvalidator backs it up with a friendlier error message.", + "properties": { + "credentialsSecretRef": { + "description": "LocalObjectReference is a reference to a Kubernetes object by name in\nthe operator namespace. Cluster-scoped references (e.g., ClusterIssuer,\nIngressClass) also use this shape.", + "properties": { + "name": { + "description": "name of the referent.", + "type": "string" + } + }, + "required": [ + "name" + ], + "type": "object" + }, + "hostedZoneID": { + "type": "string" + }, + "iamRoleARN": { + "type": "string" + }, + "region": { + "description": "region defaults to the AWS SDK's default detection (pod IMDS\n/ env vars). Set explicitly when running outside AWS or in\nair-gapped environments.", + "type": "string" + } + }, + "required": [ + "hostedZoneID" + ], + "type": "object" + }, + "sources": { + "default": [ + "service" + ], + "description": "sources controls which Kubernetes kinds external-dns watches\nfor hostname records. Defaults to [\"service\"] because Educates\npublishes the wildcard via an annotation on the Envoy Service.\nUsers can broaden to [\"service\",\"ingress\"] (or any\nchart-accepted source) when they want per-workshop Ingress\nrecords published as well.", + "items": { + "type": "string" + }, + "type": "array" + } + }, + "required": [ + "provider" + ], + "type": "object" + }, + "provider": { + "default": "None", + "description": "provider defaults to None — appropriate for local clusters using\nnip.io or hosts-file resolution. Cloud installs must set this\nexplicitly.", + "enum": [ + "BundledExternalDNS", + "Manual", + "None" + ], + "type": "string" + } + }, + "type": "object" + }, + "imageRegistry": { + "description": "imageRegistry rewrites bundled chart image refs and supplies pull\ncredentials. Applies in Managed mode (Inline mode has its own\nequivalent under spec.inline.imageRegistry).", + "properties": { + "prefix": { + "description": "prefix rewrites every bundled image reference to live under this\nprefix, e.g., \"internal-registry.corp.local/educates\". Pre-relocated\nbundles (via helm dt wrap/unwrap) do not need this set.", + "type": "string" + }, + "pullSecrets": { + "description": "pullSecrets references kubernetes.io/dockerconfigjson Secrets in\nthe operator namespace.", + "items": { + "description": "LocalObjectReference is a reference to a Kubernetes object by name in\nthe operator namespace. Cluster-scoped references (e.g., ClusterIssuer,\nIngressClass) also use this shape.", + "properties": { + "name": { + "description": "name of the referent.", + "type": "string" + } + }, + "required": [ + "name" + ], + "type": "object" + }, + "type": "array" + } + }, + "type": "object" + }, + "infrastructure": { + "description": "infrastructure describes the cluster substrate. Used in Managed\nmode; ignored in Inline mode.", + "properties": { + "cloud": { + "description": "cloud carries provider-specific configuration. Required for cloud\nproviders (EKS, GKE) when bundled cert-manager or external-dns is\nenabled.", + "properties": { + "project": { + "description": "project / account identifier, e.g., GCP project ID or AWS account\nalias.", + "type": "string" + }, + "region": { + "type": "string" + }, + "serviceAccounts": { + "description": "CloudServiceAccounts maps Educates' bundled cluster services to\nprovider-native workload identities.", + "properties": { + "certManager": { + "description": "certManager identity used by cert-manager when requesting\nDNS01-validated certificates.", + "type": "string" + }, + "externalDNS": { + "description": "externalDNS identity used by external-dns when managing DNS\nrecords.", + "type": "string" + } + }, + "type": "object" + } + }, + "type": "object" + }, + "provider": { + "description": "InfrastructureProvider identifies the underlying cluster substrate.\nUsed by the operator to compute provider-specific defaults and to\nvalidate cloud-related fields.", + "enum": [ + "Kind", + "Minikube", + "EKS", + "GKE", + "OpenShift", + "VCluster", + "Generic" + ], + "type": "string" + } + }, + "required": [ + "provider" + ], + "type": "object" + }, + "ingress": { + "description": "ingress configures the Educates ingress in Managed mode; ignored\nin Inline mode.", + "properties": { + "certificates": { + "description": "Certificates groups certificate-provider configuration.", + "properties": { + "bundledCertManager": { + "description": "BundledCertManagerConfig configures the operator-installed cert-manager\nchart and the ClusterIssuer it provides.", + "properties": { + "acme": { + "description": "ACMEConfig configures the cert-manager ACME ClusterIssuer.", + "properties": { + "email": { + "type": "string" + }, + "server": { + "description": "server is the ACME directory URL. Defaults to Let's Encrypt\nproduction. Override for Let's Encrypt staging or another CA.", + "type": "string" + }, + "solvers": { + "description": "ACMESolvers groups the cert-manager solvers used to satisfy the ACME\nchallenge.", + "properties": { + "dns01": { + "description": "dns01 is required for wildcard issuance.", + "properties": { + "azureDNS": { + "description": "AzureDNSConfig configures the Azure DNS DNS01 solver.", + "properties": { + "resourceGroup": { + "type": "string" + }, + "subscriptionID": { + "type": "string" + } + }, + "required": [ + "resourceGroup", + "subscriptionID" + ], + "type": "object" + }, + "cloudDNS": { + "description": "CloudDNSConfig configures the cert-manager GCP CloudDNS DNS01\nsolver and the GCP-side credentials.\n\nCredentials must be supplied via *exactly one* mechanism:\n - WorkloadIdentityServiceAccount: a GCP service-account email\n bound to cert-manager's K8s ServiceAccount via the\n `iam.gke.io/gcp-service-account` annotation. Recommended on\n GKE.\n - CredentialsSecretRef: a Secret in the operator namespace\n with key `credentials.json` containing a GCP service-account\n JSON key. v1alpha1 reserves the field but rejects it as\n \"not yet supported\"; static-creds support is a follow-up.", + "properties": { + "credentialsSecretRef": { + "description": "LocalObjectReference is a reference to a Kubernetes object by name in\nthe operator namespace. Cluster-scoped references (e.g., ClusterIssuer,\nIngressClass) also use this shape.", + "properties": { + "name": { + "description": "name of the referent.", + "type": "string" + } + }, + "required": [ + "name" + ], + "type": "object" + }, + "project": { + "type": "string" + }, + "workloadIdentityServiceAccount": { + "type": "string" + }, + "zone": { + "type": "string" + } + }, + "required": [ + "project" + ], + "type": "object" + }, + "cloudflare": { + "description": "CloudflareConfig configures the Cloudflare DNS01 solver.", + "properties": { + "apiTokenSecretRef": { + "description": "apiTokenSecretRef references a Secret holding the Cloudflare API\ntoken. The default key is \"api-token\".", + "properties": { + "key": { + "description": "key within the Secret. Defaults vary by use site.", + "type": "string" + }, + "name": { + "description": "name of the Secret.", + "type": "string" + } + }, + "required": [ + "name" + ], + "type": "object" + } + }, + "required": [ + "apiTokenSecretRef" + ], + "type": "object" + }, + "provider": { + "description": "DNS01Provider names a cert-manager DNS01 solver. Required for wildcard\ncertificate issuance via ACME.", + "enum": [ + "Route53", + "CloudDNS", + "Cloudflare", + "AzureDNS" + ], + "type": "string" + }, + "route53": { + "description": "Route53Config configures the cert-manager Route53 DNS01 solver\nand the AWS-side credentials it needs to write TXT records during\nACME challenges.\n\nCredentials must be supplied via *exactly one* mechanism:\n - IAMRoleARN: marks cert-manager's ServiceAccount with an\n `eks.amazonaws.com/role-arn` annotation; cert-manager assumes\n the role via IRSA / Pod Identity. Recommended on EKS.\n - CredentialsSecretRef: a Secret in the operator namespace\n with keys `aws_access_key_id` + `aws_secret_access_key`.\n v1alpha1 reserves the field but rejects it as \"not yet\n supported\"; static-creds support is a follow-up.\n\nCEL elsewhere enforces the mutual-exclusivity rule; the\noperator validator backs it up with a friendlier message.", + "properties": { + "credentialsSecretRef": { + "description": "LocalObjectReference is a reference to a Kubernetes object by name in\nthe operator namespace. Cluster-scoped references (e.g., ClusterIssuer,\nIngressClass) also use this shape.", + "properties": { + "name": { + "description": "name of the referent.", + "type": "string" + } + }, + "required": [ + "name" + ], + "type": "object" + }, + "hostedZoneID": { + "type": "string" + }, + "iamRoleARN": { + "type": "string" + }, + "region": { + "type": "string" + } + }, + "required": [ + "hostedZoneID" + ], + "type": "object" + } + }, + "required": [ + "provider" + ], + "type": "object" + }, + "http01": { + "description": "ACMEHTTP01Solver configures the optional HTTP01 solver. Rarely needed\nbecause DNS01 is required for wildcards.", + "properties": { + "ingressClassName": { + "description": "ingressClassName defaults to spec.ingress.ingressClassName when\nunset.", + "type": "string" + } + }, + "type": "object" + } + }, + "required": [ + "dns01" + ], + "type": "object" + } + }, + "required": [ + "email", + "solvers" + ], + "type": "object" + }, + "customCA": { + "description": "CustomCAConfig configures a self-signed/custom CA-backed ClusterIssuer.", + "properties": { + "caCertificateRef": { + "description": "caCertificateRef references a Secret holding the CA's own cert and\nkey (keys: tls.crt, tls.key). Namespace defaults to the operator\nnamespace when empty.", + "properties": { + "name": { + "description": "name of the referent.", + "type": "string" + }, + "namespace": { + "description": "namespace of the referent. Empty means the operator namespace.", + "type": "string" + } + }, + "required": [ + "name" + ], + "type": "object" + } + }, + "required": [ + "caCertificateRef" + ], + "type": "object" + }, + "issuerType": { + "description": "IssuerType selects the cert-manager ClusterIssuer flavour for the\nBundledCertManager provider.", + "enum": [ + "ACME", + "CustomCA" + ], + "type": "string" + } + }, + "required": [ + "issuerType" + ], + "type": "object" + }, + "externalCertManager": { + "description": "ExternalCertManagerConfig assumes cert-manager is already installed\nand references an existing ClusterIssuer; the operator only creates\nthe wildcard Certificate.", + "properties": { + "clusterIssuerRef": { + "description": "LocalObjectReference is a reference to a Kubernetes object by name in\nthe operator namespace. Cluster-scoped references (e.g., ClusterIssuer,\nIngressClass) also use this shape.", + "properties": { + "name": { + "description": "name of the referent.", + "type": "string" + } + }, + "required": [ + "name" + ], + "type": "object" + } + }, + "required": [ + "clusterIssuerRef" + ], + "type": "object" + }, + "provider": { + "description": "CertificatesProvider selects how the wildcard TLS certificate is\nprovisioned.", + "enum": [ + "BundledCertManager", + "ExternalCertManager", + "StaticCertificate" + ], + "type": "string" + }, + "staticCertificate": { + "description": "StaticCertificateConfig declares a pre-provisioned wildcard TLS\ncertificate; no cert-manager is involved.", + "properties": { + "caCertificateRef": { + "description": "caCertificateRef optionally references a Secret with the ca.crt\nkey for the issuing CA chain.", + "properties": { + "name": { + "description": "name of the referent.", + "type": "string" + } + }, + "required": [ + "name" + ], + "type": "object" + }, + "tlsSecretRef": { + "description": "tlsSecretRef references a kubernetes.io/tls Secret with keys\ntls.crt and tls.key.", + "properties": { + "name": { + "description": "name of the referent.", + "type": "string" + } + }, + "required": [ + "name" + ], + "type": "object" + } + }, + "required": [ + "tlsSecretRef" + ], + "type": "object" + } + }, + "required": [ + "provider" + ], + "type": "object" + }, + "controller": { + "description": "IngressController groups ingress-controller configuration.", + "properties": { + "bundledContour": { + "description": "BundledContourConfig configures the operator-installed Contour ingress\ncontroller.", + "properties": { + "envoyServiceType": { + "default": "LoadBalancer", + "description": "envoyServiceType selects the Kubernetes Service type for the\nEnvoy DaemonSet. Defaults to LoadBalancer so cloud-provider\ninstalls (EKS, GKE, AKS, OpenShift) work out of the box;\nset explicitly to NodePort on kind / minikube / vCluster\ninstalls where no in-cluster LoadBalancer controller exists.", + "enum": [ + "LoadBalancer", + "NodePort", + "ClusterIP" + ], + "type": "string" + }, + "operational": { + "description": "OperationalBlock collects the per-Deployment operational knobs of a\nBundled cluster service. In v1alpha1 only BundledContour carries it:\nthe cert-manager / external-dns / kyverno blocks were dropped\n(2026-06-11) because their semantics didn't hold against the\nupstream charts — external-dns 1.21.1 hardcodes replicas to 1 and\nexposes no replica value, Kyverno fanning one count across its four\ncontrollers conflicts with upstream HA guidance (3+ for the\nadmission controller only), and cert-manager never consumed it.\nThey return when per-service shapes are validated against each\nchart's real values surface. Of the knobs below, the reconciler\ncurrently applies replicas; the rest are accepted but not yet\nwired into chart values.", + "properties": { + "nodeSelector": { + "additionalProperties": { + "type": "string" + }, + "type": "object" + }, + "podAnnotations": { + "additionalProperties": { + "type": "string" + }, + "type": "object" + }, + "podLabels": { + "additionalProperties": { + "type": "string" + }, + "type": "object" + }, + "priorityClassName": { + "type": "string" + }, + "replicas": { + "description": "replicas overrides the operator-computed default. The default\nvaries by infrastructure provider (typically 1 for Kind/Minikube,\n2+ otherwise).", + "format": "int32", + "minimum": 0, + "type": "integer" + }, + "resources": { + "description": "ResourceRequirements describes the compute resource requirements.", + "properties": { + "claims": { + "description": "Claims lists the names of resources, defined in spec.resourceClaims,\nthat are used by this container.\n\nThis field depends on the\nDynamicResourceAllocation feature gate.\n\nThis field is immutable. It can only be set for containers.", + "items": { + "description": "ResourceClaim references one entry in PodSpec.ResourceClaims.", + "properties": { + "name": { + "description": "Name must match the name of one entry in pod.spec.resourceClaims of\nthe Pod where this field is used. It makes that resource available\ninside a container.", + "type": "string" + }, + "request": { + "description": "Request is the name chosen for a request in the referenced claim.\nIf empty, everything from the claim is made available, otherwise\nonly the result of this request.", + "type": "string" + } + }, + "required": [ + "name" + ], + "type": "object" + }, + "type": "array" + }, + "limits": { + "additionalProperties": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "string" + } + ], + "pattern": "^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$" + }, + "description": "Limits describes the maximum amount of compute resources allowed.\nMore info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/", + "type": "object" + }, + "requests": { + "additionalProperties": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "string" + } + ], + "pattern": "^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$" + }, + "description": "Requests describes the minimum amount of compute resources required.\nIf Requests is omitted for a container, it defaults to Limits if that is explicitly specified,\notherwise to an implementation-defined value. Requests cannot exceed Limits.\nMore info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/", + "type": "object" + } + }, + "type": "object" + }, + "tolerations": { + "items": { + "description": "The pod this Toleration is attached to tolerates any taint that matches\nthe triple \u003ckey,value,effect\u003e using the matching operator \u003coperator\u003e.", + "properties": { + "effect": { + "description": "Effect indicates the taint effect to match. Empty means match all taint effects.\nWhen specified, allowed values are NoSchedule, PreferNoSchedule and NoExecute.", + "type": "string" + }, + "key": { + "description": "Key is the taint key that the toleration applies to. Empty means match all taint keys.\nIf the key is empty, operator must be Exists; this combination means to match all values and all keys.", + "type": "string" + }, + "operator": { + "description": "Operator represents a key's relationship to the value.\nValid operators are Exists, Equal, Lt, and Gt. Defaults to Equal.\nExists is equivalent to wildcard for value, so that a pod can\ntolerate all taints of a particular category.\nLt and Gt perform numeric comparisons (requires feature gate TaintTolerationComparisonOperators).", + "type": "string" + }, + "tolerationSeconds": { + "description": "TolerationSeconds represents the period of time the toleration (which must be\nof effect NoExecute, otherwise this field is ignored) tolerates the taint. By default,\nit is not set, which means tolerate the taint forever (do not evict). Zero and\nnegative values will be treated as 0 (evict immediately) by the system.", + "format": "int64", + "type": "integer" + }, + "value": { + "description": "Value is the taint value the toleration matches to.\nIf the operator is Exists, the value should be empty, otherwise just a regular string.", + "type": "string" + } + }, + "type": "object" + }, + "type": "array" + } + }, + "type": "object" + } + }, + "type": "object" + }, + "provider": { + "description": "IngressControllerProvider selects how the cluster's ingress controller\nis provided.", + "enum": [ + "BundledContour", + "ExternalIngressController" + ], + "type": "string" + } + }, + "required": [ + "provider" + ], + "type": "object" + }, + "domain": { + "description": "domain is the wildcard subdomain under which Educates serves\nworkshops, e.g., \"educates.example.com\".", + "type": "string" + }, + "ingressClassName": { + "description": "ingressClassName names the IngressClass used by Educates. In\nBundledContour mode the operator creates an IngressClass with\nthis name; in External mode it must already exist.", + "type": "string" + } + }, + "required": [ + "certificates", + "controller", + "domain", + "ingressClassName" + ], + "type": "object" + }, + "inline": { + "description": "inline declares pre-existing cluster resources. Used in Inline\nmode; ignored in Managed mode.", + "properties": { + "imageRegistry": { + "description": "ImageRegistry configures registry rewriting and pull credentials.\nApplies to all bundled charts in Managed mode and to the runtime in\nboth modes.", + "properties": { + "prefix": { + "description": "prefix rewrites every bundled image reference to live under this\nprefix, e.g., \"internal-registry.corp.local/educates\". Pre-relocated\nbundles (via helm dt wrap/unwrap) do not need this set.", + "type": "string" + }, + "pullSecrets": { + "description": "pullSecrets references kubernetes.io/dockerconfigjson Secrets in\nthe operator namespace.", + "items": { + "description": "LocalObjectReference is a reference to a Kubernetes object by name in\nthe operator namespace. Cluster-scoped references (e.g., ClusterIssuer,\nIngressClass) also use this shape.", + "properties": { + "name": { + "description": "name of the referent.", + "type": "string" + } + }, + "required": [ + "name" + ], + "type": "object" + }, + "type": "array" + } + }, + "type": "object" + }, + "ingress": { + "description": "InlineIngress declares pre-existing ingress resources for Inline\nmode. The operator validates these and republishes them in status.", + "properties": { + "caCertificateSecretRef": { + "description": "caCertificateSecretRef references a Secret with the ca.crt key\nfor the issuing CA chain. Optional.", + "properties": { + "name": { + "description": "name of the referent.", + "type": "string" + }, + "namespace": { + "description": "namespace of the referent. Empty means the operator namespace.", + "type": "string" + } + }, + "required": [ + "name" + ], + "type": "object" + }, + "clusterIssuerRef": { + "description": "clusterIssuerRef references an existing ClusterIssuer that must be\nReady. Optional; informational for components.", + "properties": { + "name": { + "description": "name of the referent.", + "type": "string" + } + }, + "required": [ + "name" + ], + "type": "object" + }, + "domain": { + "type": "string" + }, + "ingressClassName": { + "type": "string" + }, + "wildcardCertificateSecretRef": { + "description": "wildcardCertificateSecretRef references a kubernetes.io/tls Secret\nwith keys tls.crt and tls.key, valid for *.\u003cdomain\u003e.", + "properties": { + "name": { + "description": "name of the referent.", + "type": "string" + } + }, + "required": [ + "name" + ], + "type": "object" + } + }, + "required": [ + "domain", + "ingressClassName", + "wildcardCertificateSecretRef" + ], + "type": "object" + }, + "policyEnforcement": { + "description": "InlinePolicyEnforcement declares the policy engines already in place\nfor Inline mode. Enforced engines are identified, not installed.", + "properties": { + "clusterPolicyEngine": { + "description": "ClusterPolicyEngine names the cluster-wide policy enforcement engine.", + "enum": [ + "Kyverno", + "PodSecurityStandards", + "OpenShiftSCC", + "None" + ], + "type": "string" + }, + "workshopPolicyEngine": { + "description": "WorkshopPolicyEngine names the engine enforcing per-workshop isolation\nrules. Setting to None disables workshop isolation.", + "enum": [ + "Kyverno", + "None" + ], + "type": "string" + } + }, + "required": [ + "clusterPolicyEngine", + "workshopPolicyEngine" + ], + "type": "object" + } + }, + "required": [ + "ingress", + "policyEnforcement" + ], + "type": "object" + }, + "mode": { + "description": "ClusterConfigMode selects between operator-managed and user-declared\ncluster infrastructure. Immutable once set; switching modes requires\ndeleting and recreating the resource.", + "enum": [ + "Managed", + "Inline" + ], + "type": "string" + }, + "policyEnforcement": { + "description": "policyEnforcement configures the cluster and workshop policy\nengines in Managed mode; ignored in Inline mode.", + "properties": { + "clusterPolicy": { + "description": "ClusterPolicyConfig configures the cluster-wide policy engine.", + "properties": { + "engine": { + "default": "Kyverno", + "description": "engine defaults to Kyverno.", + "enum": [ + "Kyverno", + "PodSecurityStandards", + "OpenShiftSCC", + "None" + ], + "type": "string" + } + }, + "type": "object" + }, + "kyverno": { + "description": "kyverno is required when either engine above resolves to Kyverno.", + "properties": { + "provider": { + "default": "Bundled", + "description": "provider defaults to Bundled.", + "enum": [ + "Bundled", + "External" + ], + "type": "string" + } + }, + "type": "object" + }, + "workshopPolicy": { + "description": "WorkshopPolicyConfig configures the per-workshop isolation engine.", + "properties": { + "engine": { + "default": "Kyverno", + "description": "engine defaults to Kyverno. Setting to None disables workshop\nisolation; the cluster operator takes responsibility for\ncontainment.", + "enum": [ + "Kyverno", + "None" + ], + "type": "string" + } + }, + "type": "object" + } + }, + "required": [ + "clusterPolicy", + "workshopPolicy" + ], + "type": "object" + } + }, + "required": [ + "mode" + ], + "type": "object" + }, + "LookupServiceSpec": { + "description": "LookupServiceSpec defines the desired state of LookupService.\n\nComponent-specific settings (auth, rate-limiting, storage) will be\nadded when the lookup-service owner specifies them; intentionally\nout-of-scope for the v1alpha1 surface.", + "properties": { + "image": { + "description": "ImageRef declares a chart-render-time image override as a separable\nrepository + tag pair. The split shape matches what helm dt\nwrap/unwrap (and similar relocation tools) expect.", + "properties": { + "repository": { + "type": "string" + }, + "tag": { + "type": "string" + } + }, + "type": "object" + }, + "ingress": { + "description": "LookupServiceIngress configures the lookup-service Ingress.", + "properties": { + "prefix": { + "description": "prefix combines with EducatesClusterConfig.status.ingress.domain\nto form the full hostname (e.g., \"educates-api\" with domain\n\"educates.example.com\" yields \"educates-api.educates.example.com\").", + "type": "string" + }, + "tlsSecretRef": { + "description": "tlsSecretRef optionally overrides the cluster wildcard\ncertificate. When unset, the ingress uses\nEducatesClusterConfig.status.ingress.wildcardCertificateSecretRef.", + "properties": { + "name": { + "description": "name of the referent.", + "type": "string" + } + }, + "required": [ + "name" + ], + "type": "object" + } + }, + "required": [ + "prefix" + ], + "type": "object" + }, + "logLevel": { + "default": "info", + "description": "logLevel defaults to info.", + "enum": [ + "debug", + "info", + "warn", + "error" + ], + "type": "string" + }, + "resources": { + "description": "ResourceRequirements describes the compute resource requirements.", + "properties": { + "claims": { + "description": "Claims lists the names of resources, defined in spec.resourceClaims,\nthat are used by this container.\n\nThis field depends on the\nDynamicResourceAllocation feature gate.\n\nThis field is immutable. It can only be set for containers.", + "items": { + "description": "ResourceClaim references one entry in PodSpec.ResourceClaims.", + "properties": { + "name": { + "description": "Name must match the name of one entry in pod.spec.resourceClaims of\nthe Pod where this field is used. It makes that resource available\ninside a container.", + "type": "string" + }, + "request": { + "description": "Request is the name chosen for a request in the referenced claim.\nIf empty, everything from the claim is made available, otherwise\nonly the result of this request.", + "type": "string" + } + }, + "required": [ + "name" + ], + "type": "object" + }, + "type": "array" + }, + "limits": { + "additionalProperties": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "string" + } + ], + "pattern": "^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$" + }, + "description": "Limits describes the maximum amount of compute resources allowed.\nMore info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/", + "type": "object" + }, + "requests": { + "additionalProperties": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "string" + } + ], + "pattern": "^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$" + }, + "description": "Requests describes the minimum amount of compute resources required.\nIf Requests is omitted for a container, it defaults to Limits if that is explicitly specified,\notherwise to an implementation-defined value. Requests cannot exceed Limits.\nMore info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/", + "type": "object" + } + }, + "type": "object" + } + }, + "required": [ + "ingress" + ], + "type": "object" + }, + "SecretsManagerSpec": { + "description": "SecretsManagerSpec defines the desired state of SecretsManager.\n\nsecrets-manager is a singleton at the pod level (the upstream\nimplementation can't scale beyond one replica) so no replicas knob is\nexposed. Image-pull credentials are inherited from\nEducatesClusterConfig.status.imageRegistry.pullSecrets and are not\nduplicated here.", + "properties": { + "image": { + "description": "image overrides the default image reference. Both fields are\noptional; defaults come from the chart's appVersion-derived\nimage inventory.", + "properties": { + "repository": { + "type": "string" + }, + "tag": { + "type": "string" + } + }, + "type": "object" + }, + "logLevel": { + "default": "info", + "description": "logLevel defaults to info.", + "enum": [ + "debug", + "info", + "warn", + "error" + ], + "type": "string" + }, + "resources": { + "description": "ResourceRequirements describes the compute resource requirements.", + "properties": { + "claims": { + "description": "Claims lists the names of resources, defined in spec.resourceClaims,\nthat are used by this container.\n\nThis field depends on the\nDynamicResourceAllocation feature gate.\n\nThis field is immutable. It can only be set for containers.", + "items": { + "description": "ResourceClaim references one entry in PodSpec.ResourceClaims.", + "properties": { + "name": { + "description": "Name must match the name of one entry in pod.spec.resourceClaims of\nthe Pod where this field is used. It makes that resource available\ninside a container.", + "type": "string" + }, + "request": { + "description": "Request is the name chosen for a request in the referenced claim.\nIf empty, everything from the claim is made available, otherwise\nonly the result of this request.", + "type": "string" + } + }, + "required": [ + "name" + ], + "type": "object" + }, + "type": "array" + }, + "limits": { + "additionalProperties": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "string" + } + ], + "pattern": "^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$" + }, + "description": "Limits describes the maximum amount of compute resources allowed.\nMore info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/", + "type": "object" + }, + "requests": { + "additionalProperties": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "string" + } + ], + "pattern": "^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$" + }, + "description": "Requests describes the minimum amount of compute resources required.\nIf Requests is omitted for a container, it defaults to Limits if that is explicitly specified,\notherwise to an implementation-defined value. Requests cannot exceed Limits.\nMore info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/", + "type": "object" + } + }, + "type": "object" + } + }, + "type": "object" + }, + "SessionManagerSpec": { + "description": "SessionManagerSpec defines the desired state of SessionManager.\n\nRequires SecretsManager.Ready and EducatesClusterConfig.Ready; both\ndependencies are singletons so no explicit refs are carried.\n\nImage registry prefix and pull secrets are inherited from\nEducatesClusterConfig.status.imageRegistry; only per-image overrides\nland in spec.images.overrides.", + "properties": { + "allowedEmbeddingHosts": { + "description": "allowedEmbeddingHosts lists hosts allowed to embed Educates\nworkshop frames (CSP frame-ancestors).", + "items": { + "type": "string" + }, + "type": "array" + }, + "defaultAccessCredentials": { + "description": "DefaultAccessCredentials configures the default\nusername/password used for workshop access when a TrainingPortal\ndoesn't override them.", + "properties": { + "passwordSecretRef": { + "description": "passwordSecretRef references a Secret holding the password value.", + "properties": { + "name": { + "description": "name of the referent.", + "type": "string" + } + }, + "required": [ + "name" + ], + "type": "object" + }, + "username": { + "type": "string" + } + }, + "type": "object" + }, + "defaultTheme": { + "description": "defaultTheme names the entry from themes used as the install-wide\ndefault. Must match a Theme.name.", + "type": "string" + }, + "imagePrePuller": { + "description": "ImagePrePuller configures the optional DaemonSet that pre-pulls workshop\nimages onto every node ahead of time, so session startup isn't blocked on\nimage pulls.", + "properties": { + "enabled": { + "default": false, + "type": "boolean" + } + }, + "type": "object" + }, + "images": { + "description": "Images groups image-related overrides. Registry prefix and pull\nsecrets are inherited from\nEducatesClusterConfig.status.imageRegistry; only per-image overrides\nbelong here.", + "properties": { + "overrides": { + "items": { + "description": "ImageOverride entries replace one chart-default image by short name.\nMirrors the v3 imageVersions shape: any image the chart's default\ninventory exposes by name can be overridden here (e.g.,\n\"training-portal\", \"base-environment\", \"jdk17-environment\"). Three\nnames are special-cased by the reconciler because they live outside\nthat inventory: \"session-manager\" (the chart-pod image),\n\"pause-container\" (the pre-puller pause image) and\n\"node-ca-injector\" (its own subchart) — they route to the dedicated\nchart values that control those images.", + "properties": { + "image": { + "description": "image is the full reference including tag. Digest-pinned\nreferences are not supported for the special-cased names\n(\"session-manager\", \"pause-container\", \"node-ca-injector\"),\nwhose chart values are repository+tag shaped.", + "type": "string" + }, + "name": { + "description": "name is the image's short name, e.g. \"session-manager\",\n\"training-portal\", \"jdk17-environment\".", + "type": "string" + } + }, + "required": [ + "image", + "name" + ], + "type": "object" + }, + "type": "array" + } + }, + "type": "object" + }, + "ingressOverrides": { + "description": "IngressOverrides allows SessionManager to override the cluster-wide\ningress secrets for the bare-domain hostnames it serves directly\n(TrainingPortal CRs prefix the domain for individual portals).", + "properties": { + "caCertificateSecretRef": { + "description": "LocalObjectReference is a name-only reference to an object in the\noperator namespace (or, for cluster-scoped kinds, to the cluster-\nscoped object). Mirrors the shape used in the config API group;\nduplicated here to avoid cross-group Go coupling.", + "properties": { + "name": { + "description": "name of the referent.", + "type": "string" + } + }, + "required": [ + "name" + ], + "type": "object" + }, + "protocol": { + "description": "protocol asserts the scheme of the public-facing URLs the\nsession manager and workshops generate. Set to https when TLS\nis terminated outside the cluster (external load balancer or\nproxy forwarding plain HTTP inward) so links are generated\ncorrectly despite no in-cluster certificate being presented.\nEmpty derives from the TLS configuration: https when a\nwildcard certificate is configured, http otherwise.", + "enum": [ + "http", + "https" + ], + "type": "string" + }, + "tlsSecretRef": { + "description": "LocalObjectReference is a name-only reference to an object in the\noperator namespace (or, for cluster-scoped kinds, to the cluster-\nscoped object). Mirrors the shape used in the config API group;\nduplicated here to avoid cross-group Go coupling.", + "properties": { + "name": { + "description": "name of the referent.", + "type": "string" + } + }, + "required": [ + "name" + ], + "type": "object" + } + }, + "type": "object" + }, + "logLevel": { + "default": "info", + "description": "logLevel defaults to info.", + "enum": [ + "debug", + "info", + "warn", + "error" + ], + "type": "string" + }, + "network": { + "description": "SessionNetwork configures network characteristics applied to workshop\nsessions.", + "properties": { + "blockedCidrs": { + "description": "blockedCidrs lists CIDR ranges workshop sessions are denied\nnetwork access to (e.g., cloud metadata endpoints).", + "items": { + "type": "string" + }, + "type": "array" + }, + "packetSize": { + "description": "packetSize sets the MTU for workshop session networking. Useful\non overlay networks where the default MTU is too large.", + "format": "int32", + "minimum": 576, + "type": "integer" + } + }, + "type": "object" + }, + "nodeCATrust": { + "description": "nodeCATrust controls the optional node-ca-injector install.", + "properties": { + "mode": { + "default": "Auto", + "description": "mode defaults to Auto. Auto installs the subchart only when\nthe cluster config publishes a CA Secret reference; with no CA\nconfigured, Auto skips the install silently. Enabled forces\nthe install (refuses if no CA is configured). Disabled keeps\nit uninstalled.", + "enum": [ + "Auto", + "Enabled", + "Disabled" + ], + "type": "string" + } + }, + "type": "object" + }, + "registryMirrors": { + "description": "registryMirrors configures per-registry mirrors for workshop\ncontainer pulls.", + "items": { + "description": "RegistryMirror declares a registry mirror used by workshop containers.", + "properties": { + "mirror": { + "description": "mirror is the upstream registry being mirrored\n(e.g., \"docker.io\").", + "type": "string" + }, + "url": { + "description": "url is the mirror endpoint.", + "type": "string" + } + }, + "required": [ + "mirror", + "url" + ], + "type": "object" + }, + "type": "array" + }, + "remoteAccess": { + "description": "remoteAccess controls the optional remote-access install.", + "properties": { + "mode": { + "default": "Auto", + "description": "mode defaults to Auto. Auto installs the subchart only when a\n`LookupService` CR exists in the cluster (the signal that\ncross-cluster federation is being used). Enabled forces the\ninstall regardless of LookupService presence. Disabled keeps\nit uninstalled.", + "enum": [ + "Auto", + "Enabled", + "Disabled" + ], + "type": "string" + } + }, + "type": "object" + }, + "sessionCookieDomain": { + "description": "sessionCookieDomain sets the cookie domain used by workshop\nsessions for cross-subdomain authentication.", + "type": "string" + }, + "storage": { + "description": "SessionStorage configures persistent storage characteristics for\nworkshop sessions.", + "properties": { + "storageClass": { + "type": "string" + }, + "storageGroup": { + "description": "storageGroup sets the supplemental GID for mounted volumes.", + "format": "int64", + "type": "integer" + }, + "storageUser": { + "description": "storageUser sets the UID for mounted volumes.", + "format": "int64", + "type": "integer" + } + }, + "type": "object" + }, + "themes": { + "description": "themes is a list of named themes available to TrainingPortals.", + "items": { + "description": "Theme is one named entry in the spec.themes list.", + "properties": { + "name": { + "type": "string" + }, + "source": { + "description": "ThemeSource sources theme content. Exactly one of the per-type fields\n(secretRef, configMapRef) should be populated for the selected type.\nSecret is the only source the reconciler supports in v1alpha1;\nConfigMap and URL are reserved and rejected as \"not yet supported\".", + "properties": { + "configMapRef": { + "description": "configMapRef applies when type is ConfigMap.", + "properties": { + "name": { + "type": "string" + }, + "namespace": { + "type": "string" + } + }, + "required": [ + "name", + "namespace" + ], + "type": "object" + }, + "secretRef": { + "description": "secretRef applies when type is Secret. It names a Secret holding\nthe theme assets; when its namespace differs from the release\nnamespace the runtime chart auto-creates a SecretCopier for it.", + "properties": { + "name": { + "type": "string" + }, + "namespace": { + "type": "string" + } + }, + "required": [ + "name", + "namespace" + ], + "type": "object" + }, + "type": { + "description": "ThemeSourceType selects how a theme's content is sourced.\nAdditional types may be added by the session-manager owner.", + "enum": [ + "ConfigMap", + "Secret", + "URL" + ], + "type": "string" + } + }, + "required": [ + "type" + ], + "type": "object" + } + }, + "required": [ + "name", + "source" + ], + "type": "object" + }, + "type": "array" + }, + "tracking": { + "description": "Tracking groups analytics provider configuration.", + "properties": { + "amplitude": { + "description": "TrackingProvider holds a single analytics provider's tracking ID.", + "properties": { + "trackingId": { + "type": "string" + } + }, + "required": [ + "trackingId" + ], + "type": "object" + }, + "clarity": { + "description": "TrackingProvider holds a single analytics provider's tracking ID.", + "properties": { + "trackingId": { + "type": "string" + } + }, + "required": [ + "trackingId" + ], + "type": "object" + }, + "googleAnalytics": { + "description": "TrackingProvider holds a single analytics provider's tracking ID.", + "properties": { + "trackingId": { + "type": "string" + } + }, + "required": [ + "trackingId" + ], + "type": "object" + }, + "webhook": { + "description": "TrackingWebhook configures an HTTP webhook receiver for analytics\nevents.", + "properties": { + "url": { + "type": "string" + } + }, + "required": [ + "url" + ], + "type": "object" + } + }, + "type": "object" + }, + "workshopPolicyOverride": { + "description": "WorkshopPolicyOverride locally overrides\nEducatesClusterConfig.status.policyEnforcement.workshopPolicyEngine\nfor this SessionManager.", + "properties": { + "engine": { + "description": "WorkshopPolicyEngine names the engine enforcing per-workshop isolation\nrules. Mirrors the same-named enum in the config API group;\nduplicated to avoid cross-group Go coupling.", + "enum": [ + "Kyverno", + "None" + ], + "type": "string" + } + }, + "required": [ + "engine" + ], + "type": "object" + } + }, + "type": "object" + } + }, + "$id": "https://schemas.educates.dev/cli/v1alpha1/EducatesConfig.json", + "$schema": "http://json-schema.org/draft-07/schema#", + "additionalProperties": false, + "description": "Escape-hatch CLI config kind. Mirrors the platform CRDs verbatim; CLI hand-wraps apiVersion/kind/metadata at translate time.", + "properties": { + "apiVersion": { + "const": "cli.educates.dev/v1alpha1" + }, + "educatesClusterConfig": { + "$ref": "#/$defs/EducatesClusterConfigSpec" + }, + "kind": { + "const": "EducatesConfig" + }, + "lookupService": { + "$ref": "#/$defs/LookupServiceSpec" + }, + "operator": { + "additionalProperties": false, + "properties": { + "image": { + "additionalProperties": false, + "properties": { + "repository": { + "type": "string" + }, + "tag": { + "type": "string" + } + }, + "type": "object" + }, + "imagePullSecrets": { + "items": { + "minLength": 1, + "type": "string" + }, + "type": "array" + }, + "logLevel": { + "default": "info", + "enum": [ + "debug", + "info", + "warn", + "error" + ], + "type": "string" + } + }, + "type": "object" + }, + "secretsManager": { + "$ref": "#/$defs/SecretsManagerSpec" + }, + "sessionManager": { + "$ref": "#/$defs/SessionManagerSpec" + }, + "target": { + "additionalProperties": false, + "properties": { + "cluster": { + "type": "object" + }, + "provider": { + "minLength": 1, + "type": "string" + }, + "resolver": { + "type": "object" + } + }, + "type": "object" + } + }, + "required": [ + "apiVersion", + "kind" + ], + "title": "EducatesConfig", + "type": "object" +} diff --git a/client-programs/pkg/config/v1alpha1/schemas/EducatesEKSConfig.schema.json b/client-programs/pkg/config/v1alpha1/schemas/EducatesEKSConfig.schema.json new file mode 100644 index 000000000..6273cb7e0 --- /dev/null +++ b/client-programs/pkg/config/v1alpha1/schemas/EducatesEKSConfig.schema.json @@ -0,0 +1,111 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "$id": "https://schemas.educates.dev/cli/v1alpha1/EducatesEKSConfig.json", + "title": "EducatesEKSConfig", + "description": "EKS production scenario. BundledCertManager+ACME(DNS01/Route53) + BundledContour(LoadBalancer) + BundledExternalDNS(Route53) + BundledKyverno. IRSA throughout.", + "type": "object", + "additionalProperties": false, + "required": ["apiVersion", "kind", "aws", "domain", "acme"], + "properties": { + "apiVersion": { "const": "cli.educates.dev/v1alpha1" }, + "kind": { "const": "EducatesEKSConfig" }, + + "aws": { + "type": "object", + "additionalProperties": false, + "required": ["accountId", "region", "route53HostedZoneId"], + "properties": { + "accountId": { "type": "string", "pattern": "^[0-9]{12}$" }, + "region": { "type": "string", "minLength": 1 }, + "route53HostedZoneId": { "type": "string", "minLength": 1 }, + "certManagerRoleARN": { "type": "string" }, + "externalDNSRoleARN": { "type": "string" } + } + }, + + "domain": { "type": "string", "minLength": 1 }, + + "acme": { + "type": "object", + "additionalProperties": false, + "required": ["email"], + "properties": { + "email": { "type": "string", "minLength": 1, "format": "email" }, + "server": { "type": "string", "format": "uri" } + } + }, + + "externalTLSTermination": { + "type": "boolean", + "default": false, + "description": "Asserts TLS for the ingress domain is terminated outside the cluster (external load balancer or proxy forwarding plain HTTP inward); generated portal and workshop URLs use https regardless of in-cluster certificate presence. Maps to SessionManager.spec.ingressOverrides.protocol: https." + }, + + "clusterAdmin": { "type": "boolean", "default": false }, + "lookupService": { "type": "boolean", "default": true }, + "imagePrePuller": { "type": "boolean", "default": false }, + + "websiteStyling": { + "type": "object", + "additionalProperties": false, + "properties": { + "defaultTheme": { "type": "string" }, + "themeDataRefs": { + "type": "array", + "items": { + "type": "object", + "additionalProperties": false, + "required": ["namespace", "name"], + "properties": { + "namespace": { "type": "string", "minLength": 1 }, + "name": { "type": "string", "minLength": 1 } + } + } + } + } + }, + + "secretPropagation": { + "type": "object", + "additionalProperties": false, + "properties": { + "imagePullSecretNames": { "type": "array", "items": { "type": "string", "minLength": 1 } } + } + }, + + "imageVersions": { + "type": "array", + "items": { + "type": "object", + "additionalProperties": false, + "required": ["name", "image"], + "properties": { + "name": { "type": "string", "minLength": 1 }, + "image": { "type": "string", "minLength": 1 } + } + } + }, + + "operator": { + "type": "object", + "additionalProperties": false, + "properties": { + "image": { + "type": "object", + "additionalProperties": false, + "properties": { + "repository": { "type": "string" }, + "tag": { "type": "string" }, + "pullPolicy": { "type": "string", "enum": ["Always", "IfNotPresent", "Never"] } + } + }, + "imagePullSecrets": { "type": "array", "items": { "type": "string", "minLength": 1 } }, + "logLevel": { + "type": "string", + "enum": ["debug", "info", "warn", "error"], + "default": "info" + } + } + } + } +} diff --git a/client-programs/pkg/config/v1alpha1/schemas/EducatesGKEConfig.schema.json b/client-programs/pkg/config/v1alpha1/schemas/EducatesGKEConfig.schema.json new file mode 100644 index 000000000..8123f8739 --- /dev/null +++ b/client-programs/pkg/config/v1alpha1/schemas/EducatesGKEConfig.schema.json @@ -0,0 +1,109 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "$id": "https://schemas.educates.dev/cli/v1alpha1/EducatesGKEConfig.json", + "title": "EducatesGKEConfig", + "description": "GKE production scenario. BundledCertManager+ACME(DNS01/CloudDNS) + BundledContour(LoadBalancer) + BundledExternalDNS(CloudDNS) + BundledKyverno. Workload Identity throughout.", + "type": "object", + "additionalProperties": false, + "required": ["apiVersion", "kind", "gcp", "domain", "acme"], + "properties": { + "apiVersion": { "const": "cli.educates.dev/v1alpha1" }, + "kind": { "const": "EducatesGKEConfig" }, + + "gcp": { + "type": "object", + "additionalProperties": false, + "required": ["project"], + "properties": { + "project": { "type": "string", "minLength": 1 }, + "certManagerServiceAccount": { "type": "string" }, + "externalDNSServiceAccount": { "type": "string" } + } + }, + + "domain": { "type": "string", "minLength": 1 }, + + "acme": { + "type": "object", + "additionalProperties": false, + "required": ["email"], + "properties": { + "email": { "type": "string", "minLength": 1, "format": "email" }, + "server": { "type": "string", "format": "uri" } + } + }, + + "externalTLSTermination": { + "type": "boolean", + "default": false, + "description": "Asserts TLS for the ingress domain is terminated outside the cluster (external load balancer or proxy forwarding plain HTTP inward); generated portal and workshop URLs use https regardless of in-cluster certificate presence. Maps to SessionManager.spec.ingressOverrides.protocol: https." + }, + + "clusterAdmin": { "type": "boolean", "default": false }, + "lookupService": { "type": "boolean", "default": true }, + "imagePrePuller": { "type": "boolean", "default": false }, + + "websiteStyling": { + "type": "object", + "additionalProperties": false, + "properties": { + "defaultTheme": { "type": "string" }, + "themeDataRefs": { + "type": "array", + "items": { + "type": "object", + "additionalProperties": false, + "required": ["namespace", "name"], + "properties": { + "namespace": { "type": "string", "minLength": 1 }, + "name": { "type": "string", "minLength": 1 } + } + } + } + } + }, + + "secretPropagation": { + "type": "object", + "additionalProperties": false, + "properties": { + "imagePullSecretNames": { "type": "array", "items": { "type": "string", "minLength": 1 } } + } + }, + + "imageVersions": { + "type": "array", + "items": { + "type": "object", + "additionalProperties": false, + "required": ["name", "image"], + "properties": { + "name": { "type": "string", "minLength": 1 }, + "image": { "type": "string", "minLength": 1 } + } + } + }, + + "operator": { + "type": "object", + "additionalProperties": false, + "properties": { + "image": { + "type": "object", + "additionalProperties": false, + "properties": { + "repository": { "type": "string" }, + "tag": { "type": "string" }, + "pullPolicy": { "type": "string", "enum": ["Always", "IfNotPresent", "Never"] } + } + }, + "imagePullSecrets": { "type": "array", "items": { "type": "string", "minLength": 1 } }, + "logLevel": { + "type": "string", + "enum": ["debug", "info", "warn", "error"], + "default": "info" + } + } + } + } +} diff --git a/client-programs/pkg/config/v1alpha1/schemas/EducatesInlineConfig.schema.json b/client-programs/pkg/config/v1alpha1/schemas/EducatesInlineConfig.schema.json new file mode 100644 index 000000000..7e1d9ecad --- /dev/null +++ b/client-programs/pkg/config/v1alpha1/schemas/EducatesInlineConfig.schema.json @@ -0,0 +1,119 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "$id": "https://schemas.educates.dev/cli/v1alpha1/EducatesInlineConfig.json", + "title": "EducatesInlineConfig", + "description": "BYO scenario. User asserts that cert-manager (or pre-issued wildcard cert), an ingress controller, and a policy engine already exist on the cluster.", + "type": "object", + "additionalProperties": false, + "required": ["apiVersion", "kind", "domain", "ingressClassName", "wildcardCertificateSecret"], + "properties": { + "apiVersion": { "const": "cli.educates.dev/v1alpha1" }, + "kind": { "const": "EducatesInlineConfig" }, + + "domain": { "type": "string", "minLength": 1 }, + "ingressClassName": { "type": "string", "minLength": 1 }, + "wildcardCertificateSecret": { "type": "string", "minLength": 1 }, + "caCertificateSecret": { "type": "string" }, + "clusterIssuerName": { "type": "string" }, + + "imageRegistry": { + "type": "object", + "additionalProperties": false, + "properties": { + "prefix": { "type": "string" }, + "pullSecrets": { "type": "array", "items": { "type": "string", "minLength": 1 } } + } + }, + + "policyEnforcement": { + "type": "object", + "additionalProperties": false, + "properties": { + "clusterEngine": { + "type": "string", + "enum": ["Kyverno", "PodSecurityStandards", "OpenShiftSCC", "None"] + }, + "workshopEngine": { + "type": "string", + "enum": ["Kyverno", "None"] + } + } + }, + + "externalTLSTermination": { + "type": "boolean", + "default": false, + "description": "Asserts TLS for the ingress domain is terminated outside the cluster (external load balancer or proxy forwarding plain HTTP inward); generated portal and workshop URLs use https regardless of in-cluster certificate presence. Maps to SessionManager.spec.ingressOverrides.protocol: https." + }, + + "clusterAdmin": { "type": "boolean", "default": false }, + "lookupService": { "type": "boolean", "default": true }, + "imagePrePuller": { "type": "boolean", "default": false }, + + "websiteStyling": { + "type": "object", + "additionalProperties": false, + "properties": { + "defaultTheme": { "type": "string" }, + "themeDataRefs": { + "type": "array", + "items": { + "type": "object", + "additionalProperties": false, + "required": ["namespace", "name"], + "properties": { + "namespace": { "type": "string", "minLength": 1 }, + "name": { "type": "string", "minLength": 1 } + } + } + } + } + }, + + "secretPropagation": { + "type": "object", + "additionalProperties": false, + "properties": { + "imagePullSecretNames": { "type": "array", "items": { "type": "string", "minLength": 1 } } + } + }, + + "imageVersions": { + "type": "array", + "items": { + "type": "object", + "additionalProperties": false, + "required": ["name", "image"], + "properties": { + "name": { "type": "string", "minLength": 1 }, + "image": { "type": "string", "minLength": 1 } + } + } + }, + + "operator": { + "type": "object", + "additionalProperties": false, + "properties": { + "image": { + "type": "object", + "additionalProperties": false, + "properties": { + "repository": { "type": "string" }, + "tag": { "type": "string" }, + "pullPolicy": { + "type": "string", + "enum": ["Always", "IfNotPresent", "Never"] + } + } + }, + "imagePullSecrets": { "type": "array", "items": { "type": "string", "minLength": 1 } }, + "logLevel": { + "type": "string", + "enum": ["debug", "info", "warn", "error"], + "default": "info" + } + } + } + } +} diff --git a/client-programs/pkg/config/v1alpha1/schemas/EducatesLocalConfig.schema.json b/client-programs/pkg/config/v1alpha1/schemas/EducatesLocalConfig.schema.json new file mode 100644 index 000000000..db8ee7414 --- /dev/null +++ b/client-programs/pkg/config/v1alpha1/schemas/EducatesLocalConfig.schema.json @@ -0,0 +1,160 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "$id": "https://schemas.educates.dev/cli/v1alpha1/EducatesLocalConfig.json", + "title": "EducatesLocalConfig", + "description": "Laptop kind-cluster scenario kind. Narrow, opinionated; empty file (apiVersion + kind only) is valid.", + "type": "object", + "additionalProperties": false, + "required": ["apiVersion", "kind"], + "properties": { + "apiVersion": { "const": "cli.educates.dev/v1alpha1" }, + "kind": { "const": "EducatesLocalConfig" }, + + "cluster": { + "type": "object", + "additionalProperties": false, + "properties": { + "listenAddress": { "type": "string", "default": "127.0.0.1" }, + "registryListenAddress": { "type": "string" }, + "apiServer": { + "type": "object", + "additionalProperties": false, + "properties": { + "address": { "type": "string" }, + "port": { "type": "integer", "minimum": 0, "maximum": 65535 } + } + }, + "networking": { + "type": "object", + "additionalProperties": false, + "properties": { + "serviceSubnet": { "type": "string" }, + "podSubnet": { "type": "string" } + } + }, + "volumeMounts": { + "type": "array", + "items": { + "type": "object", + "additionalProperties": false, + "required": ["hostPath", "containerPath"], + "properties": { + "hostPath": { "type": "string", "minLength": 1 }, + "containerPath": { "type": "string", "minLength": 1 }, + "readOnly": { "type": "boolean" } + } + } + }, + "registryMirrors": { + "type": "array", + "items": { + "type": "object", + "additionalProperties": false, + "required": ["mirror"], + "properties": { + "mirror": { "type": "string", "minLength": 1 }, + "url": { "type": "string" }, + "username": { "type": "string" }, + "password": { "type": "string" }, + "port": { "type": "string" }, + "bindIP": { "type": "string" } + } + } + } + } + }, + + "resolver": { + "type": "object", + "additionalProperties": false, + "properties": { + "targetAddress": { "type": "string" }, + "extraDomains": { "type": "array", "items": { "type": "string", "minLength": 1 } } + } + }, + + "ingress": { + "type": "object", + "additionalProperties": false, + "properties": { + "domain": { "type": "string" } + } + }, + + "clusterAdmin": { "type": "boolean", "default": true }, + "lookupService": { "type": "boolean", "default": true }, + "imagePrePuller": { "type": "boolean", "default": false }, + + "websiteStyling": { + "type": "object", + "additionalProperties": false, + "properties": { + "defaultTheme": { "type": "string" }, + "themeDataRefs": { + "type": "array", + "items": { + "type": "object", + "additionalProperties": false, + "required": ["namespace", "name"], + "properties": { + "namespace": { "type": "string", "minLength": 1 }, + "name": { "type": "string", "minLength": 1 } + } + } + } + } + }, + + "secretPropagation": { + "type": "object", + "additionalProperties": false, + "properties": { + "imagePullSecretNames": { + "type": "array", + "items": { "type": "string", "minLength": 1 } + } + } + }, + + "imageVersions": { + "type": "array", + "items": { + "type": "object", + "additionalProperties": false, + "required": ["name", "image"], + "properties": { + "name": { "type": "string", "minLength": 1 }, + "image": { "type": "string", "minLength": 1 } + } + } + }, + + "operator": { + "type": "object", + "additionalProperties": false, + "properties": { + "image": { + "type": "object", + "additionalProperties": false, + "properties": { + "repository": { "type": "string" }, + "tag": { "type": "string" }, + "pullPolicy": { + "type": "string", + "enum": ["Always", "IfNotPresent", "Never"] + } + } + }, + "imagePullSecrets": { + "type": "array", + "items": { "type": "string", "minLength": 1 } + }, + "logLevel": { + "type": "string", + "enum": ["debug", "info", "warn", "error"], + "default": "info" + } + } + } + } +} diff --git a/client-programs/pkg/config/v1alpha1/schemas/schemas.go b/client-programs/pkg/config/v1alpha1/schemas/schemas.go new file mode 100644 index 000000000..3655fcf9e --- /dev/null +++ b/client-programs/pkg/config/v1alpha1/schemas/schemas.go @@ -0,0 +1,22 @@ +// Package schemas embeds the JSON schemas for the cli.educates.dev/v1alpha1 +// config kinds. Schemas drive command-time validation, IDE support (via the +// public schemas.educates.dev URL), `local config set` path checks, and +// generated reference docs. +package schemas + +import _ "embed" + +//go:embed EducatesLocalConfig.schema.json +var EducatesLocalConfig []byte + +//go:embed EducatesConfig.schema.json +var EducatesConfig []byte + +//go:embed EducatesInlineConfig.schema.json +var EducatesInlineConfig []byte + +//go:embed EducatesGKEConfig.schema.json +var EducatesGKEConfig []byte + +//go:embed EducatesEKSConfig.schema.json +var EducatesEKSConfig []byte diff --git a/client-programs/pkg/config/v1alpha1/types.go b/client-programs/pkg/config/v1alpha1/types.go new file mode 100644 index 000000000..ccc549863 --- /dev/null +++ b/client-programs/pkg/config/v1alpha1/types.go @@ -0,0 +1,44 @@ +// Package v1alpha1 defines the CLI-facing configuration kinds for the +// Educates v4 installer. The API group is cli.educates.dev/v1alpha1. +// +// These kinds are translated by the CLI into the operator chart values plus +// the four platform CRs (EducatesClusterConfig, SecretsManager, LookupService, +// SessionManager). They are NOT applied to the cluster directly. +package v1alpha1 + +const ( + GroupName = "cli.educates.dev" + Version = "v1alpha1" + APIVersion = GroupName + "/" + Version + + KindEducatesLocalConfig = "EducatesLocalConfig" + + // SchemaBaseURL is where the release workflow publishes the JSON + // schemas (GitHub Pages, mapped to schemas.educates.dev upstream). + // Matches the $id baked into each schema file. + SchemaBaseURL = "https://schemas.educates.dev/cli/" + Version + "/" +) + +// SchemaURL returns the published JSON schema URL for a config kind, +// suitable for yaml-language-server modelines. +func SchemaURL(kind string) string { + return SchemaBaseURL + kind + ".json" +} + +// TypeMeta carries the apiVersion/kind discriminator. Every CLI config kind +// embeds this for kind-aware loading. +type TypeMeta struct { + APIVersion string `yaml:"apiVersion" json:"apiVersion"` + Kind string `yaml:"kind" json:"kind"` +} + +func (t TypeMeta) GetAPIVersion() string { return t.APIVersion } +func (t TypeMeta) GetKind() string { return t.Kind } + +// Config is the marker interface implemented by every CLI config kind in +// this API group. Loaders return Config; callers type-switch to the concrete +// kind they care about. +type Config interface { + GetAPIVersion() string + GetKind() string +} diff --git a/client-programs/pkg/deployer/apply/apply.go b/client-programs/pkg/deployer/apply/apply.go new file mode 100644 index 000000000..423c60adf --- /dev/null +++ b/client-programs/pkg/deployer/apply/apply.go @@ -0,0 +1,139 @@ +// Package apply server-side-applies arbitrary unstructured Kubernetes +// objects from the CLI. Used by deploy to push the four platform CRs +// after the operator chart is installed. +// +// Server-side apply is preferred over kubectl-style client-side apply: +// it converges multiple CLI runs cleanly, surfaces conflict errors with +// the field-owning manager, and matches how the operator itself writes +// back to .status (so co-ownership of .spec stays clean). +package apply + +import ( + "context" + "encoding/json" + "fmt" + + apierrors "k8s.io/apimachinery/pkg/api/errors" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" + "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/apimachinery/pkg/types" + "k8s.io/cli-runtime/pkg/genericclioptions" + "k8s.io/client-go/discovery" + "k8s.io/client-go/discovery/cached/memory" + "k8s.io/client-go/dynamic" + "k8s.io/client-go/restmapper" +) + +// FieldManager is the SSA owner the CLI claims for fields it sets. +const FieldManager = "educates-cli" + +// Client wraps dynamic.Interface + RESTMapper for server-side apply. +// One Client per `educates admin platform deploy` run. +type Client struct { + dyn dynamic.Interface + cache discovery.CachedDiscoveryInterface + mapper *restmapper.DeferredDiscoveryRESTMapper +} + +// New builds a Client from a kubectl-style RESTClientGetter. +func New(getter genericclioptions.RESTClientGetter) (*Client, error) { + cfg, err := getter.ToRESTConfig() + if err != nil { + return nil, fmt.Errorf("REST config: %w", err) + } + dyn, err := dynamic.NewForConfig(cfg) + if err != nil { + return nil, fmt.Errorf("dynamic client: %w", err) + } + dc, err := discovery.NewDiscoveryClientForConfig(cfg) + if err != nil { + return nil, fmt.Errorf("discovery client: %w", err) + } + // memory.NewMemCacheClient is the standard wrapper for the REST + // mapper. A fresh cache per deploy run avoids the trap where CRDs + // installed earlier in this run aren't seen by later apply calls. + cache := memory.NewMemCacheClient(dc) + mapper := restmapper.NewDeferredDiscoveryRESTMapper(cache) + return &Client{dyn: dyn, cache: cache, mapper: mapper}, nil +} + +// InvalidateDiscovery clears the cached discovery snapshot and resets the +// deferred mapper. Call this after applying CRDs so the next RESTMapping +// lookup re-fetches `/apis` and picks up the newly registered kinds. +// Without it, the mapper's reset-on-NoMatchError retry path rebuilds from +// the same stale cache and the new GVK stays invisible. +func (c *Client) InvalidateDiscovery() { + c.cache.Invalidate() + c.mapper.Reset() +} + +// Apply server-side-applies one Unstructured. force=true so re-runs +// after the operator stamps defaults into .spec don't deadlock on field +// conflicts the operator caused. +func (c *Client) Apply(ctx context.Context, obj *unstructured.Unstructured) (*unstructured.Unstructured, error) { + gvk := obj.GroupVersionKind() + mapping, err := c.mapper.RESTMapping(gvk.GroupKind(), gvk.Version) + if err != nil { + return nil, fmt.Errorf("REST mapping for %s: %w", gvk, err) + } + data, err := json.Marshal(obj.Object) + if err != nil { + return nil, fmt.Errorf("marshal %s/%s: %w", gvk.Kind, obj.GetName(), err) + } + + resource := c.dyn.Resource(mapping.Resource) + var typed dynamic.ResourceInterface = resource + if ns := obj.GetNamespace(); ns != "" { + typed = resource.Namespace(ns) + } + + force := true + applied, err := typed.Patch(ctx, obj.GetName(), types.ApplyPatchType, data, metav1.PatchOptions{ + FieldManager: FieldManager, + Force: &force, + }) + if err != nil { + if apierrors.IsNotFound(err) { + return nil, fmt.Errorf("apply %s/%s: target not found (CRD not installed?): %w", gvk.Kind, obj.GetName(), err) + } + return nil, fmt.Errorf("apply %s/%s: %w", gvk.Kind, obj.GetName(), err) + } + return applied, nil +} + +// Get returns the live object for a GVK + name, or NotFound. Used by +// callers that need to poll a status field (e.g. CRD Established) without +// also pulling in the wait package. +func (c *Client) Get(ctx context.Context, gvk schema.GroupVersionKind, namespace, name string) (*unstructured.Unstructured, error) { + mapping, err := c.mapper.RESTMapping(gvk.GroupKind(), gvk.Version) + if err != nil { + return nil, fmt.Errorf("REST mapping for %s: %w", gvk, err) + } + resource := c.dyn.Resource(mapping.Resource) + var typed dynamic.ResourceInterface = resource + if namespace != "" { + typed = resource.Namespace(namespace) + } + return typed.Get(ctx, name, metav1.GetOptions{}) +} + +// Delete removes one object by GVK + name. Idempotent: missing → nil. +func (c *Client) Delete(ctx context.Context, gvk schema.GroupVersionKind, namespace, name string) error { + mapping, err := c.mapper.RESTMapping(gvk.GroupKind(), gvk.Version) + if err != nil { + return fmt.Errorf("REST mapping for %s: %w", gvk, err) + } + resource := c.dyn.Resource(mapping.Resource) + var typed dynamic.ResourceInterface = resource + if namespace != "" { + typed = resource.Namespace(namespace) + } + if err := typed.Delete(ctx, name, metav1.DeleteOptions{}); err != nil { + if apierrors.IsNotFound(err) { + return nil + } + return fmt.Errorf("delete %s/%s: %w", gvk.Kind, name, err) + } + return nil +} diff --git a/client-programs/pkg/deployer/chart/embed.go b/client-programs/pkg/deployer/chart/embed.go new file mode 100644 index 000000000..1ce9b0d44 --- /dev/null +++ b/client-programs/pkg/deployer/chart/embed.go @@ -0,0 +1,70 @@ +// Package chart embeds the educates-installer Helm chart into the CLI +// binary. The chart files are copied from installer/charts/educates-installer/ +// by the `make embed-installer-chart` target (and refreshed from the same +// source whenever the chart changes). +// +// The duplication is intentional: go:embed paths cannot escape the +// containing package, and committing the copy makes builds reproducible +// without a pre-build hook. The Makefile target and `make verify-installer-chart` +// (TODO step 5 follow-up) catch drift. +package chart + +import ( + "embed" + "fmt" + "io/fs" + "strings" + + chart "helm.sh/helm/v4/pkg/chart/v2" + "helm.sh/helm/v4/pkg/chart/loader/archive" + helmloader "helm.sh/helm/v4/pkg/chart/v2/loader" +) + +//go:embed all:files +var chartFS embed.FS + +// Name is the helm chart name. Matches files/Chart.yaml. +const Name = "educates-installer" + +// Load reads the embedded operator chart and returns a parsed *chart.Chart +// ready to pass to helm install/upgrade actions. +// +// helm.sh/helm/v4 doesn't expose a fs.FS-aware loader, so we walk the +// embedded files and hand them to LoadFiles as BufferedFile entries with +// chart-root-relative names (Chart.yaml, templates/foo.yaml, ...). +func Load() (*chart.Chart, error) { + sub, err := fs.Sub(chartFS, "files") + if err != nil { + return nil, fmt.Errorf("embedded chart: open files: %w", err) + } + + var files []*archive.BufferedFile + walkErr := fs.WalkDir(sub, ".", func(path string, d fs.DirEntry, err error) error { + if err != nil { + return err + } + if d.IsDir() { + return nil + } + data, readErr := fs.ReadFile(sub, path) + if readErr != nil { + return readErr + } + // strings.TrimPrefix is a no-op when path is already chart-root + // relative (which fs.Sub guarantees); kept for defence in depth. + files = append(files, &archive.BufferedFile{ + Name: strings.TrimPrefix(path, "./"), + Data: data, + }) + return nil + }) + if walkErr != nil { + return nil, fmt.Errorf("embedded chart: walk: %w", walkErr) + } + + c, err := helmloader.LoadFiles(files) + if err != nil { + return nil, fmt.Errorf("embedded chart: load: %w", err) + } + return c, nil +} diff --git a/client-programs/pkg/deployer/chart/embed_test.go b/client-programs/pkg/deployer/chart/embed_test.go new file mode 100644 index 000000000..c632c8c45 --- /dev/null +++ b/client-programs/pkg/deployer/chart/embed_test.go @@ -0,0 +1,33 @@ +package chart + +import ( + "testing" +) + +func TestLoad_EmbeddedChartParses(t *testing.T) { + c, err := Load() + if err != nil { + t.Fatalf("Load: %v", err) + } + if c == nil || c.Metadata == nil { + t.Fatal("chart: empty metadata") + } + if got, want := c.Metadata.Name, Name; got != want { + t.Errorf("chart name = %q, want %q", got, want) + } + if c.Metadata.Version == "" { + t.Error("chart version: empty") + } + // Sanity check that templates loaded — operator deployment must be + // in the chart for the install to do anything. + var hasDeployment bool + for _, f := range c.Templates { + if f.Name == "templates/deployment.yaml" { + hasDeployment = true + break + } + } + if !hasDeployment { + t.Error("chart: templates/deployment.yaml not found") + } +} diff --git a/client-programs/pkg/deployer/chart/files/Chart.yaml b/client-programs/pkg/deployer/chart/files/Chart.yaml new file mode 100644 index 000000000..46dc29133 --- /dev/null +++ b/client-programs/pkg/deployer/chart/files/Chart.yaml @@ -0,0 +1,27 @@ +apiVersion: v2 +name: educates-installer +description: | + Educates v4 installer. Installs the four CRDs that drive the v4 + control plane (EducatesClusterConfig, SecretsManager, LookupService, + SessionManager) plus the operator that reconciles them: the operator + installs the cluster services (cert-manager, Contour, Kyverno, + external-dns) in Managed mode and the Educates runtime components. +type: application +# Publish-time default registry for the operator image. The release +# workflow rewrites these per fork (one yq -i call); local overrides go +# through values (image.repository or development.imageRegistry). Keep +# in sync with the educates-training-platform subcharts — see +# decisions.md "imageRegistry is a development override; publish-time +# defaults live in Chart.yaml annotations". +annotations: + educates.dev/image-registry-host: "ghcr.io" + educates.dev/image-registry-namespace: "educates" +version: 4.0.0-alpha.1 +appVersion: 4.0.0-alpha.1 +kubeVersion: ">=1.31.0-0" +home: https://educates.dev +sources: + - https://github.com/jorgemoralespou/educates-training-platform +maintainers: + - name: Educates Maintainers + url: https://github.com/jorgemoralespou/educates-training-platform/blob/develop/MAINTAINERS.md diff --git a/client-programs/pkg/deployer/chart/files/crds/config.educates.dev_educatesclusterconfigs.yaml b/client-programs/pkg/deployer/chart/files/crds/config.educates.dev_educatesclusterconfigs.yaml new file mode 100644 index 000000000..d9ed7185b --- /dev/null +++ b/client-programs/pkg/deployer/chart/files/crds/config.educates.dev_educatesclusterconfigs.yaml @@ -0,0 +1,1158 @@ +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.20.1 + name: educatesclusterconfigs.config.educates.dev +spec: + group: config.educates.dev + names: + kind: EducatesClusterConfig + listKind: EducatesClusterConfigList + plural: educatesclusterconfigs + shortNames: + - ecc + singular: educatesclusterconfig + scope: Cluster + versions: + - additionalPrinterColumns: + - jsonPath: .spec.mode + name: Mode + type: string + - jsonPath: .status.phase + name: Phase + type: string + - jsonPath: .metadata.creationTimestamp + name: Age + type: date + name: v1alpha1 + schema: + openAPIV3Schema: + description: |- + EducatesClusterConfig is the singleton resource describing the + cluster-wide configuration of an Educates installation. + properties: + apiVersion: + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + type: string + kind: + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + metadata: + type: object + spec: + description: |- + EducatesClusterConfigSpec defines the desired state of + EducatesClusterConfig. + + CEL invariants (structural): + - spec.mode is immutable; switching modes requires delete + recreate. + - When mode is Inline, the Managed-mode top-level fields + (infrastructure, ingress, dns, policyEnforcement, imageRegistry) + are forbidden. + - When mode is Managed, spec.inline is forbidden. + properties: + dns: + description: |- + dns configures DNS management in Managed mode; ignored in Inline + mode. + properties: + bundledExternalDNS: + description: |- + BundledExternalDNSConfig configures the operator-installed + external-dns chart. v1alpha1 supports Route53 and CloudDNS; other + providers (Cloudflare, AzureDNS, etc.) surface "not yet supported" + validation errors. + + CEL invariants: + - provider==Route53 requires route53 to be set and forbids cloudDNS. + - provider==CloudDNS requires cloudDNS to be set and forbids route53. + properties: + cloudDNS: + description: |- + ExternalDNSCloudDNSConfig configures the GCP CloudDNS provider for + the operator-installed external-dns. + + Credentials are supplied via *exactly one* of: + - CredentialsSecretRef: a Secret in the operator namespace with + key `credentials.json` containing the GCP service-account + JSON key. + - WorkloadIdentityServiceAccount: a GCP service-account email + bound to the external-dns ServiceAccount via the + `iam.gke.io/gcp-service-account` annotation. Preferred on GKE. + properties: + credentialsSecretRef: + description: |- + LocalObjectReference is a reference to a Kubernetes object by name in + the operator namespace. Cluster-scoped references (e.g., ClusterIssuer, + IngressClass) also use this shape. + properties: + name: + description: name of the referent. + type: string + required: + - name + type: object + project: + type: string + workloadIdentityServiceAccount: + type: string + required: + - project + type: object + provider: + allOf: + - enum: + - Route53 + - CloudDNS + - Cloudflare + - AzureDNS + - enum: + - Route53 + - CloudDNS + description: |- + provider selects which DNS provider external-dns publishes + records to. Reuses the DNS01Provider enum for vocabulary + consistency with cert-manager's solver config; validation + rejects Cloudflare/AzureDNS for now. + type: string + route53: + description: |- + ExternalDNSRoute53Config configures the AWS Route53 provider for + the operator-installed external-dns. HostedZoneID is required to + scope external-dns to a specific zone — running unscoped is a + production footgun (a broad IAM role plus no zone filter can + silently rewrite records across the entire account). + + Credentials are supplied via *exactly one* of: + - CredentialsSecretRef: a Secret in the operator namespace with + keys `aws_access_key_id` and `aws_secret_access_key`. + - IAMRoleARN: an IRSA / Pod Identity role assumed via the + external-dns ServiceAccount's `eks.amazonaws.com/role-arn` + annotation. Preferred on EKS. + + CEL elsewhere enforces the exactly-one rule; the operator + validator backs it up with a friendlier error message. + properties: + credentialsSecretRef: + description: |- + LocalObjectReference is a reference to a Kubernetes object by name in + the operator namespace. Cluster-scoped references (e.g., ClusterIssuer, + IngressClass) also use this shape. + properties: + name: + description: name of the referent. + type: string + required: + - name + type: object + hostedZoneID: + type: string + iamRoleARN: + type: string + region: + description: |- + region defaults to the AWS SDK's default detection (pod IMDS + / env vars). Set explicitly when running outside AWS or in + air-gapped environments. + type: string + required: + - hostedZoneID + type: object + sources: + default: + - service + description: |- + sources controls which Kubernetes kinds external-dns watches + for hostname records. Defaults to ["service"] because Educates + publishes the wildcard via an annotation on the Envoy Service. + Users can broaden to ["service","ingress"] (or any + chart-accepted source) when they want per-workshop Ingress + records published as well. + items: + type: string + type: array + required: + - provider + type: object + x-kubernetes-validations: + - message: provider Route53 requires spec.dns.bundledExternalDNS.route53 + and forbids cloudDNS + rule: self.provider != 'Route53' || (has(self.route53) && !has(self.cloudDNS)) + - message: provider CloudDNS requires spec.dns.bundledExternalDNS.cloudDNS + and forbids route53 + rule: self.provider != 'CloudDNS' || (has(self.cloudDNS) && + !has(self.route53)) + provider: + default: None + description: |- + provider defaults to None — appropriate for local clusters using + nip.io or hosts-file resolution. Cloud installs must set this + explicitly. + enum: + - BundledExternalDNS + - Manual + - None + type: string + type: object + imageRegistry: + description: |- + imageRegistry rewrites bundled chart image refs and supplies pull + credentials. Applies in Managed mode (Inline mode has its own + equivalent under spec.inline.imageRegistry). + properties: + prefix: + description: |- + prefix rewrites every bundled image reference to live under this + prefix, e.g., "internal-registry.corp.local/educates". Pre-relocated + bundles (via helm dt wrap/unwrap) do not need this set. + type: string + pullSecrets: + description: |- + pullSecrets references kubernetes.io/dockerconfigjson Secrets in + the operator namespace. + items: + description: |- + LocalObjectReference is a reference to a Kubernetes object by name in + the operator namespace. Cluster-scoped references (e.g., ClusterIssuer, + IngressClass) also use this shape. + properties: + name: + description: name of the referent. + type: string + required: + - name + type: object + type: array + type: object + infrastructure: + description: |- + infrastructure describes the cluster substrate. Used in Managed + mode; ignored in Inline mode. + properties: + cloud: + description: |- + cloud carries provider-specific configuration. Required for cloud + providers (EKS, GKE) when bundled cert-manager or external-dns is + enabled. + properties: + project: + description: |- + project / account identifier, e.g., GCP project ID or AWS account + alias. + type: string + region: + type: string + serviceAccounts: + description: |- + CloudServiceAccounts maps Educates' bundled cluster services to + provider-native workload identities. + properties: + certManager: + description: |- + certManager identity used by cert-manager when requesting + DNS01-validated certificates. + type: string + externalDNS: + description: |- + externalDNS identity used by external-dns when managing DNS + records. + type: string + type: object + type: object + provider: + description: |- + InfrastructureProvider identifies the underlying cluster substrate. + Used by the operator to compute provider-specific defaults and to + validate cloud-related fields. + enum: + - Kind + - Minikube + - EKS + - GKE + - OpenShift + - VCluster + - Generic + type: string + required: + - provider + type: object + ingress: + description: |- + ingress configures the Educates ingress in Managed mode; ignored + in Inline mode. + properties: + certificates: + description: Certificates groups certificate-provider configuration. + properties: + bundledCertManager: + description: |- + BundledCertManagerConfig configures the operator-installed cert-manager + chart and the ClusterIssuer it provides. + properties: + acme: + description: ACMEConfig configures the cert-manager ACME + ClusterIssuer. + properties: + email: + type: string + server: + description: |- + server is the ACME directory URL. Defaults to Let's Encrypt + production. Override for Let's Encrypt staging or another CA. + type: string + solvers: + description: |- + ACMESolvers groups the cert-manager solvers used to satisfy the ACME + challenge. + properties: + dns01: + description: dns01 is required for wildcard issuance. + properties: + azureDNS: + description: AzureDNSConfig configures the + Azure DNS DNS01 solver. + properties: + resourceGroup: + type: string + subscriptionID: + type: string + required: + - resourceGroup + - subscriptionID + type: object + cloudDNS: + description: |- + CloudDNSConfig configures the cert-manager GCP CloudDNS DNS01 + solver and the GCP-side credentials. + + Credentials must be supplied via *exactly one* mechanism: + - WorkloadIdentityServiceAccount: a GCP service-account email + bound to cert-manager's K8s ServiceAccount via the + `iam.gke.io/gcp-service-account` annotation. Recommended on + GKE. + - CredentialsSecretRef: a Secret in the operator namespace + with key `credentials.json` containing a GCP service-account + JSON key. v1alpha1 reserves the field but rejects it as + "not yet supported"; static-creds support is a follow-up. + properties: + credentialsSecretRef: + description: |- + LocalObjectReference is a reference to a Kubernetes object by name in + the operator namespace. Cluster-scoped references (e.g., ClusterIssuer, + IngressClass) also use this shape. + properties: + name: + description: name of the referent. + type: string + required: + - name + type: object + project: + type: string + workloadIdentityServiceAccount: + type: string + zone: + type: string + required: + - project + type: object + cloudflare: + description: CloudflareConfig configures the + Cloudflare DNS01 solver. + properties: + apiTokenSecretRef: + description: |- + apiTokenSecretRef references a Secret holding the Cloudflare API + token. The default key is "api-token". + properties: + key: + description: key within the Secret. + Defaults vary by use site. + type: string + name: + description: name of the Secret. + type: string + required: + - name + type: object + required: + - apiTokenSecretRef + type: object + provider: + description: |- + DNS01Provider names a cert-manager DNS01 solver. Required for wildcard + certificate issuance via ACME. + enum: + - Route53 + - CloudDNS + - Cloudflare + - AzureDNS + type: string + route53: + description: |- + Route53Config configures the cert-manager Route53 DNS01 solver + and the AWS-side credentials it needs to write TXT records during + ACME challenges. + + Credentials must be supplied via *exactly one* mechanism: + - IAMRoleARN: marks cert-manager's ServiceAccount with an + `eks.amazonaws.com/role-arn` annotation; cert-manager assumes + the role via IRSA / Pod Identity. Recommended on EKS. + - CredentialsSecretRef: a Secret in the operator namespace + with keys `aws_access_key_id` + `aws_secret_access_key`. + v1alpha1 reserves the field but rejects it as "not yet + supported"; static-creds support is a follow-up. + + CEL elsewhere enforces the mutual-exclusivity rule; the + operator validator backs it up with a friendlier message. + properties: + credentialsSecretRef: + description: |- + LocalObjectReference is a reference to a Kubernetes object by name in + the operator namespace. Cluster-scoped references (e.g., ClusterIssuer, + IngressClass) also use this shape. + properties: + name: + description: name of the referent. + type: string + required: + - name + type: object + hostedZoneID: + type: string + iamRoleARN: + type: string + region: + type: string + required: + - hostedZoneID + type: object + required: + - provider + type: object + http01: + description: |- + ACMEHTTP01Solver configures the optional HTTP01 solver. Rarely needed + because DNS01 is required for wildcards. + properties: + ingressClassName: + description: |- + ingressClassName defaults to spec.ingress.ingressClassName when + unset. + type: string + type: object + required: + - dns01 + type: object + required: + - email + - solvers + type: object + customCA: + description: CustomCAConfig configures a self-signed/custom + CA-backed ClusterIssuer. + properties: + caCertificateRef: + description: |- + caCertificateRef references a Secret holding the CA's own cert and + key (keys: tls.crt, tls.key). Namespace defaults to the operator + namespace when empty. + properties: + name: + description: name of the referent. + type: string + namespace: + description: namespace of the referent. Empty + means the operator namespace. + type: string + required: + - name + type: object + required: + - caCertificateRef + type: object + issuerType: + description: |- + IssuerType selects the cert-manager ClusterIssuer flavour for the + BundledCertManager provider. + enum: + - ACME + - CustomCA + type: string + required: + - issuerType + type: object + externalCertManager: + description: |- + ExternalCertManagerConfig assumes cert-manager is already installed + and references an existing ClusterIssuer; the operator only creates + the wildcard Certificate. + properties: + clusterIssuerRef: + description: |- + LocalObjectReference is a reference to a Kubernetes object by name in + the operator namespace. Cluster-scoped references (e.g., ClusterIssuer, + IngressClass) also use this shape. + properties: + name: + description: name of the referent. + type: string + required: + - name + type: object + required: + - clusterIssuerRef + type: object + provider: + description: |- + CertificatesProvider selects how the wildcard TLS certificate is + provisioned. + enum: + - BundledCertManager + - ExternalCertManager + - StaticCertificate + type: string + staticCertificate: + description: |- + StaticCertificateConfig declares a pre-provisioned wildcard TLS + certificate; no cert-manager is involved. + properties: + caCertificateRef: + description: |- + caCertificateRef optionally references a Secret with the ca.crt + key for the issuing CA chain. + properties: + name: + description: name of the referent. + type: string + required: + - name + type: object + tlsSecretRef: + description: |- + tlsSecretRef references a kubernetes.io/tls Secret with keys + tls.crt and tls.key. + properties: + name: + description: name of the referent. + type: string + required: + - name + type: object + required: + - tlsSecretRef + type: object + required: + - provider + type: object + controller: + description: IngressController groups ingress-controller configuration. + properties: + bundledContour: + description: |- + BundledContourConfig configures the operator-installed Contour ingress + controller. + properties: + envoyServiceType: + default: LoadBalancer + description: |- + envoyServiceType selects the Kubernetes Service type for the + Envoy DaemonSet. Defaults to LoadBalancer so cloud-provider + installs (EKS, GKE, AKS, OpenShift) work out of the box; + set explicitly to NodePort on kind / minikube / vCluster + installs where no in-cluster LoadBalancer controller exists. + enum: + - LoadBalancer + - NodePort + - ClusterIP + type: string + operational: + description: |- + OperationalBlock collects the per-Deployment operational knobs of a + Bundled cluster service. In v1alpha1 only BundledContour carries it: + the cert-manager / external-dns / kyverno blocks were dropped + (2026-06-11) because their semantics didn't hold against the + upstream charts — external-dns 1.21.1 hardcodes replicas to 1 and + exposes no replica value, Kyverno fanning one count across its four + controllers conflicts with upstream HA guidance (3+ for the + admission controller only), and cert-manager never consumed it. + They return when per-service shapes are validated against each + chart's real values surface. Of the knobs below, the reconciler + currently applies replicas; the rest are accepted but not yet + wired into chart values. + properties: + nodeSelector: + additionalProperties: + type: string + type: object + podAnnotations: + additionalProperties: + type: string + type: object + podLabels: + additionalProperties: + type: string + type: object + priorityClassName: + type: string + replicas: + description: |- + replicas overrides the operator-computed default. The default + varies by infrastructure provider (typically 1 for Kind/Minikube, + 2+ otherwise). + format: int32 + minimum: 0 + type: integer + resources: + description: ResourceRequirements describes the compute + resource requirements. + properties: + claims: + description: |- + Claims lists the names of resources, defined in spec.resourceClaims, + that are used by this container. + + This field depends on the + DynamicResourceAllocation feature gate. + + This field is immutable. It can only be set for containers. + items: + description: ResourceClaim references one entry + in PodSpec.ResourceClaims. + properties: + name: + description: |- + Name must match the name of one entry in pod.spec.resourceClaims of + the Pod where this field is used. It makes that resource available + inside a container. + type: string + request: + description: |- + Request is the name chosen for a request in the referenced claim. + If empty, everything from the claim is made available, otherwise + only the result of this request. + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: |- + Limits describes the maximum amount of compute resources allowed. + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: |- + Requests describes the minimum amount of compute resources required. + If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, + otherwise to an implementation-defined value. Requests cannot exceed Limits. + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ + type: object + type: object + tolerations: + items: + description: |- + The pod this Toleration is attached to tolerates any taint that matches + the triple using the matching operator . + properties: + effect: + description: |- + Effect indicates the taint effect to match. Empty means match all taint effects. + When specified, allowed values are NoSchedule, PreferNoSchedule and NoExecute. + type: string + key: + description: |- + Key is the taint key that the toleration applies to. Empty means match all taint keys. + If the key is empty, operator must be Exists; this combination means to match all values and all keys. + type: string + operator: + description: |- + Operator represents a key's relationship to the value. + Valid operators are Exists, Equal, Lt, and Gt. Defaults to Equal. + Exists is equivalent to wildcard for value, so that a pod can + tolerate all taints of a particular category. + Lt and Gt perform numeric comparisons (requires feature gate TaintTolerationComparisonOperators). + type: string + tolerationSeconds: + description: |- + TolerationSeconds represents the period of time the toleration (which must be + of effect NoExecute, otherwise this field is ignored) tolerates the taint. By default, + it is not set, which means tolerate the taint forever (do not evict). Zero and + negative values will be treated as 0 (evict immediately) by the system. + format: int64 + type: integer + value: + description: |- + Value is the taint value the toleration matches to. + If the operator is Exists, the value should be empty, otherwise just a regular string. + type: string + type: object + type: array + type: object + type: object + provider: + description: |- + IngressControllerProvider selects how the cluster's ingress controller + is provided. + enum: + - BundledContour + - ExternalIngressController + type: string + required: + - provider + type: object + domain: + description: |- + domain is the wildcard subdomain under which Educates serves + workshops, e.g., "educates.example.com". + type: string + ingressClassName: + description: |- + ingressClassName names the IngressClass used by Educates. In + BundledContour mode the operator creates an IngressClass with + this name; in External mode it must already exist. + type: string + required: + - certificates + - controller + - domain + - ingressClassName + type: object + inline: + description: |- + inline declares pre-existing cluster resources. Used in Inline + mode; ignored in Managed mode. + properties: + imageRegistry: + description: |- + ImageRegistry configures registry rewriting and pull credentials. + Applies to all bundled charts in Managed mode and to the runtime in + both modes. + properties: + prefix: + description: |- + prefix rewrites every bundled image reference to live under this + prefix, e.g., "internal-registry.corp.local/educates". Pre-relocated + bundles (via helm dt wrap/unwrap) do not need this set. + type: string + pullSecrets: + description: |- + pullSecrets references kubernetes.io/dockerconfigjson Secrets in + the operator namespace. + items: + description: |- + LocalObjectReference is a reference to a Kubernetes object by name in + the operator namespace. Cluster-scoped references (e.g., ClusterIssuer, + IngressClass) also use this shape. + properties: + name: + description: name of the referent. + type: string + required: + - name + type: object + type: array + type: object + ingress: + description: |- + InlineIngress declares pre-existing ingress resources for Inline + mode. The operator validates these and republishes them in status. + properties: + caCertificateSecretRef: + description: |- + caCertificateSecretRef references a Secret with the ca.crt key + for the issuing CA chain. Optional. + properties: + name: + description: name of the referent. + type: string + namespace: + description: namespace of the referent. Empty means the + operator namespace. + type: string + required: + - name + type: object + clusterIssuerRef: + description: |- + clusterIssuerRef references an existing ClusterIssuer that must be + Ready. Optional; informational for components. + properties: + name: + description: name of the referent. + type: string + required: + - name + type: object + domain: + type: string + ingressClassName: + type: string + wildcardCertificateSecretRef: + description: |- + wildcardCertificateSecretRef references a kubernetes.io/tls Secret + with keys tls.crt and tls.key, valid for *.. + properties: + name: + description: name of the referent. + type: string + required: + - name + type: object + required: + - domain + - ingressClassName + - wildcardCertificateSecretRef + type: object + policyEnforcement: + description: |- + InlinePolicyEnforcement declares the policy engines already in place + for Inline mode. Enforced engines are identified, not installed. + properties: + clusterPolicyEngine: + description: ClusterPolicyEngine names the cluster-wide policy + enforcement engine. + enum: + - Kyverno + - PodSecurityStandards + - OpenShiftSCC + - None + type: string + workshopPolicyEngine: + description: |- + WorkshopPolicyEngine names the engine enforcing per-workshop isolation + rules. Setting to None disables workshop isolation. + enum: + - Kyverno + - None + type: string + required: + - clusterPolicyEngine + - workshopPolicyEngine + type: object + required: + - ingress + - policyEnforcement + type: object + mode: + description: |- + ClusterConfigMode selects between operator-managed and user-declared + cluster infrastructure. Immutable once set; switching modes requires + deleting and recreating the resource. + enum: + - Managed + - Inline + type: string + policyEnforcement: + description: |- + policyEnforcement configures the cluster and workshop policy + engines in Managed mode; ignored in Inline mode. + properties: + clusterPolicy: + description: ClusterPolicyConfig configures the cluster-wide policy + engine. + properties: + engine: + default: Kyverno + description: engine defaults to Kyverno. + enum: + - Kyverno + - PodSecurityStandards + - OpenShiftSCC + - None + type: string + type: object + kyverno: + description: kyverno is required when either engine above resolves + to Kyverno. + properties: + provider: + default: Bundled + description: provider defaults to Bundled. + enum: + - Bundled + - External + type: string + type: object + workshopPolicy: + description: WorkshopPolicyConfig configures the per-workshop + isolation engine. + properties: + engine: + default: Kyverno + description: |- + engine defaults to Kyverno. Setting to None disables workshop + isolation; the cluster operator takes responsibility for + containment. + enum: + - Kyverno + - None + type: string + type: object + required: + - clusterPolicy + - workshopPolicy + type: object + required: + - mode + type: object + x-kubernetes-validations: + - message: spec.mode is immutable; delete and recreate the resource to + switch modes + rule: self.mode == oldSelf.mode + - message: spec.{infrastructure,ingress,dns,policyEnforcement,imageRegistry} + are forbidden when mode is Inline + rule: self.mode != 'Inline' || (!has(self.infrastructure) && !has(self.ingress) + && !has(self.dns) && !has(self.policyEnforcement) && !has(self.imageRegistry)) + - message: spec.inline is forbidden when mode is Managed + rule: self.mode != 'Managed' || !has(self.inline) + status: + description: |- + EducatesClusterConfigStatus is the public interface that component CRs + (SecretsManager, LookupService, SessionManager) consume. Phase 1 adds + the inter-CR contract fields (mode, ingress, policyEnforcement, + imageRegistry); the bundledChartVersions field lands in Phase 2/3 + alongside Managed-mode chart installs. + properties: + bundledChartVersions: + additionalProperties: + type: string + description: |- + bundledChartVersions records the version of each upstream Helm + chart the operator has installed in Managed mode. Keys are the + upstream chart names (e.g., "cert-manager", "contour"); values are + the chart's appVersion. Populated as charts are installed; absent + in Inline mode. + type: object + conditions: + description: |- + conditions report the resource's state. Phase 1 publishes: + - Ready (aggregate) + - ValidationSucceeded (Inline mode: refs validated) + Managed-mode conditions (IngressReady, CertificatesReady, + DNSReady, PolicyEnforcementReady, InfrastructureConfigured) land + in later phases alongside their producing reconcilers. + items: + description: Condition contains details for one aspect of the current + state of this API Resource. + properties: + lastTransitionTime: + description: |- + lastTransitionTime is the last time the condition transitioned from one status to another. + This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable. + format: date-time + type: string + message: + description: |- + message is a human readable message indicating details about the transition. + This may be an empty string. + maxLength: 32768 + type: string + observedGeneration: + description: |- + observedGeneration represents the .metadata.generation that the condition was set based upon. + For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date + with respect to the current state of the instance. + format: int64 + minimum: 0 + type: integer + reason: + description: |- + reason contains a programmatic identifier indicating the reason for the condition's last transition. + Producers of specific condition types may define expected values and meanings for this field, + and whether the values are considered a guaranteed API. + The value should be a CamelCase string. + This field may not be empty. + maxLength: 1024 + minLength: 1 + pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ + type: string + status: + description: status of the condition, one of True, False, Unknown. + enum: + - "True" + - "False" + - Unknown + type: string + type: + description: type of condition in CamelCase or in foo.example.com/CamelCase. + maxLength: 316 + pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ + type: string + required: + - lastTransitionTime + - message + - reason + - status + - type + type: object + type: array + x-kubernetes-list-map-keys: + - type + x-kubernetes-list-type: map + imageRegistry: + description: |- + imageRegistry publishes the rewriting prefix and pull secrets, if + configured. Always populated when reconciliation succeeds; an + empty prefix and empty pullSecrets means no rewriting is in effect. + properties: + prefix: + description: |- + prefix rewrites every bundled image reference to live under this + prefix, e.g., "internal-registry.corp.local/educates". Pre-relocated + bundles (via helm dt wrap/unwrap) do not need this set. + type: string + pullSecrets: + description: |- + pullSecrets references kubernetes.io/dockerconfigjson Secrets in + the operator namespace. + items: + description: |- + LocalObjectReference is a reference to a Kubernetes object by name in + the operator namespace. Cluster-scoped references (e.g., ClusterIssuer, + IngressClass) also use this shape. + properties: + name: + description: name of the referent. + type: string + required: + - name + type: object + type: array + type: object + ingress: + description: |- + ingress publishes the validated ingress contract for components to + consume. Populated once validation succeeds. + properties: + caCertificateSecretRef: + description: caCertificateSecretRef is set when a CA Secret is + configured. + properties: + name: + type: string + namespace: + type: string + required: + - name + - namespace + type: object + clusterIssuerRef: + description: |- + clusterIssuerRef names a cluster-wide ClusterIssuer when one was + configured. Components use this informationally; nothing in the + status pipeline depends on it. + properties: + name: + description: name of the referent. + type: string + required: + - name + type: object + domain: + type: string + ingressClassName: + type: string + wildcardCertificateSecretRef: + description: |- + wildcardCertificateSecretRef points at the operator-namespace + Secret holding the wildcard cert+key. + properties: + name: + type: string + namespace: + type: string + required: + - name + - namespace + type: object + required: + - domain + - ingressClassName + - wildcardCertificateSecretRef + type: object + mode: + description: |- + mode echoes spec.mode at the time of last successful reconcile. + Components can branch on this without reading spec. + enum: + - Managed + - Inline + type: string + observedGeneration: + description: observedGeneration tracks the spec generation last reconciled. + format: int64 + type: integer + phase: + description: |- + phase is an advisory summary of the operator's current activity on + this resource; conditions carry the authoritative state. + enum: + - Pending + - Installing + - Validating + - Ready + - Degraded + - Uninstalling + type: string + policyEnforcement: + description: policyEnforcement publishes the resolved policy engines. + properties: + clusterPolicyEngine: + description: ClusterPolicyEngine names the cluster-wide policy + enforcement engine. + enum: + - Kyverno + - PodSecurityStandards + - OpenShiftSCC + - None + type: string + workshopPolicyEngine: + description: |- + WorkshopPolicyEngine names the engine enforcing per-workshop isolation + rules. Setting to None disables workshop isolation. + enum: + - Kyverno + - None + type: string + required: + - clusterPolicyEngine + - workshopPolicyEngine + type: object + type: object + required: + - spec + type: object + x-kubernetes-validations: + - message: EducatesClusterConfig must be named 'cluster' (singleton per cluster) + rule: self.metadata.name == 'cluster' + served: true + storage: true + subresources: + status: {} diff --git a/client-programs/pkg/deployer/chart/files/crds/platform.educates.dev_lookupservices.yaml b/client-programs/pkg/deployer/chart/files/crds/platform.educates.dev_lookupservices.yaml new file mode 100644 index 000000000..092e09e13 --- /dev/null +++ b/client-programs/pkg/deployer/chart/files/crds/platform.educates.dev_lookupservices.yaml @@ -0,0 +1,283 @@ +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.20.1 + name: lookupservices.platform.educates.dev +spec: + group: platform.educates.dev + names: + kind: LookupService + listKind: LookupServiceList + plural: lookupservices + singular: lookupservice + scope: Cluster + versions: + - additionalPrinterColumns: + - jsonPath: .status.phase + name: Phase + type: string + - jsonPath: .metadata.creationTimestamp + name: Age + type: date + name: v1alpha1 + schema: + openAPIV3Schema: + description: |- + LookupService is the singleton resource that drives installation of + the lookup-service component. + properties: + apiVersion: + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + type: string + kind: + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + metadata: + type: object + spec: + description: |- + LookupServiceSpec defines the desired state of LookupService. + + Component-specific settings (auth, rate-limiting, storage) will be + added when the lookup-service owner specifies them; intentionally + out-of-scope for the v1alpha1 surface. + properties: + image: + description: |- + ImageRef declares a chart-render-time image override as a separable + repository + tag pair. The split shape matches what helm dt + wrap/unwrap (and similar relocation tools) expect. + properties: + repository: + type: string + tag: + type: string + type: object + ingress: + description: LookupServiceIngress configures the lookup-service Ingress. + properties: + prefix: + description: |- + prefix combines with EducatesClusterConfig.status.ingress.domain + to form the full hostname (e.g., "educates-api" with domain + "educates.example.com" yields "educates-api.educates.example.com"). + type: string + tlsSecretRef: + description: |- + tlsSecretRef optionally overrides the cluster wildcard + certificate. When unset, the ingress uses + EducatesClusterConfig.status.ingress.wildcardCertificateSecretRef. + properties: + name: + description: name of the referent. + type: string + required: + - name + type: object + required: + - prefix + type: object + logLevel: + default: info + description: logLevel defaults to info. + enum: + - debug + - info + - warn + - error + type: string + resources: + description: ResourceRequirements describes the compute resource requirements. + properties: + claims: + description: |- + Claims lists the names of resources, defined in spec.resourceClaims, + that are used by this container. + + This field depends on the + DynamicResourceAllocation feature gate. + + This field is immutable. It can only be set for containers. + items: + description: ResourceClaim references one entry in PodSpec.ResourceClaims. + properties: + name: + description: |- + Name must match the name of one entry in pod.spec.resourceClaims of + the Pod where this field is used. It makes that resource available + inside a container. + type: string + request: + description: |- + Request is the name chosen for a request in the referenced claim. + If empty, everything from the claim is made available, otherwise + only the result of this request. + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: |- + Limits describes the maximum amount of compute resources allowed. + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: |- + Requests describes the minimum amount of compute resources required. + If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, + otherwise to an implementation-defined value. Requests cannot exceed Limits. + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ + type: object + type: object + required: + - ingress + type: object + status: + description: |- + LookupServiceStatus defines the observed state of LookupService. + Phase 4 publishes the full CRD draft r3 §3 contract: phase + + conditions + url + installedVersion + deploymentRef. + properties: + conditions: + description: |- + conditions report the resource's state. Phase 4 publishes: + - Ready (aggregate) + - ClusterConfigAvailable (EducatesClusterConfig.Ready gate) + - Deployed (helm release + Deployment Available) + items: + description: Condition contains details for one aspect of the current + state of this API Resource. + properties: + lastTransitionTime: + description: |- + lastTransitionTime is the last time the condition transitioned from one status to another. + This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable. + format: date-time + type: string + message: + description: |- + message is a human readable message indicating details about the transition. + This may be an empty string. + maxLength: 32768 + type: string + observedGeneration: + description: |- + observedGeneration represents the .metadata.generation that the condition was set based upon. + For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date + with respect to the current state of the instance. + format: int64 + minimum: 0 + type: integer + reason: + description: |- + reason contains a programmatic identifier indicating the reason for the condition's last transition. + Producers of specific condition types may define expected values and meanings for this field, + and whether the values are considered a guaranteed API. + The value should be a CamelCase string. + This field may not be empty. + maxLength: 1024 + minLength: 1 + pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ + type: string + status: + description: status of the condition, one of True, False, Unknown. + enum: + - "True" + - "False" + - Unknown + type: string + type: + description: type of condition in CamelCase or in foo.example.com/CamelCase. + maxLength: 316 + pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ + type: string + required: + - lastTransitionTime + - message + - reason + - status + - type + type: object + type: array + x-kubernetes-list-map-keys: + - type + x-kubernetes-list-type: map + deploymentRef: + description: |- + deploymentRef names the upstream Deployment the operator is + gating Ready on. Stable across reconciles. + properties: + name: + type: string + namespace: + type: string + required: + - name + - namespace + type: object + installedVersion: + description: |- + installedVersion records the lookup-service chart version most + recently applied. + type: string + observedGeneration: + format: int64 + type: integer + phase: + description: |- + ComponentPhase summarises the operator's current activity on a + platform component. Phases are advisory; conditions carry the + authoritative state. + enum: + - Pending + - Installing + - Ready + - Degraded + - Uninstalling + type: string + url: + description: |- + url is the fully-qualified URL the lookup-service Ingress is + reachable at. Composed from spec.ingress.prefix and + EducatesClusterConfig.status.ingress.domain. Always https in + v1alpha1 (the operator always requires a wildcard TLS Secret + on the cluster config). + type: string + type: object + required: + - spec + type: object + x-kubernetes-validations: + - message: LookupService must be named 'cluster' (singleton per cluster) + rule: self.metadata.name == 'cluster' + served: true + storage: true + subresources: + status: {} diff --git a/client-programs/pkg/deployer/chart/files/crds/platform.educates.dev_secretsmanagers.yaml b/client-programs/pkg/deployer/chart/files/crds/platform.educates.dev_secretsmanagers.yaml new file mode 100644 index 000000000..5ee9f4c0e --- /dev/null +++ b/client-programs/pkg/deployer/chart/files/crds/platform.educates.dev_secretsmanagers.yaml @@ -0,0 +1,255 @@ +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.20.1 + name: secretsmanagers.platform.educates.dev +spec: + group: platform.educates.dev + names: + kind: SecretsManager + listKind: SecretsManagerList + plural: secretsmanagers + singular: secretsmanager + scope: Cluster + versions: + - additionalPrinterColumns: + - jsonPath: .status.phase + name: Phase + type: string + - jsonPath: .metadata.creationTimestamp + name: Age + type: date + name: v1alpha1 + schema: + openAPIV3Schema: + description: |- + SecretsManager is the singleton resource that drives installation of + the secrets-manager component. + properties: + apiVersion: + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + type: string + kind: + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + metadata: + type: object + spec: + description: |- + SecretsManagerSpec defines the desired state of SecretsManager. + + secrets-manager is a singleton at the pod level (the upstream + implementation can't scale beyond one replica) so no replicas knob is + exposed. Image-pull credentials are inherited from + EducatesClusterConfig.status.imageRegistry.pullSecrets and are not + duplicated here. + properties: + image: + description: |- + image overrides the default image reference. Both fields are + optional; defaults come from the chart's appVersion-derived + image inventory. + properties: + repository: + type: string + tag: + type: string + type: object + logLevel: + default: info + description: logLevel defaults to info. + enum: + - debug + - info + - warn + - error + type: string + resources: + description: ResourceRequirements describes the compute resource requirements. + properties: + claims: + description: |- + Claims lists the names of resources, defined in spec.resourceClaims, + that are used by this container. + + This field depends on the + DynamicResourceAllocation feature gate. + + This field is immutable. It can only be set for containers. + items: + description: ResourceClaim references one entry in PodSpec.ResourceClaims. + properties: + name: + description: |- + Name must match the name of one entry in pod.spec.resourceClaims of + the Pod where this field is used. It makes that resource available + inside a container. + type: string + request: + description: |- + Request is the name chosen for a request in the referenced claim. + If empty, everything from the claim is made available, otherwise + only the result of this request. + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: |- + Limits describes the maximum amount of compute resources allowed. + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: |- + Requests describes the minimum amount of compute resources required. + If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, + otherwise to an implementation-defined value. Requests cannot exceed Limits. + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ + type: object + type: object + type: object + status: + description: |- + SecretsManagerStatus defines the observed state of SecretsManager. + Mirrors the CRD draft r3 §2 status contract: phase + conditions + (aggregate Ready plus ClusterConfigAvailable + Deployed), plus the + installedVersion / deploymentRef pair that downstream tooling can + observe to discover the runtime install. + properties: + conditions: + description: |- + conditions report the resource's state. Phase 4 publishes: + - Ready (aggregate) + - ClusterConfigAvailable (EducatesClusterConfig.Ready gate) + - Deployed (helm release present + Deployment Available) + items: + description: Condition contains details for one aspect of the current + state of this API Resource. + properties: + lastTransitionTime: + description: |- + lastTransitionTime is the last time the condition transitioned from one status to another. + This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable. + format: date-time + type: string + message: + description: |- + message is a human readable message indicating details about the transition. + This may be an empty string. + maxLength: 32768 + type: string + observedGeneration: + description: |- + observedGeneration represents the .metadata.generation that the condition was set based upon. + For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date + with respect to the current state of the instance. + format: int64 + minimum: 0 + type: integer + reason: + description: |- + reason contains a programmatic identifier indicating the reason for the condition's last transition. + Producers of specific condition types may define expected values and meanings for this field, + and whether the values are considered a guaranteed API. + The value should be a CamelCase string. + This field may not be empty. + maxLength: 1024 + minLength: 1 + pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ + type: string + status: + description: status of the condition, one of True, False, Unknown. + enum: + - "True" + - "False" + - Unknown + type: string + type: + description: type of condition in CamelCase or in foo.example.com/CamelCase. + maxLength: 316 + pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ + type: string + required: + - lastTransitionTime + - message + - reason + - status + - type + type: object + type: array + x-kubernetes-list-map-keys: + - type + x-kubernetes-list-type: map + deploymentRef: + description: |- + deploymentRef names the upstream Deployment the operator is + gating Ready on. Stable across reconciles; populated once the + helm install lands. + properties: + name: + type: string + namespace: + type: string + required: + - name + - namespace + type: object + installedVersion: + description: |- + installedVersion records the secrets-manager chart version the + operator most recently applied. Reads back from the embedded + chart's metadata; mirrors what `helm get values` would show. + type: string + observedGeneration: + format: int64 + type: integer + phase: + description: |- + ComponentPhase summarises the operator's current activity on a + platform component. Phases are advisory; conditions carry the + authoritative state. + enum: + - Pending + - Installing + - Ready + - Degraded + - Uninstalling + type: string + type: object + required: + - spec + type: object + x-kubernetes-validations: + - message: SecretsManager must be named 'cluster' (singleton per cluster) + rule: self.metadata.name == 'cluster' + served: true + storage: true + subresources: + status: {} diff --git a/client-programs/pkg/deployer/chart/files/crds/platform.educates.dev_sessionmanagers.yaml b/client-programs/pkg/deployer/chart/files/crds/platform.educates.dev_sessionmanagers.yaml new file mode 100644 index 000000000..06862d08f --- /dev/null +++ b/client-programs/pkg/deployer/chart/files/crds/platform.educates.dev_sessionmanagers.yaml @@ -0,0 +1,523 @@ +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.20.1 + name: sessionmanagers.platform.educates.dev +spec: + group: platform.educates.dev + names: + kind: SessionManager + listKind: SessionManagerList + plural: sessionmanagers + singular: sessionmanager + scope: Cluster + versions: + - additionalPrinterColumns: + - jsonPath: .status.phase + name: Phase + type: string + - jsonPath: .metadata.creationTimestamp + name: Age + type: date + name: v1alpha1 + schema: + openAPIV3Schema: + description: |- + SessionManager is the singleton resource that drives installation of + the session-manager component (with training-portal, + assets-server, image-cache, and supporting services). + properties: + apiVersion: + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + type: string + kind: + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + metadata: + type: object + spec: + description: |- + SessionManagerSpec defines the desired state of SessionManager. + + Requires SecretsManager.Ready and EducatesClusterConfig.Ready; both + dependencies are singletons so no explicit refs are carried. + + Image registry prefix and pull secrets are inherited from + EducatesClusterConfig.status.imageRegistry; only per-image overrides + land in spec.images.overrides. + properties: + allowedEmbeddingHosts: + description: |- + allowedEmbeddingHosts lists hosts allowed to embed Educates + workshop frames (CSP frame-ancestors). + items: + type: string + type: array + defaultAccessCredentials: + description: |- + DefaultAccessCredentials configures the default + username/password used for workshop access when a TrainingPortal + doesn't override them. + properties: + passwordSecretRef: + description: passwordSecretRef references a Secret holding the + password value. + properties: + name: + description: name of the referent. + type: string + required: + - name + type: object + username: + type: string + type: object + defaultTheme: + description: |- + defaultTheme names the entry from themes used as the install-wide + default. Must match a Theme.name. + type: string + imagePrePuller: + description: |- + ImagePrePuller configures the optional DaemonSet that pre-pulls workshop + images onto every node ahead of time, so session startup isn't blocked on + image pulls. + properties: + enabled: + default: false + type: boolean + type: object + images: + description: |- + Images groups image-related overrides. Registry prefix and pull + secrets are inherited from + EducatesClusterConfig.status.imageRegistry; only per-image overrides + belong here. + properties: + overrides: + items: + description: |- + ImageOverride entries replace one chart-default image by short name. + Mirrors the v3 imageVersions shape: any image the chart's default + inventory exposes by name can be overridden here (e.g., + "training-portal", "base-environment", "jdk17-environment"). Three + names are special-cased by the reconciler because they live outside + that inventory: "session-manager" (the chart-pod image), + "pause-container" (the pre-puller pause image) and + "node-ca-injector" (its own subchart) — they route to the dedicated + chart values that control those images. + properties: + image: + description: |- + image is the full reference including tag. Digest-pinned + references are not supported for the special-cased names + ("session-manager", "pause-container", "node-ca-injector"), + whose chart values are repository+tag shaped. + type: string + name: + description: |- + name is the image's short name, e.g. "session-manager", + "training-portal", "jdk17-environment". + type: string + required: + - image + - name + type: object + type: array + type: object + ingressOverrides: + description: |- + IngressOverrides allows SessionManager to override the cluster-wide + ingress secrets for the bare-domain hostnames it serves directly + (TrainingPortal CRs prefix the domain for individual portals). + properties: + caCertificateSecretRef: + description: |- + LocalObjectReference is a name-only reference to an object in the + operator namespace (or, for cluster-scoped kinds, to the cluster- + scoped object). Mirrors the shape used in the config API group; + duplicated here to avoid cross-group Go coupling. + properties: + name: + description: name of the referent. + type: string + required: + - name + type: object + protocol: + description: |- + protocol asserts the scheme of the public-facing URLs the + session manager and workshops generate. Set to https when TLS + is terminated outside the cluster (external load balancer or + proxy forwarding plain HTTP inward) so links are generated + correctly despite no in-cluster certificate being presented. + Empty derives from the TLS configuration: https when a + wildcard certificate is configured, http otherwise. + enum: + - http + - https + type: string + tlsSecretRef: + description: |- + LocalObjectReference is a name-only reference to an object in the + operator namespace (or, for cluster-scoped kinds, to the cluster- + scoped object). Mirrors the shape used in the config API group; + duplicated here to avoid cross-group Go coupling. + properties: + name: + description: name of the referent. + type: string + required: + - name + type: object + type: object + logLevel: + default: info + description: logLevel defaults to info. + enum: + - debug + - info + - warn + - error + type: string + network: + description: |- + SessionNetwork configures network characteristics applied to workshop + sessions. + properties: + blockedCidrs: + description: |- + blockedCidrs lists CIDR ranges workshop sessions are denied + network access to (e.g., cloud metadata endpoints). + items: + type: string + type: array + packetSize: + description: |- + packetSize sets the MTU for workshop session networking. Useful + on overlay networks where the default MTU is too large. + format: int32 + minimum: 576 + type: integer + type: object + nodeCATrust: + description: nodeCATrust controls the optional node-ca-injector install. + properties: + mode: + default: Auto + description: |- + mode defaults to Auto. Auto installs the subchart only when + the cluster config publishes a CA Secret reference; with no CA + configured, Auto skips the install silently. Enabled forces + the install (refuses if no CA is configured). Disabled keeps + it uninstalled. + enum: + - Auto + - Enabled + - Disabled + type: string + type: object + registryMirrors: + description: |- + registryMirrors configures per-registry mirrors for workshop + container pulls. + items: + description: RegistryMirror declares a registry mirror used by workshop + containers. + properties: + mirror: + description: |- + mirror is the upstream registry being mirrored + (e.g., "docker.io"). + type: string + url: + description: url is the mirror endpoint. + type: string + required: + - mirror + - url + type: object + type: array + remoteAccess: + description: remoteAccess controls the optional remote-access install. + properties: + mode: + default: Auto + description: |- + mode defaults to Auto. Auto installs the subchart only when a + `LookupService` CR exists in the cluster (the signal that + cross-cluster federation is being used). Enabled forces the + install regardless of LookupService presence. Disabled keeps + it uninstalled. + enum: + - Auto + - Enabled + - Disabled + type: string + type: object + sessionCookieDomain: + description: |- + sessionCookieDomain sets the cookie domain used by workshop + sessions for cross-subdomain authentication. + type: string + storage: + description: |- + SessionStorage configures persistent storage characteristics for + workshop sessions. + properties: + storageClass: + type: string + storageGroup: + description: storageGroup sets the supplemental GID for mounted + volumes. + format: int64 + type: integer + storageUser: + description: storageUser sets the UID for mounted volumes. + format: int64 + type: integer + type: object + themes: + description: themes is a list of named themes available to TrainingPortals. + items: + description: Theme is one named entry in the spec.themes list. + properties: + name: + type: string + source: + description: |- + ThemeSource sources theme content. Exactly one of the per-type fields + (secretRef, configMapRef) should be populated for the selected type. + Secret is the only source the reconciler supports in v1alpha1; + ConfigMap and URL are reserved and rejected as "not yet supported". + properties: + configMapRef: + description: configMapRef applies when type is ConfigMap. + properties: + name: + type: string + namespace: + type: string + required: + - name + - namespace + type: object + secretRef: + description: |- + secretRef applies when type is Secret. It names a Secret holding + the theme assets; when its namespace differs from the release + namespace the runtime chart auto-creates a SecretCopier for it. + properties: + name: + type: string + namespace: + type: string + required: + - name + - namespace + type: object + type: + description: |- + ThemeSourceType selects how a theme's content is sourced. + Additional types may be added by the session-manager owner. + enum: + - ConfigMap + - Secret + - URL + type: string + required: + - type + type: object + required: + - name + - source + type: object + type: array + tracking: + description: Tracking groups analytics provider configuration. + properties: + amplitude: + description: TrackingProvider holds a single analytics provider's + tracking ID. + properties: + trackingId: + type: string + required: + - trackingId + type: object + clarity: + description: TrackingProvider holds a single analytics provider's + tracking ID. + properties: + trackingId: + type: string + required: + - trackingId + type: object + googleAnalytics: + description: TrackingProvider holds a single analytics provider's + tracking ID. + properties: + trackingId: + type: string + required: + - trackingId + type: object + webhook: + description: |- + TrackingWebhook configures an HTTP webhook receiver for analytics + events. + properties: + url: + type: string + required: + - url + type: object + type: object + workshopPolicyOverride: + description: |- + WorkshopPolicyOverride locally overrides + EducatesClusterConfig.status.policyEnforcement.workshopPolicyEngine + for this SessionManager. + properties: + engine: + description: |- + WorkshopPolicyEngine names the engine enforcing per-workshop isolation + rules. Mirrors the same-named enum in the config API group; + duplicated to avoid cross-group Go coupling. + enum: + - Kyverno + - None + type: string + required: + - engine + type: object + type: object + status: + description: |- + SessionManagerStatus defines the observed state of SessionManager. + Phase 4 publishes the full CRD draft r3 §4 contract: phase + + conditions + installedVersion + deploymentRef. + properties: + conditions: + description: |- + conditions report the resource's state. Phase 4 publishes: + - Ready (aggregate) + - ClusterConfigAvailable (EducatesClusterConfig.Ready gate) + - SecretsManagerAvailable (SecretsManager.Ready gate) + - Deployed (session-manager helm release + Deployment Available) + - NodeCATrustDeployed (optional extra; reflects mode evaluation outcome) + - RemoteAccessDeployed (optional extra; reflects mode evaluation outcome) + items: + description: Condition contains details for one aspect of the current + state of this API Resource. + properties: + lastTransitionTime: + description: |- + lastTransitionTime is the last time the condition transitioned from one status to another. + This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable. + format: date-time + type: string + message: + description: |- + message is a human readable message indicating details about the transition. + This may be an empty string. + maxLength: 32768 + type: string + observedGeneration: + description: |- + observedGeneration represents the .metadata.generation that the condition was set based upon. + For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date + with respect to the current state of the instance. + format: int64 + minimum: 0 + type: integer + reason: + description: |- + reason contains a programmatic identifier indicating the reason for the condition's last transition. + Producers of specific condition types may define expected values and meanings for this field, + and whether the values are considered a guaranteed API. + The value should be a CamelCase string. + This field may not be empty. + maxLength: 1024 + minLength: 1 + pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ + type: string + status: + description: status of the condition, one of True, False, Unknown. + enum: + - "True" + - "False" + - Unknown + type: string + type: + description: type of condition in CamelCase or in foo.example.com/CamelCase. + maxLength: 316 + pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ + type: string + required: + - lastTransitionTime + - message + - reason + - status + - type + type: object + type: array + x-kubernetes-list-map-keys: + - type + x-kubernetes-list-type: map + deploymentRef: + description: |- + deploymentRef names the upstream session-manager Deployment the + operator is gating Ready on. + properties: + name: + type: string + namespace: + type: string + required: + - name + - namespace + type: object + installedVersion: + description: |- + installedVersion records the session-manager chart version most + recently applied. + type: string + observedGeneration: + format: int64 + type: integer + phase: + description: |- + ComponentPhase summarises the operator's current activity on a + platform component. Phases are advisory; conditions carry the + authoritative state. + enum: + - Pending + - Installing + - Ready + - Degraded + - Uninstalling + type: string + type: object + required: + - spec + type: object + x-kubernetes-validations: + - message: SessionManager must be named 'cluster' (singleton per cluster) + rule: self.metadata.name == 'cluster' + served: true + storage: true + subresources: + status: {} diff --git a/client-programs/pkg/deployer/chart/files/templates/NOTES.txt b/client-programs/pkg/deployer/chart/files/templates/NOTES.txt new file mode 100644 index 000000000..3173c1350 --- /dev/null +++ b/client-programs/pkg/deployer/chart/files/templates/NOTES.txt @@ -0,0 +1,28 @@ +Educates v4 installer is now deployed in namespace {{ .Release.Namespace }}. + +The four CRDs are installed cluster-wide: + - educatesclusterconfigs.config.educates.dev (singleton, named "cluster") + - secretsmanagers.platform.educates.dev (singleton, named "cluster") + - lookupservices.platform.educates.dev (singleton, named "cluster") + - sessionmanagers.platform.educates.dev (singleton, named "cluster") + +Next, apply the platform custom resources for your scenario — the +operator installs everything else once EducatesClusterConfig is +applied. Worked examples live in installer/samples/ in the project +repository; documentation at https://docs.educates.dev. + + kubectl apply -f educates-cluster-config.yaml + kubectl wait --for=condition=Ready educatesclusterconfig/cluster --timeout=600s + kubectl apply -f educates-secrets-manager.yaml + kubectl apply -f educates-lookup-service.yaml # optional + kubectl apply -f educates-session-manager.yaml + +Useful commands: + + kubectl get pods -n {{ .Release.Namespace }} \ + -l app.kubernetes.io/name=educates-installer + kubectl logs -n {{ .Release.Namespace }} \ + -l app.kubernetes.io/name=educates-installer -f + + kubectl explain educatesclusterconfig.spec + kubectl get crd | grep educates.dev diff --git a/client-programs/pkg/deployer/chart/files/templates/_helpers.tpl b/client-programs/pkg/deployer/chart/files/templates/_helpers.tpl new file mode 100644 index 000000000..a68a83b05 --- /dev/null +++ b/client-programs/pkg/deployer/chart/files/templates/_helpers.tpl @@ -0,0 +1,86 @@ +{{/* +Common labels applied to all resources rendered by this chart. +*/}} +{{- define "educates-installer.labels" -}} +app.kubernetes.io/name: educates-installer +app.kubernetes.io/instance: {{ .Release.Name }} +app.kubernetes.io/component: operator +app.kubernetes.io/part-of: educates +app.kubernetes.io/managed-by: {{ .Release.Service }} +app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} +helm.sh/chart: {{ printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} +{{- end -}} + +{{/* +Selector labels — stable across upgrades; must not include the chart +version. +*/}} +{{- define "educates-installer.selectorLabels" -}} +app.kubernetes.io/name: educates-installer +app.kubernetes.io/instance: {{ .Release.Name }} +{{- end -}} + +{{/* +Resolve the effective image registry: development.imageRegistry (user +override) → global.development.imageRegistry (uniformity with the +runtime subcharts; this chart is standalone so it's normally unset) → +Chart.yaml `educates.dev/image-registry-*` annotations (publish-time +defaults). Returned as a YAML string — consume via `fromYaml`. +*/}} +{{- define "educates-installer.resolvedImageRegistry" -}} +{{- $local := default dict (default dict .Values.development).imageRegistry -}} +{{- $global := default dict (default dict (default dict .Values.global).development).imageRegistry -}} +{{- $merged := mergeOverwrite (deepCopy $local) $global -}} +{{- if not $merged.host -}} + {{- $_ := set $merged "host" (index .Chart.Annotations "educates.dev/image-registry-host" | default "") -}} +{{- end -}} +{{- if not $merged.namespace -}} + {{- $_ := set $merged "namespace" (index .Chart.Annotations "educates.dev/image-registry-namespace" | default "") -}} +{{- end -}} +{{- toYaml $merged -}} +{{- end -}} + +{{- define "educates-installer.imageRegistryPrefix" -}} +{{- $ir := include "educates-installer.resolvedImageRegistry" . | fromYaml -}} +{{- $host := default "" $ir.host -}} +{{- $ns := default "" $ir.namespace -}} +{{- if and $host $ns -}} +{{ $host }}/{{ $ns }} +{{- else if $host -}} +{{ $host }} +{{- else -}} +{{- fail "imageRegistry.host could not be resolved. Either set Chart.yaml annotation `educates.dev/image-registry-host` (publish-time default) or override locally via .development.imageRegistry / .global.development.imageRegistry." -}} +{{- end -}} +{{- end -}} + +{{- define "educates-installer.image.repository" -}} +{{- if .Values.image.repository -}} +{{ .Values.image.repository }} +{{- else -}} +{{ include "educates-installer.imageRegistryPrefix" . }}/educates-operator +{{- end -}} +{{- end -}} + +{{/* +Resolve the container image tag, defaulting to .Chart.AppVersion when unset. +*/}} +{{- define "educates-installer.image.tag" -}} +{{- default .Chart.AppVersion .Values.image.tag -}} +{{- end -}} + +{{/* +Auto-derive imagePullPolicy: Always for floating tags, IfNotPresent +otherwise. An explicit pullPolicy in values wins. +*/}} +{{- define "educates-installer.image.pullPolicy" -}} +{{- if .Values.image.pullPolicy -}} +{{ .Values.image.pullPolicy }} +{{- else -}} +{{- $tag := include "educates-installer.image.tag" . -}} +{{- if or (eq $tag "latest") (eq $tag "main") (eq $tag "master") (eq $tag "develop") -}} +Always +{{- else -}} +IfNotPresent +{{- end -}} +{{- end -}} +{{- end -}} diff --git a/client-programs/pkg/deployer/chart/files/templates/deployment.yaml b/client-programs/pkg/deployer/chart/files/templates/deployment.yaml new file mode 100644 index 000000000..22527e657 --- /dev/null +++ b/client-programs/pkg/deployer/chart/files/templates/deployment.yaml @@ -0,0 +1,78 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: educates-installer + namespace: {{ .Release.Namespace }} + labels: + {{- include "educates-installer.labels" . | nindent 4 }} +spec: + replicas: 1 + strategy: + type: Recreate + selector: + matchLabels: + {{- include "educates-installer.selectorLabels" . | nindent 6 }} + template: + metadata: + labels: + {{- include "educates-installer.labels" . | nindent 8 }} + {{- include "educates-installer.selectorLabels" . | nindent 8 }} + spec: + serviceAccountName: educates-installer + {{- with .Values.imagePullSecrets }} + imagePullSecrets: + {{- toYaml . | nindent 8 }} + {{- end }} + securityContext: + runAsNonRoot: true + containers: + - name: manager + image: "{{ include "educates-installer.image.repository" . }}:{{ include "educates-installer.image.tag" . }}" + imagePullPolicy: {{ include "educates-installer.image.pullPolicy" . }} + args: + - --health-probe-bind-address=:8081 + - --metrics-bind-address=0 + {{- if .Values.leaderElection.enabled }} + - --leader-elect + {{- end }} + env: + - name: OPERATOR_NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + securityContext: + allowPrivilegeEscalation: false + capabilities: + drop: ["ALL"] + ports: + - name: probes + containerPort: 8081 + protocol: TCP + livenessProbe: + httpGet: + path: /healthz + port: probes + initialDelaySeconds: 15 + periodSeconds: 20 + readinessProbe: + httpGet: + path: /readyz + port: probes + initialDelaySeconds: 5 + periodSeconds: 10 + {{- with .Values.resources }} + resources: + {{- toYaml . | nindent 12 }} + {{- end }} + {{- with .Values.nodeSelector }} + nodeSelector: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.tolerations }} + tolerations: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.affinity }} + affinity: + {{- toYaml . | nindent 8 }} + {{- end }} diff --git a/client-programs/pkg/deployer/chart/files/templates/rbac/cluster-admin-binding.yaml b/client-programs/pkg/deployer/chart/files/templates/rbac/cluster-admin-binding.yaml new file mode 100644 index 000000000..f4646b5ae --- /dev/null +++ b/client-programs/pkg/deployer/chart/files/templates/rbac/cluster-admin-binding.yaml @@ -0,0 +1,36 @@ +{{/* + Phase 2/3 development shortcut: bind the operator ServiceAccount to + the built-in cluster-admin ClusterRole. + + Why this is needed: the operator drives Helm SDK installs of upstream + charts (cert-manager today; Contour, Kyverno, external-dns in Phase + 3). Those installs apply every resource the chart contains — + ServiceAccounts, ClusterRoles, RoleBindings, Services, ConfigMaps, + ValidatingWebhookConfigurations, Deployments, CRDs — under the + operator's own ServiceAccount. Kubernetes RBAC requires the actor to + hold at least the permissions of the resources it creates, so any + scoping narrower than cluster-admin breaks on the first new chart + resource type we don't pre-enumerate. + + Why this is acceptable today: the operator is the only consumer of + cluster services in v4 (see decisions.md → no umbrella chart), and + Phase 6 will replace this binding with a fine-grained ClusterRole + derived from the manifests every vendored chart actually produces. + Until then, this is the "cluster-admin shortcut" referenced from + internal/controller/config/educatesclusterconfig_controller.go's + RBAC comment block. +*/}} +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: educates-installer-cluster-admin + labels: + {{- include "educates-installer.labels" . | nindent 4 }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: cluster-admin +subjects: + - kind: ServiceAccount + name: educates-installer + namespace: {{ .Release.Namespace }} diff --git a/client-programs/pkg/deployer/chart/files/templates/rbac/role-binding.yaml b/client-programs/pkg/deployer/chart/files/templates/rbac/role-binding.yaml new file mode 100644 index 000000000..a64469ff9 --- /dev/null +++ b/client-programs/pkg/deployer/chart/files/templates/rbac/role-binding.yaml @@ -0,0 +1,14 @@ +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: educates-installer-manager + labels: + {{- include "educates-installer.labels" . | nindent 4 }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: educates-installer-manager +subjects: + - kind: ServiceAccount + name: educates-installer + namespace: {{ .Release.Namespace }} diff --git a/client-programs/pkg/deployer/chart/files/templates/rbac/role.yaml b/client-programs/pkg/deployer/chart/files/templates/rbac/role.yaml new file mode 100644 index 000000000..b02fb4206 --- /dev/null +++ b/client-programs/pkg/deployer/chart/files/templates/rbac/role.yaml @@ -0,0 +1,116 @@ +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: educates-installer-manager +rules: +- apiGroups: + - "" + resources: + - namespaces + verbs: + - create + - delete + - get + - list + - patch + - watch +- apiGroups: + - "" + resources: + - secrets + verbs: + - create + - delete + - get + - list + - patch + - update + - watch +- apiGroups: + - apps + resources: + - deployments + verbs: + - get + - list + - watch +- apiGroups: + - cert-manager.io + resources: + - certificates + - clusterissuers + verbs: + - create + - delete + - get + - list + - patch + - update + - watch +- apiGroups: + - config.educates.dev + resources: + - educatesclusterconfigs + verbs: + - create + - delete + - get + - list + - patch + - update + - watch +- apiGroups: + - config.educates.dev + resources: + - educatesclusterconfigs/finalizers + verbs: + - update +- apiGroups: + - config.educates.dev + resources: + - educatesclusterconfigs/status + verbs: + - get + - patch + - update +- apiGroups: + - networking.k8s.io + resources: + - ingressclasses + verbs: + - get + - list + - watch +- apiGroups: + - platform.educates.dev + resources: + - lookupservices + - secretsmanagers + - sessionmanagers + verbs: + - create + - delete + - get + - list + - patch + - update + - watch +- apiGroups: + - platform.educates.dev + resources: + - lookupservices/finalizers + - secretsmanagers/finalizers + - sessionmanagers/finalizers + verbs: + - update +- apiGroups: + - platform.educates.dev + resources: + - lookupservices/status + - secretsmanagers/status + - sessionmanagers/status + verbs: + - get + - patch + - update diff --git a/client-programs/pkg/deployer/chart/files/templates/serviceaccount.yaml b/client-programs/pkg/deployer/chart/files/templates/serviceaccount.yaml new file mode 100644 index 000000000..19a4fcec4 --- /dev/null +++ b/client-programs/pkg/deployer/chart/files/templates/serviceaccount.yaml @@ -0,0 +1,7 @@ +apiVersion: v1 +kind: ServiceAccount +metadata: + name: educates-installer + namespace: {{ .Release.Namespace }} + labels: + {{- include "educates-installer.labels" . | nindent 4 }} diff --git a/client-programs/pkg/deployer/chart/files/values.yaml b/client-programs/pkg/deployer/chart/files/values.yaml new file mode 100644 index 000000000..21043f80e --- /dev/null +++ b/client-programs/pkg/deployer/chart/files/values.yaml @@ -0,0 +1,51 @@ +# Operator container image. All fields are overrides; in normal use +# leave them empty and the chart resolves the image as +# `{host}/{namespace}/educates-operator:{appVersion}` from the +# Chart.yaml `educates.dev/image-registry-*` annotations (publish-time +# defaults, rewritten per fork by the release workflow). +# +# - repository: full image repository (registry + path, no tag). +# Wins over both the annotations and development.imageRegistry. +# - tag: defaults to Chart.appVersion. +# - pullPolicy: empty auto-derives — Always for floating tags +# (latest/main/master/develop), IfNotPresent otherwise. +# +# Local development workflow: +# cd installer/operator +# make docker-build IMG=ghcr.io/educates/educates-operator:dev +# kind load docker-image ghcr.io/educates/educates-operator:dev +# helm install educates-installer installer/charts/educates-installer \ +# --namespace educates-installer --create-namespace \ +# --set image.repository=ghcr.io/educates/educates-operator \ +# --set image.tag=dev +image: + repository: "" + tag: "" + pullPolicy: "" + +# Development override for the registry prefix only (image name and tag +# still resolve normally): {host: ghcr.io, namespace: myfork}. Same +# knob as the runtime subcharts' development.imageRegistry. Leave empty +# in normal use. +development: + imageRegistry: {} + +# Pull secrets for the operator pod itself. Distinct from +# EducatesClusterConfig.spec.imageRegistry.pullSecrets, which apply to +# bundled charts the operator installs. +imagePullSecrets: [] + +# Operator pod resources. Empty means no requests or limits set; tune +# per cluster. +resources: {} + +# Pod placement. +nodeSelector: {} +tolerations: [] +affinity: {} + +# When false, leader election is disabled — appropriate for the Phase 0 +# single-replica deployment. When the operator scales beyond one replica +# (not in v4 plan), set to true. +leaderElection: + enabled: false diff --git a/client-programs/pkg/deployer/crds/crds.go b/client-programs/pkg/deployer/crds/crds.go new file mode 100644 index 000000000..c03d5df2e --- /dev/null +++ b/client-programs/pkg/deployer/crds/crds.go @@ -0,0 +1,162 @@ +// Package crds applies the four platform CRDs from the embedded +// operator chart to the cluster before helm-install. +// +// Why this exists: helm intentionally only installs CRDs from a +// chart's crds/ directory on first install — never on upgrade. After +// a CRD shape change, users would have to run +// `kubectl apply -f installer/charts/educates-installer/crds/` by +// hand for the new schema to land. Owning CRD lifecycle from deploy +// removes that step. +// +// The deploy flow passes SkipCRDs=true to helm so the two paths +// don't fight over CRD ownership. +package crds + +import ( + "bufio" + "bytes" + "context" + "fmt" + "io" + "time" + + apierrors "k8s.io/apimachinery/pkg/api/errors" + "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" + "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/apimachinery/pkg/util/yaml" + + helmchart "helm.sh/helm/v4/pkg/chart/v2" + + "github.com/educates/educates-training-platform/client-programs/pkg/deployer/apply" +) + +// crdGVK is apiextensions.k8s.io/v1 CustomResourceDefinition — used to +// poll Established=True on freshly-applied CRDs. +var crdGVK = schema.GroupVersionKind{ + Group: "apiextensions.k8s.io", + Version: "v1", + Kind: "CustomResourceDefinition", +} + +// establishedPollInterval and establishedTimeout bound the post-apply +// wait. CRD establishment is normally sub-second on a healthy apiserver; +// the timeout is just a safety net against a wedged apiserver. +const ( + establishedPollInterval = 250 * time.Millisecond + establishedTimeout = 60 * time.Second +) + +// Apply pushes every CRD found in chrt.CRDObjects() via SSA. Returns +// the list of GroupKind+Name strings applied so the deploy summary can +// log them. Idempotent: re-runs converge on the latest schema. +func Apply(ctx context.Context, applier *apply.Client, chrt *helmchart.Chart) ([]string, error) { + var applied []string + for _, crdEntry := range chrt.CRDObjects() { + if crdEntry.File == nil || len(crdEntry.File.Data) == 0 { + continue + } + docs, err := splitYAMLDocs(crdEntry.File.Data) + if err != nil { + return nil, fmt.Errorf("split CRD file %s: %w", crdEntry.Filename, err) + } + for _, doc := range docs { + u := &unstructured.Unstructured{} + if err := yaml.Unmarshal(doc, &u.Object); err != nil { + return nil, fmt.Errorf("parse CRD doc in %s: %w", crdEntry.Filename, err) + } + if u.GetKind() != "CustomResourceDefinition" { + // Defensive: helm's CRDObjects() should only return + // objects from crds/, but a malformed chart could + // slip something through. + continue + } + if _, err := applier.Apply(ctx, u); err != nil { + return nil, fmt.Errorf("apply CRD %s: %w", u.GetName(), err) + } + applied = append(applied, u.GetName()) + } + } + if err := waitEstablished(ctx, applier, applied); err != nil { + return applied, err + } + // The mapper's discovery cache was populated before these CRDs + // existed. Invalidate it so the next CR apply re-fetches /apis and + // resolves the new kinds. + applier.InvalidateDiscovery() + return applied, nil +} + +// waitEstablished polls each applied CRD until its Established=True +// condition flips. The apply call returns as soon as the CRD object +// lands, but the apiserver needs an extra moment to wire up the +// discovery endpoint for the new kind. Without this gate, the very next +// CR apply races discovery and surfaces as +// "no matches for kind ... in version ...". +func waitEstablished(ctx context.Context, applier *apply.Client, names []string) error { + deadline := time.Now().Add(establishedTimeout) + for _, name := range names { + for { + obj, err := applier.Get(ctx, crdGVK, "", name) + if err != nil && !apierrors.IsNotFound(err) { + return fmt.Errorf("get CRD %s: %w", name, err) + } + if err == nil && isEstablished(obj) { + break + } + if time.Now().After(deadline) { + return fmt.Errorf("timeout waiting for CRD %s to become Established", name) + } + select { + case <-ctx.Done(): + return ctx.Err() + case <-time.After(establishedPollInterval): + } + } + } + return nil +} + +// isEstablished returns true when the CRD's Established condition is True. +// NamesAccepted is implicit — Established only flips after NamesAccepted. +func isEstablished(obj *unstructured.Unstructured) bool { + if obj == nil { + return false + } + conds, found, err := unstructured.NestedSlice(obj.Object, "status", "conditions") + if err != nil || !found { + return false + } + for _, c := range conds { + m, ok := c.(map[string]interface{}) + if !ok { + continue + } + if m["type"] == "Established" && m["status"] == "True" { + return true + } + } + return false +} + +// splitYAMLDocs handles multi-document YAML files (--- separated). +// helm doesn't promise that each chart file holds exactly one CRD — +// the upstream convention is one-per-file but the format allows +// stacking. +func splitYAMLDocs(data []byte) ([][]byte, error) { + dec := yaml.NewYAMLReader(bufio.NewReader(bytes.NewReader(data))) + var out [][]byte + for { + doc, err := dec.Read() + if err == io.EOF { + break + } + if err != nil { + return nil, err + } + if len(bytes.TrimSpace(doc)) == 0 { + continue + } + out = append(out, doc) + } + return out, nil +} diff --git a/client-programs/pkg/deployer/crds/crds_test.go b/client-programs/pkg/deployer/crds/crds_test.go new file mode 100644 index 000000000..183f838f2 --- /dev/null +++ b/client-programs/pkg/deployer/crds/crds_test.go @@ -0,0 +1,85 @@ +package crds + +import ( + "strings" + "testing" + + "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" + "k8s.io/apimachinery/pkg/util/yaml" + + "github.com/educates/educates-training-platform/client-programs/pkg/deployer/chart" +) + +func TestCRDObjects_AllFourParseAsCRDs(t *testing.T) { + chrt, err := chart.Load() + if err != nil { + t.Fatalf("chart.Load: %v", err) + } + objs := chrt.CRDObjects() + if len(objs) != 4 { + t.Fatalf("chart CRDObjects len = %d, want 4 (ECC + SecretsManager + LookupService + SessionManager)", len(objs)) + } + + wantKinds := map[string]bool{ + "EducatesClusterConfig": false, + "SecretsManager": false, + "LookupService": false, + "SessionManager": false, + } + for _, c := range objs { + docs, err := splitYAMLDocs(c.File.Data) + if err != nil { + t.Fatalf("split %s: %v", c.Filename, err) + } + if len(docs) != 1 { + t.Errorf("%s: %d docs, want 1", c.Filename, len(docs)) + } + u := &unstructured.Unstructured{} + if err := yaml.Unmarshal(docs[0], &u.Object); err != nil { + t.Fatalf("parse %s: %v", c.Filename, err) + } + if got, want := u.GetKind(), "CustomResourceDefinition"; got != want { + t.Errorf("%s: kind = %q, want %q", c.Filename, got, want) + } + // CRD name format is . e.g. "educatesclusterconfigs.config.educates.dev" + // We assert spec.names.kind is one of the four we expect. + kind, found, err := unstructured.NestedString(u.Object, "spec", "names", "kind") + if err != nil || !found { + t.Errorf("%s: spec.names.kind not found: %v", c.Filename, err) + continue + } + if _, ok := wantKinds[kind]; !ok { + t.Errorf("%s: unexpected kind %q", c.Filename, kind) + continue + } + wantKinds[kind] = true + } + for kind, found := range wantKinds { + if !found { + t.Errorf("CRD for kind %q not found in embedded chart", kind) + } + } +} + +func TestSplitYAMLDocs_MultiDocFile(t *testing.T) { + doc := []byte(`apiVersion: v1 +kind: A +--- +apiVersion: v1 +kind: B +`) + parts, err := splitYAMLDocs(doc) + if err != nil { + t.Fatal(err) + } + if len(parts) != 2 { + t.Fatalf("len = %d, want 2", len(parts)) + } + if !strings.Contains(string(parts[0]), "kind: A") { + t.Errorf("first doc missing 'kind: A'") + } + if !strings.Contains(string(parts[1]), "kind: B") { + t.Errorf("second doc missing 'kind: B'") + } +} + diff --git a/client-programs/pkg/deployer/delete.go b/client-programs/pkg/deployer/delete.go new file mode 100644 index 000000000..77e3c6c36 --- /dev/null +++ b/client-programs/pkg/deployer/delete.go @@ -0,0 +1,242 @@ +package deployer + +import ( + "context" + "errors" + "fmt" + "io" + "time" + + apierrors "k8s.io/apimachinery/pkg/api/errors" + "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/cli-runtime/pkg/genericclioptions" + + "github.com/educates/educates-training-platform/client-programs/pkg/deployer/apply" + "github.com/educates/educates-training-platform/client-programs/pkg/deployer/helm" + "github.com/educates/educates-training-platform/client-programs/pkg/deployer/progress" + "github.com/educates/educates-training-platform/client-programs/pkg/deployer/wait" +) + +// DeleteOptions configures a delete run. Mirrors Options but the inputs +// differ: we don't need translator output here since the resources are +// always the same four CRs at metadata.name=cluster + the helm release. +type DeleteOptions struct { + Getter genericclioptions.RESTClientGetter + Out io.Writer + HelmLog io.Writer + Timeout time.Duration + Progress progress.Reporter + + // Purge, when true, extends the delete pipeline AFTER helm + // uninstall to remove the four CRDs, the operator namespace, and + // the 'educates-secrets' namespace. Local /config.yaml + // + cached CA Secrets are intentionally preserved — they're user + // authoring inputs and survive cluster reinstalls. + Purge bool +} + +// PurgeTargets is the inventory --purge will delete in addition to the +// standard delete pipeline. Exported so the cmd-layer confirmation +// prompt can render it for the user before they accept. +type PurgeTargets struct { + CRDs []string + Namespaces []string +} + +// PurgePlan returns the list of cluster resources Purge would remove +// after helm uninstall. Stable order so the confirmation prompt is +// reproducible. +func PurgePlan() PurgeTargets { + return PurgeTargets{ + CRDs: []string{ + "educatesclusterconfigs.config.educates.dev", + "secretsmanagers.platform.educates.dev", + "lookupservices.platform.educates.dev", + "sessionmanagers.platform.educates.dev", + }, + Namespaces: []string{ + OperatorNamespace, // educates-installer + "educates-secrets", + }, + } +} + +// Delete executes the uninstall pipeline: +// +// 1. Delete SessionManager → wait gone. +// 2. Delete LookupService → wait gone. +// 3. Delete SecretsManager → wait gone. +// 4. Delete EducatesClusterConfig → wait gone (its finalizer drains +// kyverno → external-dns → contour → cert-manager → CustomCA +// copy in reverse install order). +// 5. helm uninstall the operator chart. +// +// Idempotent: a CR that's already gone is a no-op step. Useful for +// re-running after a half-finished delete or for cleaning up state the +// last deploy never created. +// +// Deliberately NOT deleted (user state across reinstalls): +// - CRDs (helm never owns them; would cascade-delete any CR in the +// cluster, including ones from other Educates installs). +// - The operator namespace itself. +// - educates-secrets namespace + the synced CA Secret (so the next +// deploy reuses the same CA the user already trusts in their +// browser). +func Delete(ctx context.Context, opts DeleteOptions) error { + if opts.Out == nil { + opts.Out = io.Discard + } + if opts.HelmLog == nil { + opts.HelmLog = io.Discard + } + if opts.Timeout == 0 { + opts.Timeout = DefaultTimeout + } + if opts.Progress == nil { + opts.Progress = progress.New(io.Discard, 0, false) + } + + applier, err := apply.New(opts.Getter) + if err != nil { + return err + } + waiter, err := wait.New(opts.Getter) + if err != nil { + return err + } + + for _, st := range deleteOrder() { + if err := deleteCRStep(ctx, opts, applier, waiter, st.gvk, st.name, st.label); err != nil { + return err + } + } + + // helm uninstall the operator chart. + step := opts.Progress.Start(fmt.Sprintf("helm uninstall %s", OperatorReleaseName)) + helmClient, err := helm.New(opts.Getter, OperatorNamespace, opts.HelmLog) + if err != nil { + step.Fail(err) + return err + } + if err := helmClient.Uninstall(OperatorReleaseName); err != nil { + // Uninstall already swallows "release not found"; surface other + // errors as-is. + step.Fail(err) + return err + } + step.Done("uninstalled") + + if opts.Purge { + if err := purge(ctx, opts, applier); err != nil { + return err + } + } + opts.Progress.Note("delete complete") + return nil +} + +// purge removes the four platform CRDs and the operator + secrets +// namespaces. Idempotent: NotFound at any step closes that step with +// "already gone" rather than erroring. +// +// Order matters: CRDs first (their deletion cascade-removes any +// lingering CR instances cluster-wide; we've already deleted ours +// from the operator-owned namespace, but other teams may have ECC +// resources we don't want to leave dangling against deleted CRDs). +// Namespaces last (they cascade Pod/Secret/ConfigMap cleanup; finalizer +// drain on the operator namespace is what waits the longest). +func purge(ctx context.Context, opts DeleteOptions, applier *apply.Client) error { + plan := PurgePlan() + crdGVK := schema.GroupVersionKind{ + Group: "apiextensions.k8s.io", + Version: "v1", + Kind: "CustomResourceDefinition", + } + for _, name := range plan.CRDs { + step := opts.Progress.Start(fmt.Sprintf("purge CRD %s", name)) + if err := applier.Delete(ctx, crdGVK, "", name); err != nil { + var statusErr *apierrors.StatusError + if errors.As(err, &statusErr) && apierrors.IsNotFound(err) { + step.Done("already gone") + continue + } + step.Fail(err) + return err + } + step.Done("removed") + } + nsGVK := schema.GroupVersionKind{Version: "v1", Kind: "Namespace"} + for _, name := range plan.Namespaces { + step := opts.Progress.Start(fmt.Sprintf("purge namespace %s", name)) + if err := applier.Delete(ctx, nsGVK, "", name); err != nil { + var statusErr *apierrors.StatusError + if errors.As(err, &statusErr) && apierrors.IsNotFound(err) { + step.Done("already gone") + continue + } + step.Fail(err) + return err + } + step.Done("deletion initiated") + } + return nil +} + +// deleteCRStep removes one CR by GVK + name and waits for it to be +// 404, reporting both halves through a single progress step. NotFound +// at the delete call → step closes with "already gone" + return nil +// (idempotent re-run). +func deleteCRStep(ctx context.Context, opts DeleteOptions, applier *apply.Client, waiter *wait.Client, gvk schema.GroupVersionKind, name, label string) error { + step := opts.Progress.Start(fmt.Sprintf("delete %s/%s", label, name)) + if err := applier.Delete(ctx, gvk, "", name); err != nil { + var statusErr *apierrors.StatusError + if errors.As(err, &statusErr) && apierrors.IsNotFound(err) { + step.Done("already gone") + return nil + } + step.Fail(err) + return err + } + step.Update("waiting for finalizer drain") + if err := waiter.WaitGone(ctx, gvk, "", name, opts.Timeout); err != nil { + step.Fail(err) + return err + } + step.Done("gone") + return nil +} + +type deleteStep struct { + gvk schema.GroupVersionKind + name string + label string +} + +// deleteOrder is the inverse of the deploy install order. SessionManager +// first so its remote-access subchart goes away while LookupService is +// still present; LookupService next (its subchart's cleanup runs); then +// SecretsManager; then ECC last (its finalizer drains cluster services). +func deleteOrder() []deleteStep { + return []deleteStep{ + { + gvk: schema.GroupVersionKind{Group: "platform.educates.dev", Version: "v1alpha1", Kind: "SessionManager"}, + name: "cluster", + label: "SessionManager", + }, + { + gvk: schema.GroupVersionKind{Group: "platform.educates.dev", Version: "v1alpha1", Kind: "LookupService"}, + name: "cluster", + label: "LookupService", + }, + { + gvk: schema.GroupVersionKind{Group: "platform.educates.dev", Version: "v1alpha1", Kind: "SecretsManager"}, + name: "cluster", + label: "SecretsManager", + }, + { + gvk: schema.GroupVersionKind{Group: "config.educates.dev", Version: "v1alpha1", Kind: "EducatesClusterConfig"}, + name: "cluster", + label: "EducatesClusterConfig", + }, + } +} diff --git a/client-programs/pkg/deployer/deploy.go b/client-programs/pkg/deployer/deploy.go new file mode 100644 index 000000000..2e92a273d --- /dev/null +++ b/client-programs/pkg/deployer/deploy.go @@ -0,0 +1,291 @@ +// Package deployer is the v4 install path: load a CLI config, translate +// to operator chart values + four platform CRs, install the operator +// chart via Helm SDK, server-side-apply the CRs in dependency order, and +// wait for each to be Ready=True. +// +// Walking skeleton scope: the happy path works end-to-end on a kind +// cluster. Polish (richer progress reporting, dry-run, rollback) is for +// follow-up commits in step 5. +package deployer + +import ( + "context" + "encoding/json" + "fmt" + "io" + "time" + + "github.com/educates/educates-training-platform/client-programs/pkg/config/translator" + "github.com/educates/educates-training-platform/client-programs/pkg/deployer/apply" + "github.com/educates/educates-training-platform/client-programs/pkg/deployer/chart" + "github.com/educates/educates-training-platform/client-programs/pkg/deployer/crds" + "github.com/educates/educates-training-platform/client-programs/pkg/deployer/helm" + "github.com/educates/educates-training-platform/client-programs/pkg/deployer/prereq" + "github.com/educates/educates-training-platform/client-programs/pkg/deployer/progress" + "github.com/educates/educates-training-platform/client-programs/pkg/deployer/wait" + "github.com/educates/educates-training-platform/client-programs/pkg/secrets" + + "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" + "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/cli-runtime/pkg/genericclioptions" + "k8s.io/client-go/kubernetes" +) + +const ( + // OperatorNamespace is where the educates-installer helm release + // lives. Matches the chart's recommended deploy namespace and the + // samples in installer/samples/. + OperatorNamespace = "educates-installer" + + // OperatorReleaseName is the helm release name. + OperatorReleaseName = "educates-installer" + + // DefaultTimeout caps the wait on each CR's Ready=True condition. + DefaultTimeout = 5 * time.Minute +) + +// Options configures a deploy run. +type Options struct { + // Getter is the kubectl-style RESTClientGetter — typically a + // configured genericclioptions.ConfigFlags from cobra. + Getter genericclioptions.RESTClientGetter + + // Out is where progress lines are written. Pass cmd.OutOrStdout() + // from cobra; pass io.Discard from tests. + Out io.Writer + + // HelmLog receives helm SDK debug output. io.Discard by default. + HelmLog io.Writer + + // Timeout overrides DefaultTimeout per CR wait. + Timeout time.Duration + + // SkipPrereqCheck bypasses the educates-custom-ca Secret existence + // check. Set when the caller has already verified, or for advanced + // users who manage the Secret asynchronously. + SkipPrereqCheck bool + + // SkipCRDApply bypasses the operator CRD apply step. The default + // is to push CRDs from the embedded chart before helm-install so a + // CRD shape change reaches the cluster on re-deploy (helm itself + // only installs CRDs on first install, never on upgrade). Set true + // when the user manages CRDs out of band (GitOps, separate + // kubectl apply, etc.). + SkipCRDApply bool + + // SyncLocalSecrets, when true, copies /secrets/*.yaml into + // the cluster's 'educates-secrets' namespace before applying the + // platform CRs. Matches the v3 laptop flow: cached CA/TLS material + // is pushed at deploy time, ECC's caCertificateRef points there. + // Only meaningful for EducatesLocalConfig deploys. + SyncLocalSecrets bool + + // Progress is the structured progress reporter. When nil, plain + // io.Discard-backed reporter is used (no progress output, but the + // helpers still call into it so the call-site code is uniform). + // Cmd code typically passes progress.NewForStdout(...) to render + // to the user's terminal with TTY-aware overwriting. + Progress progress.Reporter +} + +// Deploy executes the install pipeline against the cluster reachable +// via opts.Getter: +// +// 1. Helm install/upgrade the operator chart in the operator namespace. +// 2. Apply EducatesClusterConfig → wait Ready. +// 3. Verify the educates-custom-ca prerequisite Secret (unless skipped). +// 4. Apply SecretsManager → wait Ready. +// 5. Apply LookupService (if present) → wait Ready. +// 6. Apply SessionManager → wait Ready. +// +// Returns the last LookupService/SessionManager objects observed so the +// caller can print URLs from .status. +func Deploy(ctx context.Context, out *translator.Output, opts Options) error { + if opts.Out == nil { + opts.Out = io.Discard + } + if opts.HelmLog == nil { + opts.HelmLog = io.Discard + } + if opts.Timeout == 0 { + opts.Timeout = DefaultTimeout + } + if opts.Progress == nil { + opts.Progress = progress.New(io.Discard, 0, false) + } + + // Note-class lines (no step counter) for the setup operations + // that aren't part of the install sequence proper. + if opts.SyncLocalSecrets { + opts.Progress.Note("syncing cached local secrets to cluster") + if err := syncLocalSecrets(opts.Getter); err != nil { + return err + } + } + + chrt, err := chart.Load() + if err != nil { + return fmt.Errorf("load embedded chart: %w", err) + } + // Applier needs to exist before the CRD step; hoist before helm. + applier, err := apply.New(opts.Getter) + if err != nil { + return err + } + waiter, err := wait.New(opts.Getter) + if err != nil { + return err + } + + // 1. CRDs. + if !opts.SkipCRDApply { + step := opts.Progress.Start("apply CRDs") + applied, err := crds.Apply(ctx, applier, chrt) + if err != nil { + step.Fail(err) + return err + } + step.Done(fmt.Sprintf("%d applied", len(applied))) + } + + // 2. Helm install/upgrade the operator chart. + step := opts.Progress.Start(fmt.Sprintf("helm upgrade --install %s", OperatorReleaseName)) + helmClient, err := helm.New(opts.Getter, OperatorNamespace, opts.HelmLog) + if err != nil { + step.Fail(err) + return err + } + if _, err := helmClient.UpgradeOrInstall(ctx, OperatorReleaseName, chrt, out.OperatorChartValues); err != nil { + step.Fail(err) + return err + } + step.Done("released") + + // 3. Apply EducatesClusterConfig + wait. + if err := applyAndWaitStep(ctx, opts, applier, waiter, out.EducatesClusterConfig, "EducatesClusterConfig"); err != nil { + return err + } + + // 4. Prereq check — only meaningful when the caller didn't sync + // local secrets. With SyncLocalSecrets the cache push is the + // prereq; the render-time lookup already verified the cache had + // a CA matching the domain. + if !opts.SkipPrereqCheck && !opts.SyncLocalSecrets { + step := opts.Progress.Start(fmt.Sprintf("check prerequisite Secret %s", prereq.CustomCASecretName)) + if err := prereq.CheckCustomCASecret(ctx, opts.Getter, OperatorNamespace); err != nil { + step.Fail(err) + return err + } + step.Done("present") + } + + // 5. SecretsManager + wait. + if err := applyAndWaitStep(ctx, opts, applier, waiter, out.SecretsManager, "SecretsManager"); err != nil { + return err + } + + // 6. LookupService + SessionManager — applied together, waited + // together. See remote-access-token cycle comment from commit + // 0d79afc6. + if out.LookupService != nil { + if err := applyOnlyStep(ctx, opts, applier, out.LookupService, "LookupService"); err != nil { + return err + } + } + if err := applyOnlyStep(ctx, opts, applier, out.SessionManager, "SessionManager"); err != nil { + return err + } + if out.LookupService != nil { + if err := waitOnlyStep(ctx, opts, waiter, out.LookupService, "LookupService"); err != nil { + return err + } + } + if err := waitOnlyStep(ctx, opts, waiter, out.SessionManager, "SessionManager"); err != nil { + return err + } + + opts.Progress.Note("deploy complete") + return nil +} + +// applyAndWaitStep does apply + wait under a single progress step. +// Used by ECC and SecretsManager where the two operations are +// strictly sequential. +func applyAndWaitStep(ctx context.Context, opts Options, applier *apply.Client, waiter *wait.Client, obj map[string]interface{}, label string) error { + if err := applyOnlyStep(ctx, opts, applier, obj, label); err != nil { + return err + } + return waitOnlyStep(ctx, opts, waiter, obj, label) +} + +// applyOnlyStep is one progress step that just applies and reports +// the apply outcome. Used by the interleaved LookupService / +// SessionManager path where applies and waits are deliberately split. +func applyOnlyStep(ctx context.Context, opts Options, applier *apply.Client, obj map[string]interface{}, label string) error { + u, err := mapToUnstructured(obj) + if err != nil { + return fmt.Errorf("%s: %w", label, err) + } + step := opts.Progress.Start(fmt.Sprintf("apply %s/%s", label, u.GetName())) + if _, err := applier.Apply(ctx, u); err != nil { + step.Fail(err) + return err + } + step.Done("applied") + return nil +} + +// waitOnlyStep is one progress step that just polls for Ready and +// surfaces phase changes (when the CR's status.phase field updates) +// as Update calls on the step. +func waitOnlyStep(ctx context.Context, opts Options, waiter *wait.Client, obj map[string]interface{}, label string) error { + u, err := mapToUnstructured(obj) + if err != nil { + return fmt.Errorf("%s: %w", label, err) + } + step := opts.Progress.Start(fmt.Sprintf("wait %s/%s Ready", label, u.GetName())) + if _, err := waiter.WaitReadyWithPhase(ctx, u.GroupVersionKind(), u.GetNamespace(), u.GetName(), opts.Timeout, step.Update); err != nil { + step.Fail(err) + return err + } + step.Done("Ready") + return nil +} + +// syncLocalSecrets copies /secrets/*.yaml into the cluster's +// 'educates-secrets' namespace. Reuses the v3 secrets package so the +// laptop flow stays the same; deletion of the v3 package in step 9 will +// fold this through whatever the new home is. +func syncLocalSecrets(getter genericclioptions.RESTClientGetter) error { + cfg, err := getter.ToRESTConfig() + if err != nil { + return fmt.Errorf("REST config for secrets sync: %w", err) + } + cs, err := kubernetes.NewForConfig(cfg) + if err != nil { + return fmt.Errorf("kubernetes client for secrets sync: %w", err) + } + if err := secrets.SyncLocalCachedSecretsToCluster(cs); err != nil { + return fmt.Errorf("sync local secrets: %w", err) + } + return nil +} + +// mapToUnstructured roundtrips a translator-produced CR map through JSON +// to get an *unstructured.Unstructured. The translator's maps are already +// JSON-shaped (string keys, no yaml-v2 interface{} maps) since they're +// built with map[string]interface{} literals. +func mapToUnstructured(m map[string]interface{}) (*unstructured.Unstructured, error) { + raw, err := json.Marshal(m) + if err != nil { + return nil, fmt.Errorf("marshal: %w", err) + } + u := &unstructured.Unstructured{} + if err := u.UnmarshalJSON(raw); err != nil { + return nil, fmt.Errorf("unmarshal: %w", err) + } + if u.GroupVersionKind() == (schema.GroupVersionKind{}) { + return nil, fmt.Errorf("missing apiVersion/kind") + } + return u, nil +} diff --git a/client-programs/pkg/deployer/helm/helm.go b/client-programs/pkg/deployer/helm/helm.go new file mode 100644 index 000000000..b9120b30d --- /dev/null +++ b/client-programs/pkg/deployer/helm/helm.go @@ -0,0 +1,147 @@ +// Package helm wraps the helm SDK with the small surface the CLI needs to +// install or upgrade the educates-installer chart in-process. +// +// It mirrors the operator's helm wrapper at installer/operator/internal/helm +// (which is not importable from this module — Go internal/ rule). The +// CLI-side variant differs by accepting a genericclioptions.RESTClientGetter +// directly (kubectl-style kubeconfig discovery) rather than a pre-built +// *rest.Config (which is what the operator has from controller-runtime). +package helm + +import ( + "context" + "errors" + "fmt" + "io" + "log/slog" + + "helm.sh/helm/v4/pkg/action" + chart "helm.sh/helm/v4/pkg/chart/v2" + "helm.sh/helm/v4/pkg/kube" + release "helm.sh/helm/v4/pkg/release/v1" + "helm.sh/helm/v4/pkg/storage/driver" + "k8s.io/cli-runtime/pkg/genericclioptions" +) + +// helmDriver = "secrets" matches the helm CLI default. Releases the CLI +// creates are visible to `helm list` and vice versa. +const helmDriver = "secrets" + +// ErrReleaseNotFound is the stable sentinel for "no release with that name". +var ErrReleaseNotFound = errors.New("helm release not found") + +// Client is a small helm action wrapper scoped to one namespace. +type Client struct { + cfg *action.Configuration + namespace string +} + +// New builds a Client from a kubectl-style RESTClientGetter. Pass the +// genericclioptions.ConfigFlags the cobra command parsed (--kubeconfig, +// --context, --namespace) directly — the SDK consumes the same interface +// the helm CLI does. +// +// logOut receives helm SDK debug output. The CLI usually wants this +// suppressed in production but visible with --verbose; callers pass +// io.Discard or os.Stderr accordingly. +func New(getter genericclioptions.RESTClientGetter, namespace string, logOut io.Writer) (*Client, error) { + if namespace == "" { + return nil, errors.New("namespace is required") + } + if logOut == nil { + logOut = io.Discard + } + cfg := new(action.Configuration) + if err := cfg.Init(getter, namespace, helmDriver); err != nil { + return nil, fmt.Errorf("init helm action config: %w", err) + } + cfg.SetLogger(slog.NewTextHandler(logOut, &slog.HandlerOptions{Level: slog.LevelDebug})) + return &Client{cfg: cfg, namespace: namespace}, nil +} + +// UpgradeOrInstall is the idempotent variant: install if no release of +// that name exists, otherwise upgrade. The CLI's deploy command calls +// this; reruns of `educates admin platform deploy` should converge. +func (c *Client) UpgradeOrInstall(ctx context.Context, releaseName string, chrt *chart.Chart, vals map[string]any) (*release.Release, error) { + existing, err := c.status(releaseName) + if err != nil && !errors.Is(err, ErrReleaseNotFound) { + return nil, err + } + if existing == nil { + return c.install(ctx, releaseName, chrt, vals) + } + return c.upgrade(ctx, releaseName, chrt, vals) +} + +func (c *Client) install(ctx context.Context, name string, chrt *chart.Chart, vals map[string]any) (*release.Release, error) { + act := action.NewInstall(c.cfg) + act.ReleaseName = name + act.Namespace = c.namespace + act.CreateNamespace = true + act.WaitStrategy = kube.HookOnlyStrategy + // CRD lifecycle is owned by pkg/deployer/crds (applied separately + // before this install so the same path runs on first-install and + // on every subsequent re-deploy — helm's default would only install + // CRDs on first install). + act.SkipCRDs = true + + rel, err := act.RunWithContext(ctx, chrt, vals) + if err != nil { + return nil, fmt.Errorf("helm install %q: %w", name, err) + } + r, ok := rel.(*release.Release) + if !ok { + return nil, fmt.Errorf("helm install %q: unexpected release type %T", name, rel) + } + return r, nil +} + +func (c *Client) upgrade(ctx context.Context, name string, chrt *chart.Chart, vals map[string]any) (*release.Release, error) { + act := action.NewUpgrade(c.cfg) + act.Namespace = c.namespace + act.WaitStrategy = kube.HookOnlyStrategy + // ForceConflicts lets a re-deploy steal field ownership from + // 'kubectl edit'/'kubectl patch' (which claim ownership under + // the 'kubectl-edit'/'kubectl-patch' field managers). Without + // this, any user-side manual edit poisons the next deploy with + // an SSA conflict on the edited field. The CLI's deploy is the + // source of truth for chart-managed fields. + act.ForceConflicts = true + + rel, err := act.RunWithContext(ctx, name, chrt, vals) + if err != nil { + return nil, fmt.Errorf("helm upgrade %q: %w", name, err) + } + r, ok := rel.(*release.Release) + if !ok { + return nil, fmt.Errorf("helm upgrade %q: unexpected release type %T", name, rel) + } + return r, nil +} + +// Uninstall removes the named release. Idempotent: missing → nil. +func (c *Client) Uninstall(name string) error { + act := action.NewUninstall(c.cfg) + act.IgnoreNotFound = true + act.WaitStrategy = kube.HookOnlyStrategy + if _, err := act.Run(name); err != nil { + return fmt.Errorf("helm uninstall %q: %w", name, err) + } + return nil +} + +func (c *Client) status(name string) (*release.Release, error) { + rel, err := action.NewStatus(c.cfg).Run(name) + if err != nil { + if errors.Is(err, driver.ErrReleaseNotFound) { + return nil, ErrReleaseNotFound + } + return nil, fmt.Errorf("helm status %q: %w", name, err) + } + r, ok := rel.(*release.Release) + if !ok { + return nil, fmt.Errorf("helm status %q: unexpected release type %T", name, rel) + } + return r, nil +} + diff --git a/client-programs/pkg/deployer/prereq/ca.go b/client-programs/pkg/deployer/prereq/ca.go new file mode 100644 index 000000000..ef0c2e3cd --- /dev/null +++ b/client-programs/pkg/deployer/prereq/ca.go @@ -0,0 +1,57 @@ +// Package prereq checks deploy prerequisites that must be satisfied before +// the four platform CRs can reconcile. +package prereq + +import ( + "context" + "fmt" + + apierrors "k8s.io/apimachinery/pkg/api/errors" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/cli-runtime/pkg/genericclioptions" + "k8s.io/client-go/kubernetes" +) + +// CustomCASecretName is the Secret the Local-mode translator hardcodes +// as caCertificateRef. Must exist in the operator namespace before deploy +// applies EducatesClusterConfig. +const CustomCASecretName = "educates-custom-ca" + +// CheckCustomCASecret returns nil when the educates-custom-ca Secret +// exists in the operator namespace, or a user-actionable error pointing +// at the kubectl command that creates it. +func CheckCustomCASecret(ctx context.Context, getter genericclioptions.RESTClientGetter, namespace string) error { + cfg, err := getter.ToRESTConfig() + if err != nil { + return fmt.Errorf("REST config: %w", err) + } + cs, err := kubernetes.NewForConfig(cfg) + if err != nil { + return fmt.Errorf("kubernetes client: %w", err) + } + _, err = cs.CoreV1().Secrets(namespace).Get(ctx, CustomCASecretName, metav1.GetOptions{}) + if err == nil { + return nil + } + if !apierrors.IsNotFound(err) { + return fmt.Errorf("read Secret %s/%s: %w", namespace, CustomCASecretName, err) + } + return fmt.Errorf(`missing prerequisite: Secret %q in namespace %q. + +EducatesLocalConfig deploys cert-manager in CustomCA mode, which signs +the cluster's wildcard TLS cert from a CA you provide. Create the Secret +before re-running deploy: + + kubectl create namespace %s + kubectl -n %s create secret tls %s \ + --cert=ca.crt \ + --key=ca.key + +For development on a laptop, a self-signed CA is fine. Generate one with: + + openssl req -x509 -newkey rsa:2048 -nodes -days 365 \ + -subj '/CN=educates-dev-ca' \ + -keyout ca.key -out ca.crt`, + CustomCASecretName, namespace, + namespace, namespace, CustomCASecretName) +} diff --git a/client-programs/pkg/deployer/progress/progress.go b/client-programs/pkg/deployer/progress/progress.go new file mode 100644 index 000000000..88d0cb523 --- /dev/null +++ b/client-programs/pkg/deployer/progress/progress.go @@ -0,0 +1,175 @@ +// Package progress renders deploy/delete step status as compact +// per-step lines instead of free-form prints. +// +// The default reporter writes 'plain text with [N/M] counters' per +// the design choice in step 5 polish — no spinner library dep. When +// stdout is a TTY, in-progress lines are over-written via \r so the +// final state replaces the polling chatter. When stdout is not a TTY +// (CI, pipe, file), every state change appends a new line so the log +// is grep-able. +package progress + +import ( + "fmt" + "io" + "os" + "sync" +) + +// Reporter is the surface deploy.go / delete.go talk to. Each call to +// Start opens a Step the caller closes via Done or Fail. Update can be +// called any number of times in between to surface intermediate phase +// changes (the wait poller drives this). +// +// Reporters are safe for use from a single goroutine. The CLI today +// runs deploy strictly sequentially so a mutex-protected concurrency +// story isn't needed. +type Reporter interface { + Start(label string) Step + // Note prints a one-off informational line outside the step counter + // (used for things like 'syncing cached local secrets'). It does + // not advance the step counter. + Note(msg string) +} + +// Step represents one numbered deploy operation (apply ECC, wait +// SessionManager Ready, etc.). Update surfaces an intermediate state +// while the step is pending; Done / Fail close the step. +type Step interface { + Update(phase string) + Done(summary string) + Fail(err error) +} + +// New builds the default reporter. total is the expected step count +// (drives the [N/M] counter); 0 means counters are hidden ("delete" +// has a variable step count depending on what's actually present, so +// it passes 0 and just gets prefix-less lines). +// +// w is the destination; isTTY determines whether \r-based overwrite +// is used. Callers in cmd/ wire isTTY from os.Stdout. +func New(w io.Writer, total int, isTTY bool) Reporter { + if w == nil { + w = io.Discard + } + return &reporter{w: w, total: total, isTTY: isTTY} +} + +// NewForStdout wires the default reporter against os.Stdout and +// auto-detects TTY. Used by cmd/ to avoid threading isatty through +// every option struct. +func NewForStdout(total int) Reporter { + return New(os.Stdout, total, isTerminal(os.Stdout)) +} + +// isTerminal returns true when w is a TTY-like file descriptor. +// Stdlib-only check: os.File.Stat() yields ModeCharDevice for terminals. +func isTerminal(w io.Writer) bool { + f, ok := w.(*os.File) + if !ok { + return false + } + info, err := f.Stat() + if err != nil { + return false + } + return info.Mode()&os.ModeCharDevice != 0 +} + +type reporter struct { + w io.Writer + total int + isTTY bool + mu sync.Mutex + current int +} + +func (r *reporter) Start(label string) Step { + r.mu.Lock() + r.current++ + n := r.current + r.mu.Unlock() + s := &step{r: r, n: n, label: label} + s.render("") + return s +} + +func (r *reporter) Note(msg string) { + fmt.Fprintln(r.w, "·", msg) +} + +type step struct { + r *reporter + n int + label string + lastLine string // tracks last rendered text for TTY overwrite +} + +func (s *step) Update(phase string) { s.render(phase) } + +func (s *step) Done(summary string) { + s.finalize("✓", summary) +} + +func (s *step) Fail(err error) { + s.finalize("✗", err.Error()) +} + +// render writes the in-progress line, optionally overwriting the +// previous render on a TTY. +func (s *step) render(phase string) { + line := s.format("→", phase) + if s.r.isTTY && s.lastLine != "" { + // Carriage return + spaces to clear previous content. + fmt.Fprint(s.r.w, "\r"+pad(line, len(s.lastLine))) + } else { + fmt.Fprintln(s.r.w, line) + } + s.lastLine = line +} + +// finalize writes the closing line (✓ or ✗). On a TTY this overwrites +// the in-progress line; on a non-TTY it appends. +func (s *step) finalize(symbol, msg string) { + final := s.format(symbol, msg) + if s.r.isTTY { + fmt.Fprintln(s.r.w, "\r"+pad(final, len(s.lastLine))) + } else { + fmt.Fprintln(s.r.w, final) + } + s.lastLine = "" +} + +// format builds '[3/6] symbol Label: detail'. Empty total hides the +// counter; empty detail hides the colon-detail tail. +func (s *step) format(symbol, detail string) string { + prefix := "" + if s.r.total > 0 { + prefix = fmt.Sprintf("[%d/%d] ", s.n, s.r.total) + } + out := fmt.Sprintf("%s%s %s", prefix, symbol, s.label) + if detail != "" { + out += ": " + detail + } + return out +} + +// pad right-pads s with spaces to at least width characters so a TTY +// overwrite hides longer previous content. +func pad(s string, width int) string { + if len(s) >= width { + return s + } + return s + spaces(width-len(s)) +} + +func spaces(n int) string { + if n <= 0 { + return "" + } + b := make([]byte, n) + for i := range b { + b[i] = ' ' + } + return string(b) +} diff --git a/client-programs/pkg/deployer/progress/progress_test.go b/client-programs/pkg/deployer/progress/progress_test.go new file mode 100644 index 000000000..5b443530a --- /dev/null +++ b/client-programs/pkg/deployer/progress/progress_test.go @@ -0,0 +1,92 @@ +package progress + +import ( + "bytes" + "errors" + "strings" + "testing" +) + +func TestNonTTY_AppendsEveryStateChange(t *testing.T) { + var buf bytes.Buffer + r := New(&buf, 3, false) + + s1 := r.Start("ECC apply") + s1.Done("Ready") + + s2 := r.Start("SecretsManager apply") + s2.Update("Installing") + s2.Update("Validating") + s2.Done("Ready") + + out := buf.String() + // Every state change should be its own line (no \r mid-stream). + if strings.Contains(out, "\r") { + t.Errorf("non-TTY mode should not emit \\r:\n%q", out) + } + for _, want := range []string{ + "[1/3] → ECC apply", + "[1/3] ✓ ECC apply: Ready", + "[2/3] → SecretsManager apply", + "[2/3] → SecretsManager apply: Installing", + "[2/3] → SecretsManager apply: Validating", + "[2/3] ✓ SecretsManager apply: Ready", + } { + if !strings.Contains(out, want) { + t.Errorf("output missing %q:\n%s", want, out) + } + } +} + +func TestTTY_OverwritesWithCarriageReturn(t *testing.T) { + var buf bytes.Buffer + r := New(&buf, 2, true) + + s := r.Start("ECC apply") + s.Update("Installing") + s.Done("Ready") + + out := buf.String() + if !strings.Contains(out, "\r") { + t.Errorf("TTY mode should emit \\r for in-place updates:\n%q", out) + } + // Final state should still be present. + if !strings.Contains(out, "✓ ECC apply: Ready") { + t.Errorf("final state missing:\n%s", out) + } +} + +func TestNoCounter_WhenTotalZero(t *testing.T) { + var buf bytes.Buffer + r := New(&buf, 0, false) + r.Start("LookupService delete").Done("gone") + out := buf.String() + if strings.Contains(out, "[1/0]") || strings.Contains(out, "[1/") { + t.Errorf("total=0 should hide counter:\n%s", out) + } + if !strings.Contains(out, "✓ LookupService delete: gone") { + t.Errorf("expected counter-less final line:\n%s", out) + } +} + +func TestFail_RendersErrorMessage(t *testing.T) { + var buf bytes.Buffer + r := New(&buf, 1, false) + r.Start("ECC apply").Fail(errors.New("boom")) + if !strings.Contains(buf.String(), "✗ ECC apply: boom") { + t.Errorf("fail line missing:\n%s", buf.String()) + } +} + +func TestNote_HasNoCounter(t *testing.T) { + var buf bytes.Buffer + r := New(&buf, 5, false) + r.Note("syncing cached local secrets") + out := buf.String() + if strings.Contains(out, "[1/5]") { + t.Errorf("Note should not advance the step counter:\n%s", out) + } + if !strings.Contains(out, "· syncing cached local secrets") { + t.Errorf("note prefix missing:\n%s", out) + } +} diff --git a/client-programs/pkg/deployer/wait/wait.go b/client-programs/pkg/deployer/wait/wait.go new file mode 100644 index 000000000..1e5facf4d --- /dev/null +++ b/client-programs/pkg/deployer/wait/wait.go @@ -0,0 +1,198 @@ +// Package wait polls a Kubernetes resource until its Ready=True condition +// flips, or a timeout fires. Used by deploy between CR apply calls — each +// platform CR is gated on the previous one being Ready. +package wait + +import ( + "context" + "fmt" + "time" + + apierrors "k8s.io/apimachinery/pkg/api/errors" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" + "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/cli-runtime/pkg/genericclioptions" + "k8s.io/client-go/discovery" + "k8s.io/client-go/discovery/cached/memory" + "k8s.io/client-go/dynamic" + "k8s.io/client-go/restmapper" +) + +// Client polls a resource via dynamic+REST mapping. One Client per +// deploy run. +type Client struct { + dyn dynamic.Interface + mapper *restmapper.DeferredDiscoveryRESTMapper +} + +func New(getter genericclioptions.RESTClientGetter) (*Client, error) { + cfg, err := getter.ToRESTConfig() + if err != nil { + return nil, err + } + dyn, err := dynamic.NewForConfig(cfg) + if err != nil { + return nil, err + } + dc, err := discovery.NewDiscoveryClientForConfig(cfg) + if err != nil { + return nil, err + } + mapper := restmapper.NewDeferredDiscoveryRESTMapper(memory.NewMemCacheClient(dc)) + return &Client{dyn: dyn, mapper: mapper}, nil +} + +// PollInterval is how often the waiter re-checks. Kept short to keep +// the CLI feeling responsive on small clusters; large clusters mostly +// pay the cost in apiserver list/watch traffic which is negligible. +const PollInterval = 2 * time.Second + +// WaitReady blocks until the object's status.conditions[?(@.type=="Ready")].status +// is "True", or ctx times out. namespace="" for cluster-scoped resources. +// +// Returns the last-observed object on success — callers use it for the +// summary line (status.url, status.observedDomain, etc.). +func (c *Client) WaitReady(ctx context.Context, gvk schema.GroupVersionKind, namespace, name string, timeout time.Duration) (*unstructured.Unstructured, error) { + return c.WaitReadyWithPhase(ctx, gvk, namespace, name, timeout, nil) +} + +// WaitReadyWithPhase is WaitReady with a callback that fires every +// time the observed phase changes (or first becomes set). The callback +// runs on the poll goroutine; reporter implementations are expected to +// be cheap (write a single status line). A nil callback is equivalent +// to WaitReady. +func (c *Client) WaitReadyWithPhase(ctx context.Context, gvk schema.GroupVersionKind, namespace, name string, timeout time.Duration, onPhase func(phase string)) (*unstructured.Unstructured, error) { + mapping, err := c.mapper.RESTMapping(gvk.GroupKind(), gvk.Version) + if err != nil { + return nil, fmt.Errorf("REST mapping for %s: %w", gvk, err) + } + resource := c.dyn.Resource(mapping.Resource) + var typed dynamic.ResourceInterface = resource + if namespace != "" { + typed = resource.Namespace(namespace) + } + + deadline := time.Now().Add(timeout) + var lastPhase string + for { + obj, err := typed.Get(ctx, name, metav1.GetOptions{}) + if err != nil && !apierrors.IsNotFound(err) { + return nil, fmt.Errorf("get %s/%s: %w", gvk.Kind, name, err) + } + if onPhase != nil && obj != nil { + if phase, _, _ := unstructured.NestedString(obj.Object, "status", "phase"); phase != "" && phase != lastPhase { + onPhase(phase) + lastPhase = phase + } + } + if err == nil && isReady(obj) { + return obj, nil + } + + if time.Now().After(deadline) { + return obj, fmt.Errorf("timeout waiting for %s/%s to be Ready (last status: %s)", + gvk.Kind, name, readyReason(obj)) + } + select { + case <-ctx.Done(): + return obj, ctx.Err() + case <-time.After(PollInterval): + } + } +} + +// WaitGone polls until the resource is 404 or ctx times out. Used by the +// delete command to gate on a finalizer-driven drain completing before +// moving to the next CR in reverse-install order. +// +// "Already gone" at first poll is success: idempotent re-runs of delete +// (or deleting state the deploy never created) shouldn't fail. +func (c *Client) WaitGone(ctx context.Context, gvk schema.GroupVersionKind, namespace, name string, timeout time.Duration) error { + mapping, err := c.mapper.RESTMapping(gvk.GroupKind(), gvk.Version) + if err != nil { + return fmt.Errorf("REST mapping for %s: %w", gvk, err) + } + resource := c.dyn.Resource(mapping.Resource) + var typed dynamic.ResourceInterface = resource + if namespace != "" { + typed = resource.Namespace(namespace) + } + + deadline := time.Now().Add(timeout) + for { + obj, err := typed.Get(ctx, name, metav1.GetOptions{}) + if apierrors.IsNotFound(err) { + return nil + } + if err != nil { + return fmt.Errorf("get %s/%s: %w", gvk.Kind, name, err) + } + if time.Now().After(deadline) { + return fmt.Errorf("timeout waiting for %s/%s to be deleted (last phase: %s, finalizers: %v)", + gvk.Kind, name, lastPhase(obj), obj.GetFinalizers()) + } + select { + case <-ctx.Done(): + return ctx.Err() + case <-time.After(PollInterval): + } + } +} + +// lastPhase pulls .status.phase from an object for the timeout error +// message. Returns "(none)" when unset. +func lastPhase(obj *unstructured.Unstructured) string { + if p, _, _ := unstructured.NestedString(obj.Object, "status", "phase"); p != "" { + return p + } + return "(none)" +} + +// isReady returns true when status.conditions[?(@.type=="Ready")].status == "True". +func isReady(obj *unstructured.Unstructured) bool { + if obj == nil { + return false + } + conds, found, err := unstructured.NestedSlice(obj.Object, "status", "conditions") + if err != nil || !found { + return false + } + for _, c := range conds { + m, ok := c.(map[string]interface{}) + if !ok { + continue + } + if m["type"] == "Ready" && m["status"] == "True" { + return true + } + } + return false +} + +// readyReason extracts a short status snippet for the timeout error +// message. Returns "(no status yet)" when the object hasn't reconciled +// at all. +func readyReason(obj *unstructured.Unstructured) string { + if obj == nil { + return "(not found)" + } + phase, _, _ := unstructured.NestedString(obj.Object, "status", "phase") + if phase != "" { + return "phase=" + phase + } + conds, _, _ := unstructured.NestedSlice(obj.Object, "status", "conditions") + for _, c := range conds { + m, ok := c.(map[string]interface{}) + if !ok { + continue + } + if m["type"] == "Ready" { + status, _ := m["status"].(string) + reason, _ := m["reason"].(string) + msg, _ := m["message"].(string) + return fmt.Sprintf("Ready=%s reason=%q message=%q", status, reason, msg) + } + } + return "(no status yet)" +} diff --git a/client-programs/pkg/diagnostics/compress.go b/client-programs/pkg/diagnostics/compress.go index 1b0c575f2..d56d9e103 100644 --- a/client-programs/pkg/diagnostics/compress.go +++ b/client-programs/pkg/diagnostics/compress.go @@ -14,7 +14,7 @@ func CompressDirToFile(tempDir string, targetFile string) error { // Compress the directory into the file provided out, err := os.Create(targetFile) if err != nil { - errors.Errorf("Error writing archive:", err) + return errors.Wrap(err, "Error writing archive") } defer out.Close() diff --git a/client-programs/pkg/installer/installer.go b/client-programs/pkg/installer/installer.go deleted file mode 100644 index 8fc6e6c0a..000000000 --- a/client-programs/pkg/installer/installer.go +++ /dev/null @@ -1,457 +0,0 @@ -package installer - -import ( - "context" - "fmt" - "os" - "path/filepath" - "time" - - "github.com/educates/educates-training-platform/client-programs/pkg/cluster" - "github.com/educates/educates-training-platform/client-programs/pkg/config" - "github.com/educates/educates-training-platform/client-programs/pkg/logger" - "github.com/educates/educates-training-platform/client-programs/pkg/utils" - - "github.com/cppforlife/go-cli-ui/ui" - "github.com/pkg/errors" - - "carvel.dev/imgpkg/pkg/imgpkg/cmd" - "carvel.dev/imgpkg/pkg/imgpkg/registry" - imgpkgv1 "carvel.dev/imgpkg/pkg/imgpkg/v1" - - "carvel.dev/kapp/pkg/kapp/cmd/app" - - cmdtpl "carvel.dev/ytt/pkg/cmd/template" - yttUI "carvel.dev/ytt/pkg/cmd/ui" - "carvel.dev/ytt/pkg/files" - - kbldcmd "carvel.dev/kbld/pkg/kbld/cmd" - kbldlog "carvel.dev/kbld/pkg/kbld/logger" - - "gopkg.in/yaml.v2" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" -) - -const EducatesInstallerString = "educates-installer" -const EducatesInstallerAppString = "label:installer=educates-installer.app" -const educatesConfigNamespace = "educates" -const educatesConfigConfigMapName = "educates-config" -const processedValuesKey = "educates-processed-values.yaml" -const originalConfigKey = "educates-original-config.yaml" - -// We use a NullWriter to suppress the output of some commands, like kbld -type NullWriter int - -func (NullWriter) Write([]byte) (int, error) { return 0, nil } - -type Installer struct { -} - -func NewInstaller() *Installer { - return &Installer{} -} - -func (inst *Installer) DryRun(version string, packageRepository string, fullConfig *config.InstallationConfig, verbose bool, showPackagesValues bool, skipImageResolution bool) error { - if verbose { - fmt.Println("Installing educates (DryRun) ...") - } - - // Create a temporary directory - tempDir, err := os.MkdirTemp("", EducatesInstallerString) - if err != nil { - return err - } - // if verbose { - // fmt.Println("Temp dir: ", tempDir) - // } - - defer os.RemoveAll(tempDir) // clean up - - // Hack for local development. When version=latest, we use: - // - localhost:5001 as the package repository - // - 0.0.1 as the version - // - skipImageResolution=true - if version == "latest" { - packageRepository = "localhost:5001" - version = "0.0.1" - skipImageResolution = true - } - - // Fetch - prevDir, err := inst.fetch(tempDir, version, packageRepository, verbose) - if err != nil { - return err - } - - // Template - prevDir, err = inst.template(tempDir, prevDir, fullConfig, verbose, showPackagesValues, skipImageResolution) - if err != nil { - return err - } - - // kbld - if !skipImageResolution { - prevDir, err = inst.resolve(tempDir, prevDir, verbose) - if err != nil { - return err - } - } - - err = utils.PrintYamlFilesInDir(prevDir, []string{}) - if err != nil { - return err - } - - return nil -} - -func (inst *Installer) Run(version string, packageRepository string, fullConfig *config.InstallationConfig, clusterConfig *cluster.ClusterConfig, verbose bool, showPackagesValues bool, skipImageResolution bool, showDiff bool) error { - if verbose { - fmt.Println("Installing educates ...") - } - - // Create a temporary directory - tempDir, err := os.MkdirTemp("", EducatesInstallerString) - if err != nil { - return err - } - // if verbose { - // fmt.Println("Temp dir: ", tempDir) - // } - - defer os.RemoveAll(tempDir) // clean up - - // Hack for local development. When version=latest, we use: - // - localhost:5001 as the package repository - // - 0.0.1 as the version - // - skipImageResolution=true - if version == "latest" { - packageRepository = "localhost:5001" - version = "0.0.1" - skipImageResolution = true - } - - // Fetch - prevDir, err := inst.fetch(tempDir, version, packageRepository, verbose) - if err != nil { - return err - } - - // Template - prevDir, err = inst.template(tempDir, prevDir, fullConfig, verbose, showPackagesValues, skipImageResolution) - if err != nil { - return err - } - - // kbld for image resolution - if !skipImageResolution { - prevDir, err = inst.resolve(tempDir, prevDir, verbose) - if err != nil { - return err - } - } - - // Deploy - err = inst.deploy(tempDir, prevDir, clusterConfig, verbose, showDiff) - if err != nil { - return err - } - - return nil -} - -func (inst *Installer) Delete(fullConfig *config.InstallationConfig, clusterConfig *cluster.ClusterConfig, verbose bool) error { - fmt.Println("Deleting educates ...") - - if err := inst.delete(clusterConfig); err != nil { - return err - } - - return nil -} - -func (inst *Installer) GetValuesFromCluster(kubeconfig string, kubeContext string) (string, error) { - clusterConfig := cluster.NewClusterConfig(kubeconfig, kubeContext) - - client, err := clusterConfig.GetClient() - - if err != nil { - return "", errors.Wrapf(err, "unable to create Kubernetes client") - } - - configMapClient := client.CoreV1().ConfigMaps(educatesConfigNamespace) - - values, err := configMapClient.Get(context.TODO(), educatesConfigConfigMapName, metav1.GetOptions{}) - - if err != nil { - return "", errors.Wrap(err, "error querying the cluster") - } - - valuesData, ok := values.Data[processedValuesKey] - - if !ok { - return "", errors.New("no platform configuration found") - } - - return string(valuesData), nil -} - -func (inst *Installer) GetConfigFromCluster(kubeconfig string, kubeContext string) (string, error) { - clusterConfig := cluster.NewClusterConfig(kubeconfig, kubeContext) - - client, err := clusterConfig.GetClient() - - if err != nil { - return "", errors.Wrapf(err, "unable to create Kubernetes client") - } - - configMapClient := client.CoreV1().ConfigMaps(educatesConfigNamespace) - - values, err := configMapClient.Get(context.TODO(), educatesConfigConfigMapName, metav1.GetOptions{}) - - if err != nil { - return "", errors.Wrap(err, "error querying the cluster") - } - - valuesData, ok := values.Data[originalConfigKey] - - if !ok { - return "", errors.New("no platform configuration found") - } - - return string(valuesData), nil -} - -func (inst *Installer) fetch(tempDir string, version string, packageRepository string, verbose bool) (string, error) { - if verbose { - fmt.Println("Running fetch ...") - } - - pullOpts := imgpkgv1.PullOpts{ - Logger: logger.NewNullLogger(), - AsImage: false, - IsBundle: true, - } - // TODO: Remove some logging from here - fetchOutputDir := filepath.Join(tempDir, "fetch") - _, err := imgpkgv1.Pull(inst.getBundleImageRef(version, packageRepository, verbose), fetchOutputDir, pullOpts, registry.Opts{}) - if err != nil { - // TODO: There might be more potential issues here - return "", errors.Wrapf(err, "Installer image not found") - } - return fetchOutputDir, nil -} - -func (inst *Installer) template(tempDir string, inputDir string, fullConfig *config.InstallationConfig, verbose bool, showPackagesValues bool, skipImageResolution bool) (string, error) { - if verbose { - fmt.Println("Running template ...") - } - - paths := []string{filepath.Join(inputDir, "config/ytt/")} - if !showPackagesValues && !skipImageResolution { - paths = append(paths, filepath.Join(inputDir, "kbld/kbld-bundle.yaml")) - } - filesToProcess, err := files.NewSortedFilesFromPaths(paths, files.SymlinkAllowOpts{}) - if err != nil { - return "", err - } - - // Use ytt to generate the yaml for the cluster packages - opts := cmdtpl.NewOptions() - - // Debug in ytt schema config is used to output the processed values - if showPackagesValues { - fullConfig.Debug = utils.BoolPointer(true) - } - - yamlBytes, err := yaml.Marshal(fullConfig) - if err != nil { - return "", err - } - - kbldFiles := []*files.File{} - // TODO: Revisit when this needs to be used - // if !skipImageResolution { - kbldFiles, err = files.NewSortedFilesFromPaths([]string{filepath.Join(inputDir, "kbld/kbld-images.yaml")}, files.SymlinkAllowOpts{}) - if err != nil { - return "", err - } - // } - - opts.DataValuesFlags = cmdtpl.DataValuesFlags{ - FromFiles: []string{"values", "images"}, - ReadFilesFunc: func(path string) ([]*files.File, error) { - switch path { - case "values": - return []*files.File{ - files.MustNewFileFromSource(files.NewBytesSource("values/values.yaml", yamlBytes)), - }, nil - case "images": - return kbldFiles, nil - default: - return nil, fmt.Errorf("unknown file '%s'", path) - } - }, - } - - out := opts.RunWithFiles(cmdtpl.Input{Files: filesToProcess}, yttUI.NewTTY(false)) - - // When we get errors in ytt processing, e.g. because of schema validation, out.Err is not nil - if out.Err != nil { - fmt.Println(out.Err) - } - if out.DocSet == nil { - return "", errors.New("error processing files") - } - - // Create a new subdirectory in tempDir - templateOutputDir := filepath.Join(tempDir, "template") - err = os.Mkdir(templateOutputDir, 0755) - if err != nil { - fmt.Printf("Failed to create subdirectory: %v\n", err) - return "", err - } - - // We write the processed output to files - err = utils.WriteYamlDocSetItemsToDir(out.DocSet, templateOutputDir) - if err != nil { - return "", err - } - return templateOutputDir, nil -} - -func (inst *Installer) resolve(tempDir string, inputDir string, verbose bool) (string, error) { - if verbose { - fmt.Println("Running resolve images ...") - } - - kbldOutputDir := filepath.Join(tempDir, "kbld") - err := os.Mkdir(kbldOutputDir, 0755) - if err != nil { - return "", err - } - - // ui - confUI := ui.NewConfUI(ui.NewNoopLogger()) - uiFlags := cmd.UIFlags{ - Color: true, - JSON: false, - NonInteractive: true, - } - uiFlags.ConfigureUI(confUI) - defer confUI.Flush() - - resolveOptions := kbldcmd.NewResolveOptions(confUI) - resolveOptions.FileFlags.Files = []string{inputDir} - // Apply defaults from CLI - resolveOptions.ImagesAnnotation = false - resolveOptions.OriginsAnnotation = false - resolveOptions.UnresolvedInspect = false - resolveOptions.AllowedToBuild = false - resolveOptions.BuildConcurrency = 5 - var logger kbldlog.Logger - if verbose { - logger = kbldlog.NewLogger(os.Stderr) - } else { - logger = kbldlog.NewLogger(NullWriter(0)) - } - prefixedLogger := logger.NewPrefixedWriter("resolve | ") - resBss, err := resolveOptions.ResolveResources(&logger, prefixedLogger) - if err != nil { - return "", err - } - if verbose { - fmt.Println("All images have been resolved images") - } - - err = utils.WriteYamlByteArrayItemsToDir(resBss, kbldOutputDir) - if err != nil { - return "", err - } - return kbldOutputDir, nil -} - -func (inst *Installer) deploy(tempDir string, inputDir string, clusterConfig *cluster.ClusterConfig, verbose bool, showDiff bool) error { - if verbose { - fmt.Println("Running deploy ...") - } - - confUI := ui.NewConfUI(ui.NewNoopLogger()) - uiFlags := cmd.UIFlags{ - Color: true, - JSON: false, - NonInteractive: true, - } - uiFlags.ConfigureUI(confUI) - defer confUI.Flush() - - depsFactory := NewKappDepsFactoryImpl(clusterConfig) - deployOptions := app.NewDeployOptions(confUI, depsFactory, logger.NewKappLogger(), nil) - deployOptions.AppFlags.Name = EducatesInstallerAppString - deployOptions.AppFlags.AppNamespace = EducatesInstallerString - deployOptions.FileFlags.Files = []string{inputDir, filepath.Join(tempDir, "fetch/config/kapp/")} - deployOptions.ApplyFlags.ClusterChangeOpts.Wait = true - deployOptions.ApplyFlags.ClusterChangeOpts.ApplyIgnored = false - deployOptions.ApplyFlags.ClusterChangeOpts.WaitIgnored = false - - deployOptions.ApplyFlags.ApplyingChangesOpts.Concurrency = 5 - - deployOptions.ApplyFlags.WaitingChangesOpts.CheckInterval = time.Duration(1) * time.Second - deployOptions.ApplyFlags.WaitingChangesOpts.Timeout = time.Duration(15) * time.Minute - deployOptions.ApplyFlags.WaitingChangesOpts.Concurrency = 5 - - deployOptions.DeployFlags.ExistingNonLabeledResourcesCheck = false - deployOptions.DeployFlags.ExistingNonLabeledResourcesCheckConcurrency = 100 - deployOptions.DeployFlags.AppChangesMaxToKeep = 5 - - deployOptions.DiffFlags.AgainstLastApplied = true - if showDiff { - deployOptions.DiffFlags.Changes = true - } - - err := deployOptions.Run() - if err != nil { - return err - } - return nil -} - -func (inst *Installer) delete(clusterConfig *cluster.ClusterConfig) error { - fmt.Println("Running delete ...") - - confUI := ui.NewConfUI(ui.NewNoopLogger()) - - uiFlags := cmd.UIFlags{ - Color: true, - JSON: false, - NonInteractive: true, - } - - uiFlags.ConfigureUI(confUI) - - defer confUI.Flush() - - depsFactory := NewKappDepsFactoryImpl(clusterConfig) - deleteOptions := app.NewDeleteOptions(confUI, depsFactory, logger.NewKappLogger()) - deleteOptions.AppFlags.Name = EducatesInstallerAppString - deleteOptions.AppFlags.AppNamespace = EducatesInstallerString - deleteOptions.ApplyFlags.ClusterChangeOpts.Wait = true - deleteOptions.ApplyFlags.ApplyingChangesOpts.Concurrency = 5 - deleteOptions.ApplyFlags.WaitingChangesOpts.CheckInterval = time.Duration(1) * time.Second - deleteOptions.ApplyFlags.WaitingChangesOpts.Timeout = time.Duration(15) * time.Minute - deleteOptions.ApplyFlags.WaitingChangesOpts.Concurrency = 5 - - err := deleteOptions.Run() - if err != nil { - return err - } - return nil -} - -func (inst *Installer) getBundleImageRef(version string, packageRepository string, verbose bool) string { - bundleImageRef := fmt.Sprintf("%s/%s:%s", packageRepository, EducatesInstallerString, version) - if verbose { - fmt.Printf("Using installer image: %s\n", bundleImageRef) - } - return bundleImageRef -} diff --git a/client-programs/pkg/installer/kappDepsFactory.go b/client-programs/pkg/installer/kappDepsFactory.go deleted file mode 100644 index 034a15244..000000000 --- a/client-programs/pkg/installer/kappDepsFactory.go +++ /dev/null @@ -1,39 +0,0 @@ -package installer - -import ( - core "carvel.dev/kapp/pkg/kapp/cmd/core" - "github.com/educates/educates-training-platform/client-programs/pkg/cluster" - "k8s.io/apimachinery/pkg/api/meta" - "k8s.io/client-go/dynamic" - "k8s.io/client-go/kubernetes" -) - -type KappDepsFactoryImpl struct { - clusterConfig *cluster.ClusterConfig -} - -var _ core.DepsFactory = &KappDepsFactoryImpl{} - -func NewKappDepsFactoryImpl(clusterConfig *cluster.ClusterConfig) *KappDepsFactoryImpl { - return &KappDepsFactoryImpl{clusterConfig: clusterConfig} -} - -// ConfigureWarnings implements core.DepsFactory. -func (k *KappDepsFactoryImpl) ConfigureWarnings(warnings bool) { - // no-op -} - -// CoreClient implements core.DepsFactory. -func (k *KappDepsFactoryImpl) CoreClient() (kubernetes.Interface, error) { - return k.clusterConfig.GetClient() -} - -// DynamicClient implements core.DepsFactory. -func (k *KappDepsFactoryImpl) DynamicClient(opts core.DynamicClientOpts) (dynamic.Interface, error) { - return k.clusterConfig.GetDynamicClient() -} - -func (k *KappDepsFactoryImpl) RESTMapper() (meta.RESTMapper, error) { - // TODO: Implement this method - return nil, nil -} diff --git a/client-programs/pkg/registry/mirror.go b/client-programs/pkg/registry/mirror.go new file mode 100644 index 000000000..8c5368e26 --- /dev/null +++ b/client-programs/pkg/registry/mirror.go @@ -0,0 +1,15 @@ +package registry + +// MirrorConfig is the focused input for registry-mirror container +// management. Decouples the registry package from any specific CLI +// config kind. Callers build one from EducatesLocalConfig (via the +// laptop create command) or from individual command flags (via +// 'educates local mirror deploy/delete'). +type MirrorConfig struct { + Mirror string + URL string + Username string + Password string + Port string + BindIP string +} diff --git a/client-programs/pkg/registry/registry.go b/client-programs/pkg/registry/registry.go index 8ed27cf7b..69c5f62d6 100644 --- a/client-programs/pkg/registry/registry.go +++ b/client-programs/pkg/registry/registry.go @@ -17,7 +17,7 @@ import ( "github.com/docker/docker/api/types/image" "github.com/docker/docker/api/types/network" "github.com/docker/go-connections/nat" - "github.com/educates/educates-training-platform/client-programs/pkg/config" + "github.com/educates/educates-training-platform/client-programs/pkg/docker" "github.com/pkg/errors" yaml "gopkg.in/yaml.v2" @@ -186,7 +186,7 @@ func createRegistryContainer(bindIP string) error { * This function is used to deploy a registry mirror and link it to the cluster. * It is used when creating a new local registry mirror. */ -func DeployMirrorAndLinkToCluster(mirrorConfig *config.RegistryMirrorConfig) error { +func DeployMirrorAndLinkToCluster(mirrorConfig *MirrorConfig) error { err := createMirrorContainer(mirrorConfig) if err != nil { @@ -206,7 +206,7 @@ func DeployMirrorAndLinkToCluster(mirrorConfig *config.RegistryMirrorConfig) err /** * This private function only creates the registry mirror container. */ -func createMirrorContainer(mirrorConfig *config.RegistryMirrorConfig) error { +func createMirrorContainer(mirrorConfig *MirrorConfig) error { ctx := context.Background() fmt.Printf("Deploying local image registry mirror %s\n", mirrorConfig.Mirror) @@ -518,7 +518,7 @@ func DeleteRegistry() error { * This function is used to delete a local registry mirror and unlink it from the cluster. * It is used when deleting a local registry mirror. */ -func DeleteMirrorAndUnlinkFromCluster(mirrorConfig *config.RegistryMirrorConfig) error { +func DeleteMirrorAndUnlinkFromCluster(mirrorConfig *MirrorConfig) error { ctx := context.Background() fmt.Printf("Deleting local image registry mirror %s\n", mirrorConfig.Mirror) @@ -739,7 +739,7 @@ func PruneRegistry() error { /** * This function is used to get the container name of a registry mirror. */ -func registryMirrorContainerName(mirrorConfig *config.RegistryMirrorConfig) string { +func registryMirrorContainerName(mirrorConfig *MirrorConfig) string { return fmt.Sprintf("%s-mirror-%s", EducatesRegistryContainer, mirrorConfig.Mirror) } diff --git a/client-programs/pkg/renderer/hugo.go b/client-programs/pkg/renderer/hugo.go index daa0eb946..fbc40d5ee 100644 --- a/client-programs/pkg/renderer/hugo.go +++ b/client-programs/pkg/renderer/hugo.go @@ -439,7 +439,7 @@ func RunHugoServer(workshopRoot string, kubeconfig string, context string, works // Also catch signals so we can try and cleanup temporary directory. - c := make(chan os.Signal) + c := make(chan os.Signal, 1) signal.Notify(c, os.Interrupt, syscall.SIGTERM) go func() { diff --git a/client-programs/pkg/resolver/resolver.go b/client-programs/pkg/resolver/resolver.go index e21dadc6d..14a5107f2 100644 --- a/client-programs/pkg/resolver/resolver.go +++ b/client-programs/pkg/resolver/resolver.go @@ -13,7 +13,7 @@ import ( "github.com/docker/docker/api/types/image" "github.com/docker/docker/api/types/mount" "github.com/docker/go-connections/nat" - "github.com/educates/educates-training-platform/client-programs/pkg/config" + "github.com/educates/educates-training-platform/client-programs/pkg/config/hostinfo" "github.com/educates/educates-training-platform/client-programs/pkg/docker" "github.com/educates/educates-training-platform/client-programs/pkg/utils" "github.com/pkg/errors" @@ -198,7 +198,7 @@ func generateDnsmasqConfig(domain string, targetAddress string, extraDomains []s var clusterConfigData bytes.Buffer - localIPAddress, err := config.HostIP() + localIPAddress, err := hostinfo.DetectHostIP() if err != nil { localIPAddress = "127.0.0.1" diff --git a/client-programs/pkg/secrets/secrets.go b/client-programs/pkg/secrets/secrets.go index 568091f6d..63f3e425c 100644 --- a/client-programs/pkg/secrets/secrets.go +++ b/client-programs/pkg/secrets/secrets.go @@ -18,12 +18,17 @@ import ( "k8s.io/kubectl/pkg/scheme" ) -var secretsCacheDir = path.Join(utils.GetEducatesHomeDir(), "secrets") +// secretsCacheDir resolves the on-disk secrets cache directory at call +// time rather than at package-init, so $EDUCATES_CLI_DATA_HOME (and +// tests using t.Setenv) takes effect. +func secretsCacheDir() string { + return path.Join(utils.GetEducatesHomeDir(), "secrets") +} const secretsNS = "educates-secrets" func LocalCachedSecretForIngressDomain(domain string) string { - files, err := os.ReadDir(secretsCacheDir) + files, err := os.ReadDir(secretsCacheDir()) if err != nil { return "" @@ -66,7 +71,7 @@ func LocalCachedSecretForIngressDomain(domain string) string { } func LocalCachedSecretForCertificateAuthority(domain string) string { - files, err := os.ReadDir(secretsCacheDir) + files, err := os.ReadDir(secretsCacheDir()) if err != nil { return "" @@ -87,13 +92,19 @@ func LocalCachedSecretForCertificateAuthority(domain string) string { continue } - // Type of secret needs to be Opaque. - if secretObj.Type != "Opaque" && secretObj.Type != "" { + // v4 CustomCA flow: cert-manager signs workshop certs from + // this CA, so the Secret must carry both the CA cert and + // its private key. v3's Opaque+ca.crt shape (cert only, + // for trust distribution) is no longer supported — users + // who want a non-signing CA reference switch to the + // EducatesConfig escape hatch. + if secretObj.Type != apiv1.SecretTypeTLS { continue } - - // Needs contain ca.crt data. - if value, exists := secretObj.Data["ca.crt"]; !exists || len(value) == 0 { + if v, ok := secretObj.Data["tls.crt"]; !ok || len(v) == 0 { + continue + } + if v, ok := secretObj.Data["tls.key"]; !ok || len(v) == 0 { continue } @@ -108,7 +119,7 @@ func LocalCachedSecretForCertificateAuthority(domain string) string { * SyncSecretsToCluster copies secrets from the local cache to the cluster. */ func SyncLocalCachedSecretsToCluster(client *kubernetes.Clientset) error { - err := os.MkdirAll(secretsCacheDir, os.ModePerm) + err := os.MkdirAll(secretsCacheDir(), os.ModePerm) if err != nil { return errors.Wrapf(err, "unable to create secrets cache directory") @@ -125,15 +136,25 @@ func SyncLocalCachedSecretsToCluster(client *kubernetes.Clientset) error { }, } - namespacesClient.Create(context.TODO(), &namespaceObj, metav1.CreateOptions{}) + // Surface RBAC / admission / transient errors here rather than + // proceeding to write Secrets into a namespace that doesn't + // exist — the subsequent secret writes would fail with a + // confusing 'namespaces "educates-secrets" not found' that + // masks the real cause (typically: kubeconfig user lacks + // 'create namespaces'). + if _, err := namespacesClient.Create(context.TODO(), &namespaceObj, metav1.CreateOptions{}); err != nil && !k8serrors.IsAlreadyExists(err) { + return errors.Wrapf(err, "unable to create namespace %q for local secrets sync", secretsNS) + } + } else if err != nil { + return errors.Wrapf(err, "unable to check namespace %q for local secrets sync", secretsNS) } secretsClient := client.CoreV1().Secrets(secretsNS) - files, err := os.ReadDir(secretsCacheDir) + files, err := os.ReadDir(secretsCacheDir()) if err != nil { - return errors.Wrapf(err, "unable to read secrets cache directory %q", secretsCacheDir) + return errors.Wrapf(err, "unable to read secrets cache directory %q", secretsCacheDir()) } for _, f := range files { @@ -182,7 +203,7 @@ func SyncLocalCachedSecretsToCluster(client *kubernetes.Clientset) error { } func decodeFileIntoSecret(fileName string) (*apiv1.Secret, error) { - fullPath := path.Join(secretsCacheDir, fileName) + fullPath := path.Join(secretsCacheDir(), fileName) yamlData, err := os.ReadFile(fullPath) if err != nil { diff --git a/client-programs/pkg/utils/dirs.go b/client-programs/pkg/utils/dirs.go index 2a2ea6e68..ab566c2b9 100644 --- a/client-programs/pkg/utils/dirs.go +++ b/client-programs/pkg/utils/dirs.go @@ -1,11 +1,27 @@ package utils import ( + "os" "path" "github.com/adrg/xdg" ) +// EducatesCLIDataHomeEnv overrides the on-disk home for all Educates CLI +// state. When set and non-empty, it takes precedence over the default +// xdg.DataHome/educates location. Useful for CI, multi-instance laptop +// workflows, and tests. +const EducatesCLIDataHomeEnv = "EDUCATES_CLI_DATA_HOME" + +// GetEducatesHomeDir returns the on-disk home for all Educates CLI state +// (config.yaml, secrets/, kind/, resolver/, workshops/). +// +// Resolution order: +// 1. $EDUCATES_CLI_DATA_HOME if set and non-empty. +// 2. $XDG_DATA_HOME/educates/ (default). func GetEducatesHomeDir() string { + if v := os.Getenv(EducatesCLIDataHomeEnv); v != "" { + return v + } return path.Join(xdg.DataHome, "educates") } diff --git a/developer-docs/build-instructions.md b/developer-docs/build-instructions.md index a83976cf0..530f974e9 100644 --- a/developer-docs/build-instructions.md +++ b/developer-docs/build-instructions.md @@ -60,33 +60,24 @@ Note that this later command will create/update service resources in the Kuberne Defining installer configuration -------------------------------- -Before building and deploying Educates from source code, you will need to supply a configuration file providing details of the target cluster and what is to be installed. This configuration should be placed in the file: +Before building and deploying Educates from source code, you will need a configuration describing the target cluster and what is to be installed. The local configuration is managed by the `educates` CLI itself and lives in the CLI data home (by default `$XDG_DATA_HOME/educates/config.yaml`). Create a minimal configuration by running: ``` -developer-testing/educates-installer-values.yaml +educates local config init ``` -within the Educates source code directory. +You can inspect it with `educates local config view` and change it with `educates local config edit`. The local configuration uses the `EducatesLocalConfig` format and should contain at least: -Where deploying to the local Kind cluster created using the Educates CLI, you can create this by running: - -``` -educates local config view > developer-testing/educates-installer-values.yaml +```yaml +apiVersion: cli.educates.dev/v1alpha1 +kind: EducatesLocalConfig +ingress: + domain: 192-168-1-1.nip.io ``` -this should contain at least: +The `EducatesLocalConfig` kind implies an opinionated configuration suitable for a Kubernetes cluster created using Kind: the operator deploys an ingress router for the cluster using Contour, cert-manager for TLS, and Kyverno for implementing cluster and workshop security policies. -``` -clusterInfrastructure: - provider: kind - -clusterIngress: - domain: 192.168.1.1.nip.io -``` - -By setting the `provider` as `kind`, an opinionated configuration suitable for a Kubernetes cluster created using Kind will be used. This includes the automatic deployment and configuration of an ingress router for the cluster using Contour, and the installation of Kyverno for implementing cluster and workshop security policies. - -The `domain` should be set to be a `nip.io` address mapping to the IP address of your local host where you are doing development, or some other FQDN which maps to your local host. +The `domain` should be set to be a `nip.io` address mapping to the IP address of your local host where you are doing development, or some other FQDN which maps to your local host. If left unset, the deploy command falls back to a `nip.io` address derived from your host IP. If the configuration requires additional secrets these will need added to the local Kubernetes cluster in the namespace required by the configuration. If these secrets had previously been added to the local secrets cache, you can copy them to the local Kubernetes cluster by running: @@ -94,111 +85,145 @@ If the configuration requires additional secrets these will need added to the lo educates local secrets sync ``` -Building Educates platform images ---------------------------------- +Building Educates from source +----------------------------- -To build the container images for the Educates training platform you can run: +To build everything needed for local testing — the `educates` CLI, the core platform images and the installer operator image — run, from the repository root: ``` -make build-core-images +make ``` -NOTE: By default, images will be pushed to a local registry. There's instructions above on how to provide a local registry -via the Educates cli. +This is the default target (`local-build`). It: -This will trigger the building of the container images and push the resulting images to the local docker image registry. +* builds the `educates` CLI for your host platform into `client-programs/bin/educates--`, with compiled-in defaults pointing at the local image registry (`localhost:5001`, tag `latest`); +* deploys the local image registry container using that CLI if it isn't already running; +* builds the core platform images and the operator image **for your host architecture only** and pushes them to the local registry; +* regenerates the committed embedded artifacts (operator CRDs, the runtime subchart tarballs the operator embeds, the CLI-embedded operator chart and JSON schemas) when their sources changed — if `git status` is dirty after `make`, commit the regenerated files. -Targets for make are also available for building and pushing to the local docker image registry individual container images. +Then deploy the locally built system: ``` -make build-session-manager -make build-secrets-manager -make build-training-portal -... +client-programs/bin/educates-- local cluster create ``` -See the [Makefile](../Makefile) for more details of the make targets that are available. There are parameters that can be -set to alter behavior of the Makefile. There's comprehensive documentation at the top of the file. +Because the CLI was built with a non-release version (`latest`), it identifies itself as a development build and automatically points every platform image — the operator, secrets-manager, lookup-service, session-manager, training-portal, the workshop base environment and the rest of the core set — at `localhost:5001/educates-:latest`. No configuration editing is needed. Explicit `imageVersions` or `operator.image` entries in your local configuration always win over these defaults, so remove any manual overrides left over from earlier workflows unless you want them. -Once the container images have been built and pushed to the local docker image registry, you can then deploy everything by running: +Make knobs (environment variables or `make VAR=value`): -``` -make deploy-platform -``` +* `TARGET_PLATFORMS` — image platforms. Defaults to the current host architecture only (e.g. `linux/arm64` on Apple silicon); multi-architecture builds are explicit opt-in (`TARGET_PLATFORMS=linux/amd64,linux/arm64`) and slow under emulation. +* `IMAGE_REPOSITORY` / `PACKAGE_VERSION` — registry and tag for images (default `localhost:5001` / `latest`). +* `PUSH_IMAGES=false` — load images into the Docker daemon instead of pushing. +* `CLI_VERSION` / `CLI_IMAGE_REPOSITORY` — the CLI binary's compiled-in defaults; a semver `CLI_VERSION` makes the binary behave like a release build (no local-image defaulting). + +Any single image can be rebuilt with `make image-`, for example `make image-training-portal` or `make image-operator` (the operator target refreshes the embedded subchart tarballs first). Run `make help` for the full target list. Building requires `docker`, Go and `helm` (used to repackage the runtime subcharts the operator embeds). -This will perform an install directly from configuration files in the current directory. If needing to test that the `educates-installer` package bundle used by the Educates CLI installer can be installed using `kapp-controller`, ensure that `kapp-controller` is installed in the cluster and then use the commands: +After rebuilding runtime component images, restart the deployed components to pick them up (dev tags are pulled with `Always`): ``` -make build-all-images -make push-installer-bundle -make deploy-platform-app +make restart-training-platform ``` -The `make build-all-images` command will make sure that optional workshop base images as well as the core Educates platform are built. It is necessary to build all images when testing the package bundle as the package generated will include image hashes for all images. +For the operator itself, `make image-operator` then `kubectl rollout restart deployment -n educates-installer`. See the [operator README](../installer/operator/README.md) and the make targets there (`make smoke-test`, `make test`) for the operator development loop. -To delete everything deployed using the `educates-installer` package when using the `make` command, use: +If the cluster is already up and you only want to (re)deploy the platform, run: ``` -make delete-platform +client-programs/bin/educates-- admin platform deploy --local-config ``` -or: +To delete everything deployed to the cluster, use: ``` -make delete-platform-app +educates admin platform delete ``` -as appropriate. - Building additional workshop images ----------------------------------- -When using `make build-core-images`, it will only build the main workshop base image. That is, it will not build workshop base images for Java and Python. - -If you want to build all workshop base images you can instead run: +The default `make` only builds the main workshop base image. The workshop language images (Java and Python variants) are optional — when a workshop uses one and it isn't built locally, the published `ghcr.io/educates` image is used. To build them locally: ``` -make build-all-images +make build-workshop-images ``` -Note that this will consume a lot more storage space in the local docker environment. In general you will probably want to configure the local docker environment with 100Gi or more of storage space to be used across local image caching, the local docker image registry and the Kubernetes cluster itself. +or everything at once with `make build-all-images`. Note that this will consume a lot more storage space in the local docker environment. In general you will probably want to configure the local docker environment with 100Gi or more of storage space to be used across local image caching, the local docker image registry and the Kubernetes cluster itself. -As well as the `build-all-images`, make targets are also supplied for building and pushing to the local docker image registry individual workshop base images. +Individual workshop images can be built with the generic image target: ``` -make build-base-environment -make build-jdk8-environment -make build-jdk11-environment -make build-jdk17-environment -make build-jdk21-environment -make build-conda-environment +make image-base-environment +make image-jdk17-environment +make image-conda-environment ``` -See the [Makefile](../Makefile) for more details of the make targets that are available. +If you want a locally built language image to be used by deployed workshops, add a matching `imageVersions` entry to the local configuration (only the core set is defaulted automatically), for example `name: jdk17-environment`, `image: localhost:5001/educates-jdk17-environment:latest`. Building the Educates CLI program --------------------------------- -If needing to work on the `educates` CLI it can be built using the command: +If needing to work on just the `educates` CLI it can be built using the command: ``` -make build-client-programs +make build-cli ``` -You can then run the `educates` CLI program from the `client-programs/bin` subdirectory. The name of the compiled CLI will incorporate the target system and machine architecture, e.g.: `educates-linux-amd64`. +You can then run the `educates` CLI program from the `client-programs/bin` subdirectory. The name of the compiled CLI will incorporate the target system and machine architecture, e.g.: `educates-darwin-arm64`. (`make build-client-programs` remains as an alias.) + +Note that when building the `educates` CLI from local source code, the embedded project version defaults to `latest` and the embedded image registry to `localhost:5001` — the CLI behaves as a development build, defaulting all platform images to your local registry as described above. The operator Helm chart and config schemas embedded in the CLI are refreshed from your source tree as part of the build. To build a CLI that behaves like a release binary, pass a semver version: `make build-cli CLI_VERSION=4.0.0 CLI_IMAGE_REPOSITORY=ghcr.io/educates`. -Note that when building the `educates` CLI from local source code, the embedded project version will be `develop`. If you are running it to test creation of the local Kubernetes cluster with Educates using an existing version, you will need to tell it what previously released version of the package should be used. This can be done using the `--version` of sub commands where this is necessary. +Running CI checks locally +------------------------- + +The GitHub Actions workflows that gate pull requests +(`.github/workflows/client-programs-ci.yaml` and +`.github/workflows/installer-operator-ci.yaml`) invoke these same make +targets, so running them locally exercises exactly what CI runs — there is +no second copy of the step list to drift out of sync. From the repository +root: ``` -./client-programs/bin/educates-linux-amd64 create-cluster --version=3.0.0 +make ci # run all CI checks (CLI + operator) +make ci-cli # only the client-programs checks +make ci-operator # only the installer-operator checks ``` -If you have built and pushed to the local image registry the package bundles for `educates-installer`, you will need to tell the CLI to use the package bundles and images from the local image registry rather than those hosted on GitHub container registry. This can be done by specifying the version to be `latest`. +`make ci-cli` is what the client-programs workflow runs: it stages the +embedded theme files (see below), then runs `go vet`, `go build` and +`go test` against `client-programs`, and finally the embedded-chart and +CLI-schema drift checks (`verify-installer-chart`, `verify-cli-schemas`). + +`make ci-operator` is what the installer-operator workflow runs: it runs +`hack/lint-chart-versions.sh`, `go vet` and `go build` against +`installer/operator`, the generated-CRD/RBAC and DeepCopy drift checks +(`make manifests` / `make generate` followed by a `git diff`), the envtest +suite (`make test`), and `golangci-lint` (`make lint`). Because the drift +checks regenerate files in place and fail on any difference, a failure may +leave generated files modified in your working tree — review the diff, +which is exactly what CI is flagging, and commit it if it is a legitimate +regeneration. + +The CLI's Hugo renderer embeds theme files via `//go:embed` from +`client-programs/pkg/renderer/files/`, but that directory is `.gitignore`d +and populated at build time from the workshop base environment +(`workshop-images/base-environment/opt/eduk8s/etc/themes`). Without it +`go vet`/`build`/`test` fail with `pattern all:files/*: no matching files +found`. Both `make build-cli` and `make ci-cli` stage it automatically; if +you ever need it on its own, run: ``` -./client-programs/bin/educates-linux-amd64 create-cluster --version=latest +make stage-renderer-files ``` +The operator module is pinned to a specific Go version (see +`installer/operator/go.mod`). If you have more than one Go toolchain +installed, set `GOTOOLCHAIN` to that version (e.g. +`GOTOOLCHAIN=go1.26.0 make ci-operator`) or ensure the pinned toolchain is +the one on your `PATH`, otherwise some build steps may mix toolchains and +fail with a `compile: version "…" does not match go tool version "…"` +error. CI is unaffected because it provisions a single Go version via +`actions/setup-go`. + Cleaning up available storage space ----------------------------------- diff --git a/developer-docs/json-schemas.md b/developer-docs/json-schemas.md new file mode 100644 index 000000000..bd20558be --- /dev/null +++ b/developer-docs/json-schemas.md @@ -0,0 +1,72 @@ +CLI JSON Schemas +================ + +The `educates` CLI config kinds (`cli.educates.dev/v1alpha1`) each have a +JSON schema at +[client-programs/pkg/config/v1alpha1/schemas](../client-programs/pkg/config/v1alpha1/schemas). +The schemas are embedded in the CLI (`go:embed`) and drive command-time +validation, `local config set` path checks, and editor support. + +* `EducatesLocalConfig`, `EducatesGKEConfig`, `EducatesEKSConfig` and + `EducatesInlineConfig` are maintained by hand alongside their Go types. +* `EducatesConfig` is generated from the operator CRD OpenAPI schemas — + regenerate with `make generate-cli-schemas` (CI fails on drift). +* `EducatesAnyConfig` is a kind-discriminated umbrella (`oneOf` over the + five kinds) used only for filename-based editor matching (SchemaStore). + It is not embedded in the CLI. **When a new config kind ships, add its + `$ref` here.** + +Publishing +---------- + +The `publish-schemas` job in the release workflow deploys the schemas to +this repository's GitHub Pages site on every release tag, at paths +matching the `$id` baked into each schema: + +``` +https://schemas.educates.dev/cli/v1alpha1/.json +``` + +Forks deploy to `https://.github.io/educates-training-platform/...` +(no custom domain); the job is `continue-on-error` so forks that never +enabled Pages don't break their releases. + +One-time setup (upstream) +------------------------- + +1. Repository Settings → Pages → Source: **GitHub Actions**. +2. Repository Settings → Pages → Custom domain: `schemas.educates.dev` + (GitHub provisions the TLS certificate). +3. DNS: `CNAME schemas.educates.dev → educates.github.io.` + +Editor discovery +---------------- + +Two mechanisms: + +* **Modeline** — `educates local config init` writes a + `# yaml-language-server: $schema=…/EducatesLocalConfig.json` header, so + any editor with a YAML language server validates the file immediately. + Hand-written scenario-kind files can carry the same modeline with their + kind's URL. +* **SchemaStore** — filename-based matching for files without modelines. + Registration is a one-time PR against + [SchemaStore/schemastore](https://github.com/SchemaStore/schemastore) + adding the following to `src/api/json/catalog.json` (file the PR after + the first release publishes the schemas, so the URLs resolve): + +```json +{ + "name": "Educates CLI config", + "description": "Educates training platform CLI configuration (cli.educates.dev/v1alpha1)", + "fileMatch": ["**/educates/config.yaml", "*.educates.yaml"], + "url": "https://schemas.educates.dev/cli/v1alpha1/EducatesAnyConfig.json" +} +``` + +The `**/educates/config.yaml` pattern matches the CLI data home +(`$XDG_DATA_HOME/educates/config.yaml`); `*.educates.yaml` is the +documented naming convention for scenario-kind files kept in user +repositories. SchemaStore requires a positive and negative test file +under `src/test/` — use a minimal `EducatesLocalConfig` (apiVersion + +kind) as the positive case. diff --git a/developer-docs/release-procedures.md b/developer-docs/release-procedures.md index 5f361888f..6e458da93 100644 --- a/developer-docs/release-procedures.md +++ b/developer-docs/release-procedures.md @@ -24,6 +24,40 @@ Where changes are non trivial or need further explanation, the release notes sho Once a `release/*` branch has been cut, release notes and documentation updates for that release count as stabilization work and are made on the `release/*` branch. They reach `develop` through the back-merge when the release is finished. +Release Artifacts +----------------- + +A release build (triggered by pushing a version tag) produces: + +* Container images pushed to `ghcr.io//educates-*`: the platform component images (session-manager, training-portal, secrets-manager, etc.), the v4 installer operator (`educates-operator`), the workshop base and language environment images, the CLI container image (`educates-cli`) and the Docker Desktop extension. +* Two Helm charts pushed to `oci://ghcr.io//charts/`: `educates-installer` (the v4 operator chart users `helm install` or point ArgoCD/Flux at) and `educates-training-platform` (the standalone no-operator runtime chart). The chart tarballs are also attached to the GitHub release. +* The `educates` CLI binaries for Linux and macOS (amd64 and arm64), attached to the GitHub release together with a `checksums.txt`. +* A digest-pinned image list (`educates-images-.txt`, generated by [hack/generate-image-list.sh](../hack/generate-image-list.sh)) attached to the GitHub release: the platform images plus workshop base-environment at the released version, plus the upstream cluster-service images from the vendored charts. Air-gapped users mirror these name-preserving (skopeo/crane) into their internal registry and install with the registry overrides (`development.imageRegistry`, `EducatesClusterConfig.spec.imageRegistry.prefix`). +* The CLI config JSON schemas, deployed to GitHub Pages at `https://schemas.educates.dev/cli/v1alpha1/.json` (forks: `https://.github.io/educates-training-platform/...`; deploy is skipped gracefully where Pages isn't enabled). See [json-schemas.md](json-schemas.md) for the one-time Pages/DNS setup and SchemaStore registration. +* A GitHub release for the tag. Tags containing a `-` (alpha/beta/rc) are marked as pre-release. + +Release Versioning and Stamping +------------------------------- + +Releases are "tag and go": the committed tree always carries a development version (currently `4.0.0-alpha.1` for the charts, with the runtime `appVersion` pointing at the last released runtime) and is never bumped by a release commit. All released artifacts derive their version from the git tag at build time: + +* CLI binaries get the version and image registry via `-ldflags` (`main.projectVersion`, `main.imageRepository`). +* Container images are tagged by `docker/metadata-action` from the tag. +* Charts and everything embedding them are stamped by [hack/stamp-release-version.sh](../hack/stamp-release-version.sh), which the workflow runs in three places: before the operator image build (so the image embeds the runtime subchart tarballs at the released version), in the four CLI binary builds (`--charts-only`, stamping the chart embedded in the CLI), and in the `publish-charts` job. + +The stamp script rewrites, without ever committing anything back: + +* `version` AND `appVersion` to the tag across `educates-installer`, the `educates-training-platform` umbrella (including its `dependencies[].version` pins) and the five runtime subcharts. Stamping `appVersion` too is what makes a release self-consistent: the runtime images the charts reference are exactly the ones the same workflow run published. +* The `educates.dev/image-registry-host` / `-namespace` annotations on every chart that renders images, to `ghcr.io` / ``. These annotations are the publish-time default registry for all chart-rendered image references (see the decisions log entry "imageRegistry is a development override; publish-time defaults live in Chart.yaml annotations"). +* The five runtime subchart tarballs under `installer/operator/vendored-charts/`, repackaged at the stamped version, with the `//go:embed` filenames and `ChartVersion` constants in `embed.go` and the `SHA256SUMS` entries updated to match. The upstream cluster-service charts (cert-manager, Contour, external-dns, Kyverno) are NOT touched — those are only ever re-vendored deliberately via `make vendor-charts`. +* The CLI's embedded copy of the `educates-installer` chart, regenerated from the stamped chart. + +Worked example, upstream release: pushing tag `4.2.0` to `educates/educates-training-platform` publishes charts at version/appVersion `4.2.0` whose annotations resolve images to `ghcr.io/educates`, matching the images that same run pushed — for upstream the annotation rewrite is a no-op since the committed annotations already say `educates`. + +Worked example, fork release: pushing tag `0.0.1-alpha.1` to `/educates-training-platform` publishes charts at `0.0.1-alpha.1` whose annotations resolve to `ghcr.io/`, an operator image embedding subcharts stamped `0.0.1-alpha.1`, and CLI binaries defaulting to `ghcr.io/` — a fork release is fully self-contained and needs nothing published upstream. + +The stamping relies on the committed tree staying uniform (one chart version everywhere, identical annotations, `embed.go` aligned with the committed tarballs). This is enforced by [hack/lint-chart-versions.sh](../hack/lint-chart-versions.sh), run as the `chart-sync-lint` job in the installer operator CI workflow. If you need to inspect what a release would produce, run the stamp script locally (e.g. `./hack/stamp-release-version.sh 4.2.0 ghcr.io educates`) in a scratch clone or discard the resulting working-tree changes afterwards — its output must never be committed. + Triggering a Development Build ------------------------------ @@ -37,11 +71,7 @@ From the GitHub actions page select "Build and Publish Images" from the list of By default the build will only be run for the `linux/amd64` platform. The `linux/arm64` platform can instead be selected, or both, by selecting `linux/amd64,linux/arm64`. Note that any `linux/arm64` build will take significantly longer as the build is done under GitHub actions using the QEMU machine emulator and virtualizer. -Being a development build, all the container images, client programs and package bundles will be created, but no GitHub release will be created. To test the build, client programs and package resource manifests for installing the development version can be downloaded from the build artifacts of the GitHub actions workflow run. For a build of the `develop` branch, client programs can also be downloaded by using the command: - -``` -imgpkg pull -i ghcr.io/educates/educates-client-programs:develop -o /tmp/client-programs -``` +Being a development build, all the container images and client programs will be created, but no version stamping occurs, no Helm charts are published and no GitHub release is created. Development builds install via the CLI (which carries the operator chart embedded) or via `helm install` from a clone of the repository. The CLI binaries for all platforms can be downloaded from the build artifacts of the GitHub actions workflow run. For a build of the `develop` branch, the Linux binaries are also available from the `educates-cli` container image (e.g. `docker create` + `docker cp` from `ghcr.io/educates/educates-cli:develop`). A development build prior to a release would be done against the main Educates GitHub repository. If necessary a developer of some changes could also trigger such a build using GitHub actions from their fork of the Educates GitHub repository. In this case all container image references will resolve to images built and pushed to the developers GitHub container registry namespace and not that of the main Educates GitHub repository. For more complicated changes, it possibly should be a requirement that a developer do a full development build from their fork and test it before creating a pull request with their changes. @@ -50,7 +80,7 @@ Note that builds done in a fork will only include container images built for the Tagged Pre-release Versions --------------------------- -Development builds created by manually invoking the GitHub actions workflow are mutable and would be replaced by a subsequent development build. To generate a more official pre-release version for testing, create a version tag against the appropriate commit and push the tag to GitHub. Pushing the tag will automatically trigger the GitHub actions workflow to run. As with a development build all the container images, client programs and package bundles will be created. This time a GitHub release will also be created, marked as pre-release. +Development builds created by manually invoking the GitHub actions workflow are mutable and would be replaced by a subsequent development build. To generate a more official pre-release version for testing (alpha, beta, or release candidate), create a version tag against the appropriate commit and push the tag to GitHub. Pushing the tag will automatically trigger the GitHub actions workflow to run. A pre-release tag produces the full set of release artifacts described above — including the OCI-published Helm charts — with the GitHub release marked as pre-release. The format of the tags for pre-release builds are: @@ -74,7 +104,7 @@ git push origin 4.0.0-rc.1 Once pushed to the canonical repo, a version tag is immutable. The tag ruleset blocks updates and deletions, so a tag cannot be moved or removed afterwards without bypass. If a pre-release build turns out to be broken, move on to the next pre-release number rather than attempting to re-tag. -Version tags can also be created in a fork, in which case the GitHub release will be added against the fork and not the main GitHub repository. Because the same tag might be used in the main GitHub repository, which would be propagated to the fork when the repositories are synchronized, use of these tags is discouraged in forks except for testing release procedures. If done for this purpose, it is suggested that a tag of the form `0.0.1-???.N` be used, and that after testing both the tag and GitHub release be deleted from the fork once no longer required, so that the same tag can be used again in such future testing. +Version tags can also be created in a fork, in which case the GitHub release will be added against the fork and not the main GitHub repository. Because the same tag might be used in the main GitHub repository, which would be propagated to the fork when the repositories are synchronized, use of these tags is discouraged in forks except for testing release procedures. If done for this purpose, it is suggested that a tag of the form `0.0.1-???.N` be used, and that after testing both the tag and GitHub release be deleted from the fork once no longer required, so that the same tag can be used again in such future testing. Note that OCI chart versions and image tags pushed to the fork's `ghcr.io` namespace by the test release should be deleted as well. Cutting a Release Branch ------------------------ @@ -152,10 +182,19 @@ gh pr create --base develop --head merge/4.0.0-to-develop --title "Back-merge 4. git push origin --delete release/4.0.0 ``` -The format of the tag for a final release is `X.Y.Z`, with no suffix. `main` only ever carries final release tags. Pushing the tag triggers the GitHub actions workflow, which will create all the container images, client programs and package bundles, and a GitHub release not marked as pre-release. +The format of the tag for a final release is `X.Y.Z`, with no suffix. `main` only ever carries final release tags. Pushing the tag triggers the GitHub actions workflow, which produces the full set of release artifacts described above, and a GitHub release not marked as pre-release. The back-merge in step 3 ensures the release's stabilization fixes, and the release/version-bump commits, are not lost, and that `develop` reflects exactly what shipped. The release branch is ephemeral: once merged and tagged it has done its job, and the permanent record is the tag plus the merge commits, not the branch. Deleting it (step 4) is a deliberate, explicit step; keep it on the release checklist so stale `release/*` branches don't accumulate. +Once the workflow completes, verify the release is installable from the published artifacts alone: + +``` +helm pull oci://ghcr.io/educates/charts/educates-installer --version X.Y.Z +helm pull oci://ghcr.io/educates/charts/educates-training-platform --version X.Y.Z +``` + +and confirm a cluster install from the published chart reaches `Ready` (`helm install educates-installer oci://ghcr.io/educates/charts/educates-installer --version X.Y.Z --namespace educates-installer --create-namespace`, then apply the platform CRs), or use the released CLI (`educates admin platform deploy`). + As with pre-release tags, a pushed final release tag is immutable on the canonical repo and cannot be moved or removed. Creation of a final release in a fork should only be done if testing the release process. In this case the version tag `0.0.1` should be used and the tag and GitHub release should be deleted from the fork once the test has been completed. Support Branches and Patch Releases diff --git a/docs/architecture/decisions.md b/docs/architecture/decisions.md new file mode 100644 index 000000000..7fa2fded1 --- /dev/null +++ b/docs/architecture/decisions.md @@ -0,0 +1,1374 @@ +# Architectural Decisions Log + +> One paragraph per decision. Append-only — when a decision is reversed, +> add a new entry and link back to the superseded one. Don't rewrite +> history. + +Format: `### ` — date — what was decided, why. + +--- + +### Helm chart apiVersion v2 + +**Date:** 2026-04-27. +**Decision:** All Helm charts produced for the v4 installer use +`apiVersion: v2` in `Chart.yaml`. **Why:** v2 is required for +`dependencies`, `kubeVersion` enforcement, and library-chart support, all +of which we use or will use. v1 is legacy. + +### Kubernetes version floor: 1.31 + +**Date:** 2026-04-27. +**Decision:** All v4 charts declare `kubeVersion: ">=1.31.0-0"`. +**Why:** Educates v4 will not support Kubernetes <1.31. The chart-level +constraint is advisory (Helm warns rather than fails on mismatch in some +versions), but it documents the contract and lets `helm install` reject +obvious mismatches. Project-level support is the source of truth; this is +the chart-level mirror of it. + +### Single version across umbrella and subcharts + +**Date:** 2026-04-27. +**Decision:** The `educates-training-platform` umbrella chart and its +three subcharts (`secrets-manager`, `lookup-service`, `session-manager`) +all carry the same `version` and `appVersion`, bumped together on every +release. **Why:** They ship as a set. Independent versioning would imply +the subcharts are reusable in other contexts, which they are not — they +are tightly coupled to a specific Educates runtime build. A single +version simplifies release tooling and makes "which subchart version goes +with which umbrella version" a non-question. + +### Chart version tracks appVersion + +**Date:** 2026-04-27. +**Decision:** `version` and `appVersion` are kept in lockstep on these +charts. **Why:** Same reasoning as the previous entry — these charts are +not reusable artifacts whose chart packaging would evolve independently +of the application they install. Decoupling the two adds bookkeeping +without buying anything. + +### Umbrella chart structure: physical subcharts under `charts/` + +**Date:** 2026-04-27. +**Decision:** The `educates-training-platform` umbrella chart embeds its +three subcharts as physical directories under `charts/` *and* declares +them in `Chart.yaml` `dependencies` (with `condition: .enabled`). +**Why:** Physical subcharts make `helm template` and `helm install` work +without a `helm dependency update` step or a Chart.lock. Declaring them +in `dependencies` is what lets the `condition` flag toggle them on and +off cleanly. Combining both gives the local-repo ergonomics of physical +charts with the gating ergonomics of declared dependencies. + +### Subchart toggling: per-subchart `enabled` flag + +**Date:** 2026-04-27. +**Decision:** Each subchart can be independently enabled or disabled via +`.enabled` in the umbrella values. All three default to +`true`. **Why:** The pre-phase plan calls for subcharts to be enabled or +disabled independently. The flag is the standard Helm pattern. All three +default on because the typical install is the full runtime; users who +want a subset (e.g., no lookup-service for a single-cluster install) opt +out explicitly. + +### Subcharts do not vendor upstream charts + +**Date:** 2026-04-27. +**Decision:** The Educates runtime subcharts (`secrets-manager`, +`lookup-service`, `session-manager`) do not depend on any upstream Helm +charts and therefore vendor nothing. **Why:** These subcharts package +Educates' own components only. Cluster services like cert-manager, +Contour, Kyverno, external-dns are installed by the operator (in Managed +mode), not by the runtime chart. Open item #2 in the development plan +(vendor upstream charts at build time) applies to those operator-driven +installs, not to these subcharts. + +### Runtime chart values shape is operator-driven, not v3-driven *(superseded 2026-04-30 — see "session-manager values are typed and standalone-friendly")* + +**Date:** 2026-04-27. +**Decision:** The values shape of the `educates-training-platform` chart +and its subcharts is designed for what the v4 operator will pass in +(derived from component CRs and `EducatesClusterConfig.status`), not as a +1:1 mirror of the v3 ytt schema. **Why:** The v3 schema is shaped by the +single-blob installer config it was fed from. The v4 operator passes +narrowly scoped values per component, derived from per-component CRs. +Mirroring v3 would carry forward structural choices that no longer fit. +Translation choices will be flagged as they're made; the migration tool +(`educates migrate-config`) bridges the user-facing v3 config to v4 CR +YAML, not to chart values. + +### CRDs shipped in each subchart's `crds/` directory *(supersedes earlier `templates/`-based decision)* + +**Date:** 2026-04-28. +**Decision:** CRDs in each runtime subchart are placed in the +subchart's `crds/` directory (Helm's special location) as pure YAML — +no Helm templating, no annotations. They are installed on first +`helm install`, left untouched on `helm upgrade`, and not deleted on +`helm uninstall`. +**Why this supersedes the earlier `templates/` decision:** +- Helm cannot install CRs and their CRDs in a single release when the + CRDs are in `templates/`: Helm needs the CRD's REST mapping to exist + in the API server *while* it builds the manifest, but the CRD won't + be applied until the manifest is built. Confirmed empirically when + scenario 01 failed with + `resource mapping not found for ... SecretInjector ... ensure CRDs + are installed first`. The runtime chart contains both the + `secrets.educates.dev` CRDs *and* SecretInjector/SecretCopier custom + resources, so this is unavoidable with `templates/`. +- Workarounds exist (pre-install hooks on each CRD; a dedicated CRDs + subchart installed first) but each adds chart complexity and changes + the upgrade story in ways we'd rather not commit to. +- The original concern that drove the `templates/` choice was + upgradability during v1alpha1 schema churn. In practice the Educates + internal CRDs (training, secrets, lookup) have been stable through v3 + and are not expected to change in v4 except in a coordinated way that + also requires a runtime change. The operator CRDs that *will* see + more churn (EducatesClusterConfig, SecretsManager, LookupService, + SessionManager) are managed by the operator chart, not this runtime + chart, and those will be handled separately. +**Consequences to be aware of:** +- A schema change in any of these CRDs requires users to apply the new + CRD out-of-band before `helm upgrade` (or use `helm install --force`, + which has its own caveats). This is the standard operational story + for CRDs in Helm and is documented across the Helm ecosystem. +- `helm uninstall` leaves CRDs in place (which is actually the same + behaviour we wanted from the previous `keep` annotation, just via a + different mechanism). +- CRD files cannot use Helm template directives — they are pure YAML. + Chart labels are not added to CRDs as a result; this is consistent + with how most Helm charts ship CRDs. +**Reconsider trigger:** If we end up needing per-release CRD updates +during v4 development (e.g., we change a validation rule and want +`helm upgrade` to roll it out), revisit and consider a dedicated +`crds` subchart pattern (kube-prometheus-stack-style) that explicitly +manages the CRD lifecycle. + +### Drop the v3 `educates-config` blob from the secrets-manager subchart + +**Date:** 2026-04-27. +**Decision:** The v4 `secrets-manager` subchart does not create or mount +the `educates-config` Secret that the v3 installer used. **Why:** The +secrets-manager Python operator only reads `operator.namespace` from +that config blob, and even that value is overridden at runtime by +`/var/run/secrets/kubernetes.io/serviceaccount/namespace`. The mount is +dead weight for this component. The session-manager subchart's +configuration story (which is genuinely larger) is handled separately in +its own subchart values. + +### Drop PodSecurityPolicy bindings; keep SCC for now + +**Date:** 2026-04-27. +**Decision:** The v4 runtime subcharts do not include +PodSecurityPolicy-related ClusterRoleBindings. SCC +(SecurityContextConstraints) ClusterRoleBindings remain available, +gated by a chart value, defaulting off. **Why:** PodSecurityPolicy was +removed from Kubernetes in 1.25; the v4 floor is 1.31, so PSP code is +unreachable. SCC is OpenShift-specific and is being kept available +because the OpenShift Inline-mode story (Scenario E in the CRD draft) +hasn't been fully designed yet. Once that scenario is implemented we +will revisit whether SCC bindings belong in the runtime subcharts at +all, or are better managed by the cluster admin out-of-band. + +### `remote-access` is a separate, toggleable subchart + +**Date:** 2026-04-27. +**Decision:** The `remote-access` ServiceAccount, ClusterRole, +ClusterRoleBinding, and long-lived service-account-token Secret are +packaged as their own subchart (`remote-access`) under the umbrella, +gated by `remote-access.enabled`, defaulted to `true`. The lookup-service +subchart conditionally mounts the `remote-access-token` Secret at +`/opt/cluster-access-token` only when `remote-access.enabled=true`. +**Why:** `remote-access` grants read access to `training.educates.dev` +resources for external CLI clients (e.g., `educates` CLI used +cross-cluster). Use cases vary: some installs want it without +lookup-service (session-manager only, with external CLI access), some +want lookup-service federation without remote CLI access, some want +both. Bundling it inside lookup-service forced installs to choose +between two unrelated capabilities. A separate subchart keeps the +permission grant explicit and independently toggleable. **How to apply:** +The lookup-service Deployment uses `/opt/cluster-access-token` only when +serving a "local" ClusterConfig (no kubeconfig secretRef), per +`lookup-service/service/handlers/clusters.py`. When `remote-access` is +disabled, lookup-service still works for any ClusterConfig with an +explicit kubeconfig secretRef. This runtime nuance is documented in +chart values, not enforced at chart install time. + +### session-manager hard-couples to secrets-manager; secrets-manager is standalone + +**Date:** 2026-04-27. +**Decision:** The `session-manager` subchart renders SecretCopier and +SecretInjector resources unconditionally (no `secretsManagerIntegration` +toggle). Installing session-manager therefore requires the +`secrets.educates.dev` CRDs to be present, which means `secrets-manager` +must be installed alongside it. The `secrets-manager` subchart, by +contrast, is fully standalone — it can be installed on its own without +session-manager. **Why:** session-manager's runtime depends on the +secret-propagation primitives (image-pull-secrets, registry credentials, +ingress TLS replication into operator namespace) that secrets-manager +provides. Splitting them via a chart-level toggle would only paper over +a real runtime dependency. The reverse is not true — secrets-manager is +useful by itself (e.g., for cross-namespace secret propagation in a +cluster that hosts other Educates-adjacent tooling), so it stays +standalone. + +### Runtime chart never creates TLS or CA Secrets + +**Date:** 2026-04-27. +**Decision:** The `educates-training-platform` chart and its subcharts +do not create wildcard TLS Secrets or CA Secrets from inline value +fields. They only reference such Secrets by name (e.g., +`ingress.tls.secretName`, `caTrust.secretName`). **Why:** v3 supported +inline `tls.crt`/`tls.key` and `ca.crt` value fields and synthesised the +backing Secrets at install time. That feature is being retired in v4 — +TLS and CA material are managed by the v4 operator (in Managed mode) or +declared by the user as pre-existing Secrets (in Inline mode), per +`EducatesClusterConfig`. The runtime chart only consumes the resulting +Secrets by name, never materialises them. Standalone chart users who +have raw cert/key material must create the Secret themselves before +`helm install`. + +### Bundled Kyverno policies: two-path layout (`clusterPolicies` + `workshopPolicies`) + +**Date:** 2026-04-29 (revised same day after closer reading of v3). +**Decision:** The session-manager subchart ships v3-vendored Kyverno +policies on **two independent paths**, mirroring v3's split between +`01-clusterpolicies.yaml` and `06-secrets.yaml`: + +- **`bundledKyvernoPolicies.clusterPolicies`** (default `true`) — + cluster-wide ClusterPolicy resources installed directly by the chart + from `files/kyverno-policies/cluster-policies/{baseline,restricted}/`. + Both Pod Security Standards profiles are installed unconditionally + when this is on; workshops do not pick a profile, so all must be + present. Default action is `Audit` from the upstream YAMLs. +- **`bundledKyvernoPolicies.workshopPolicies`** (default `true`) — + operational best-practices + the Educates-internal + `require-ingress-session-name`, concatenated into the + `kyverno-policies.yaml` key of the `educates-config` Secret. + session-manager reads the stream and clones each rule per workshop + environment with a namespace selector added. + +User extras live in `.Values.additionalKyvernoPolicies` (a map with +two list-valued keys, `clusterPolicies` and `workshopPolicies`, +mirroring the `bundledKyvernoPolicies` toggles). The chart applies +`additionalKyvernoPolicies.clusterPolicies` cluster-wide alongside +the bundled set, and appends +`additionalKyvernoPolicies.workshopPolicies` to the workshop-policies +Secret feed. This is a **net-new feature vs. v3** — v3 had no +operator-managed path for users to install additional Kyverno +ClusterPolicies; admins applied them out-of-band after install. +Bringing them into the chart values keeps the platform configuration +in one place and lets users version and review their policy +extensions alongside everything else. + +**Why the split, and why not collapse them:** the first iteration of +this decision used a single `profile` selector + `operationalPolicies` +toggle, all bundling into the Secret feed. That was wrong: the v3 +baseline+restricted policies are applied **cluster-wide** at install +time (by `01-clusterpolicies.yaml`), not per-workshop. Workshops can't +choose a profile — they can only exclude individual rules from the +per-environment feed. Replicating v3's split is the only way to preserve +both behaviours. +**Reconsider trigger:** if the policy bundle starts churning faster +than the runtime, or we add other operational policy sources (e.g., +admission-controller policies, Trivy admission rules) and the bundle +becomes operationally distinct from session-manager, split it into a +dedicated subchart at that point. Likely natural alongside Phase 4 +operator work, when the runtime may also gain the ability to read +policies from labelled Secrets — that change would let a sibling +subchart populate its own Secrets without the Helm cross-subchart +composition problem. + +### Image references exposed as repository + tag + +**Date:** 2026-04-27. +**Decision:** Every container image reference in the runtime chart is +exposed in values as `image.repository` plus `image.tag` (or an +equivalent splittable shape). **Why:** This is the shape `helm dt +wrap`/`unwrap` and similar relocation tools expect. Locking the shape now +keeps the air-gapped path open without committing to a specific +relocation tool (open item #4). No digest pinning at chart level for +v0.1.0; pinning happens via published values files at release time. + +### session-manager values are typed and standalone-friendly *(supersedes "Runtime chart values shape is operator-driven, not v3-driven")* + +**Date:** 2026-04-30. +**Decision:** The `session-manager` subchart exposes its inputs as a +typed, schema-validated values surface (see +`docs/architecture/session-manager-chart-values.yaml` and the +matching JSON schema). The well-known runtime fields — `clusterIngress`, +`clusterSecurity`, `workshopSecurity`, `imageRegistry`, `imageVersions`, +`trainingPortal`, `sessionCookies`, `clusterStorage`, `clusterRuntime`, +`clusterNetwork`, `dockerDaemon`, `workshopAnalytics`, and +`websiteStyling` — are top-level, typed values. The opaque `config:` +map remains as an escape hatch deep-merged on top of the typed-derived +runtime config; new fields land there first and get promoted to typed +values in a subsequent release. SecretCopiers for ingress TLS/CA are +auto-derived from `clusterIngress.{tls,ca}CertificateRef.namespace` +when those refs target a foreign namespace; the explicit +`secretPropagation.upstream.ingressTLS/ingressCA` knobs from the +earlier shape are gone. + +**Why this supersedes the earlier decision:** The earlier framing was +"the operator passes typed values, so the chart just needs to accept +what the operator emits — don't mirror v3." That gave us a chart with +one well-known runtime field (`clusterIngress`) typed and the rest +flat-out opaque under `config:`. The development-plan note for the +runtime chart explicitly calls it "what the Educates project will +publish ongoing as the canonical Helm install for the runtime," +including for users who don't want the operator. Standalone users +were therefore expected to write opaque YAML against the v3 schema +from memory, *and* duplicate the same TLS/CA inputs in two different +forms (`config.clusterIngress.tlsCertificateRef` and +`secretPropagation.upstream.ingressTLS`). Both audiences — the +operator and the standalone user — are better served by a single +typed surface. + +The chart-side translation also lets us decouple presentation casing +from runtime casing: chart values use PascalCase enums (`Kyverno`, +`PodSecurityStandards`, `OpenShiftSCC`, `None`) per Kubernetes +convention, while the runtime config blob continues to use lowercase, +unchanged. No runtime change was required. + +**Consequences to be aware of:** +- The chart fails fast at template time if `clusterIngress.domain` is + empty, instead of silently falling through to the runtime's + `educates-local-dev.test` default. This is a deliberate change — the + default existed for the runtime's own development; production + installs should never hit it. +- `additionalProperties: false` on every typed block in the schema + catches typos, but means new runtime fields land in `config:` until + promoted. Plan for cross-version drift: runtime adds a field → + release N exposes it via `config:` → release N+1 promotes it to a + typed key. +- Helm injects `enabled` and `global` into subchart values; both are + whitelisted in the schema. +- The `imagePullSecrets` schema item is `[{name: ...}]` (PodSpec + shape), not `[string]` — it flows directly into the Deployment's + PodSpec, so the standard k8s shape applies. + +**Reconsider trigger:** if the operator ever needs values the +standalone user wouldn't (or vice versa) and the typed surface starts +forking by audience, split presentation: keep the typed shape as the +canonical, expose a thinner operator-only surface that derives from +it. Not anticipated for v4. + +### Image tags derive from `Chart.appVersion`; `imageVersions` defaults via helper, merged by name + +**Date:** 2026-04-30. +**Decision:** The bundled Educates runtime version is `Chart.appVersion` +in `Chart.yaml` — used as the default tag for the chart's own pods +(session-manager, pause-container) AND for the Educates-published +entries in the chart's default `imageVersions` set. The default +`imageVersions` list (mirroring v3's +`carvel-packages/installer/config/images.yaml`) is built in the +`session-manager.imageVersions` template helper, with Educates-published +tags derived from `Chart.appVersion` and upstream pins +(`docker-in-docker`, `loftsh-*`, `debian-base-image`) hard-coded to +specific tags. User-supplied entries in `.Values.imageVersions` are +merged BY NAME — an override replaces just the matching default, other +defaults pass through, names not in the default list are appended. +The `Chart.appVersion` field is currently `"3.7.1"` (the v3 runtime we +ship against) while `Chart.version` is `4.0.0-alpha.1` (the chart +package); they may diverge if a chart-only patch ships, but normally +move in lock-step at release time. + +**Why `Chart.appVersion`:** It's the standard Helm pattern — `appVersion` +denotes the bundled application's version, `version` denotes the chart +package. Using `appVersion` for runtime tags means a release process +that bumps `Chart.appVersion` automatically updates every runtime +image reference; no parallel knob to keep in sync. Tying runtime tags +to `Chart.version` instead, or auto-injecting it without distinction, +silently broke session-manager's spawned children (training-portal, +base-environment, etc.) with `ErrImagePull` against non-existent +`4.0.0-alpha.1` images. + +**Why `imageRegistry` is the prefix knob:** A chart user working +against a fork or a locally-built registry should be able to redirect +every Educates-image reference with one knob. `imageRegistry.host` / +`.namespace` (defaulting to `ghcr.io` / `educates`) compose the prefix +for: the chart-pod (when `image.repository` is empty), the pause image +(when `imagePrePuller.pauseImage.repository` is empty), and the Educates- +published entries in the `imageVersions` helper. Upstream pins +(`docker-in-docker`, `loftsh-*`, `debian-base-image`) are NOT +relocated by `imageRegistry` — those are public upstream images that +mirror under different names; relocate them via per-entry +`imageVersions` overrides instead. + +**Why a helper, not a populated `values.yaml` default:** Chart users +typically don't need to see the full image inventory in their values +file — they just want overrides for the entries they're changing +(airgap, JDK variant, mirror). Per-key merge means a single override +doesn't require copying the whole list. The helper is the documented +inventory; the values file stays focused on the overrides. + +**Why per-key merge instead of Helm's default list-replacement:** v3's +UX required overriding the entire `imageVersions` list to change one +entry. Per-key merge in the helper is strictly better — chart users +override only what they need and inherit the rest, including any new +entries the chart adds in future releases. + +**Consequences to be aware of:** +- A release that bumps the runtime updates `Chart.appVersion` in the + umbrella chart and the four subchart `Chart.yaml`s. Standard Helm + release process; no parallel values-file edit needed. +- The full default image inventory lives in + `templates/_helpers.tpl::session-manager.imageVersions` — keep this + in sync with `session-manager/handlers/operator_config.py`'s + `image_reference()` short-name list when adding new runtime images. +- A user override with a `name` not in the helper's defaults is + appended (forward-compat). A user override matching a default `name` + replaces just that entry's `image`. +- `imageRegistry.host` / `.namespace` affect ONLY images that fall + through to the runtime's `image_reference()` — i.e., images NOT in + the merged `imageVersions` list. For airgap relocation of the + helper-defaulted set, override the `image:` field of the relevant + entries via `.Values.imageVersions`. + +**Reconsider trigger:** if the helper-default list grows large enough +that surfacing it in `values.yaml` is more useful than the per-key +override UX, revisit. Or if `Chart.appVersion` and the runtime version +need to diverge (a chart that bundles multiple runtime versions for +selection at install time), promote the runtime version to a typed +value at that point. + +### Cross-cutting values promoted to umbrella `global:`; subchart-local fall-back + +**Date:** 2026-04-30. +**Decision:** `imageRegistry`, `clusterIngress`, and `clusterSecurity` +are deployment-scope values that should be set once and consumed +consistently across every subchart that renders affected resources. They +move to the umbrella's `global:` block, propagated by Helm to every +subchart as `.Values.global.`. Each subchart retains a local block +of the same name with sensible defaults (e.g., `imageRegistry.host: +ghcr.io`); helpers deep-merge the umbrella global over the subchart +local, with globals winning per-leaf where set. Subcharts remain +independently installable: a standalone `helm install lookup-service` +just sets the values at the top level instead of under `global:`. + +**Why globals over per-subchart duplication:** Under the umbrella, a +single `global.clusterSecurity.policyEngine: OpenShiftSCC` now triggers +SCC ClusterRoleBindings in both session-manager and secrets-manager. +A single `global.imageRegistry: { host: my-fork, namespace: org }` +redirects every chart-pod, pause image, and runtime-children entry. A +single `global.clusterIngress.{tls,ca}CertificateRef` drives both the +session-manager auto-derived SecretCopier and (in step 2) the lookup- +service Ingress + chart-rendered ca-trust-store init container in both +subcharts. Without globals each user would have to set the same value in +multiple subchart blocks and keep them in sync. + +**Why retain subchart locals (not globals-only):** Helm subcharts are +independently installable by design. A standalone `helm install +session-manager` user shouldn't have to know the umbrella's `global:` +convention; they should write `clusterIngress: { domain: ... }` at the +top level of their values file like any other chart. Globals are a +multiplier when the umbrella exists; subchart locals are the default +shape when it doesn't. + +**Why deep-merge with globals winning:** The merge runs +`mergeOverwrite local global`: each leaf in the global block replaces +the matching leaf in the subchart local; unset globals leave subchart +locals intact. So a user can set `global.imageRegistry.host: my-fork` +without also having to set `namespace`; the subchart-local `namespace: +educates` passes through. Pathological case: an explicit empty string +in a global key (e.g., `global.imageRegistry.host: ""`) overrides the +local — document this as "explicit unset is still an override." + +**Validation:** subchart schemas can no longer require keys that may +come from globals. The session-manager schema drops `clusterIngress` and +`clusterSecurity` from its top-level `required` list; helpers do the +post-merge `fail` instead. Subchart-local `clusterIngress.domain`'s +`minLength: 1` constraint is also relaxed for the same reason. The +helper enforces non-empty resolved values at template time. + +**Consequences to be aware of:** +- Helm's globals propagation only works under an umbrella chart. A + user installing a subchart standalone gets the local defaults; their + values file uses top-level keys, not `global:`. +- The local fall-back means there are two valid paths to set the same + thing. Document that umbrella users should prefer `global:` and only + put cross-cutting values in subchart blocks for per-subchart + overrides (atypical). +- Helpers across subcharts duplicate the merge logic (~10 lines each). + Acceptable at this scale; revisit a library chart if duplication + exceeds three places of substantial helper logic. + +**Reconsider trigger:** if the umbrella is dropped (operator builds +each component from individual chart installs without the umbrella +wrapper), or if the duplicated helpers grow significantly, extract a +shared library chart that all subcharts depend on. + +### node-ca-injector is its own subchart, not a flag inside session-manager + +**Date:** 2026-04-30. +**Decision:** The cluster-node CA injection feature lives in its own +subchart (`installer/charts/educates-training-platform/charts/node-ca-injector/`), +sibling to session-manager / lookup-service / secrets-manager / remote- +access. The toggle is the umbrella's `node-ca-injector.enabled: false` +(default off), via Helm's standard subchart-condition mechanism. The +subchart consumes `global.clusterIngress.caCertificateRef` (with +subchart-local fall-back for standalone) and bails fast at template +time if the resolved CA ref is empty. The earlier-considered +`session-manager.clusterIngress.caNodeInjector.enabled` field is +removed entirely from the values surface. + +**Why a separate subchart:** + +- *Source layout match.* `node-ca-injector/` already exists as a + top-level Go module with its own Dockerfile in this repo. The chart + layout now mirrors the source. +- *Lifecycle independence.* It's a privileged per-node DaemonSet plus + a controller Deployment, with its own image, RBAC, and operational + story. Nothing about it logically belongs to session-manager's + release. +- *Mirrors the remote-access precedent.* remote-access is also a + small, optional, single-purpose subchart with its own toggle. + node-ca-injector fits the same shape exactly. +- *Cleaner toggle UX.* `node-ca-injector.enabled: true` at the + umbrella is more discoverable than a nested + `global.clusterIngress.caNodeInjector.enabled: true`. +- *Standalone install.* Someone running v3 elsewhere who wants + containerd-level CA trust on a new cluster can `helm install + node-ca-injector` alone with just a CA Secret reference — they don't + need the rest of the runtime. + +**What it renders (mirroring v3's `07-node-ca-injector.yaml`):** + +- `ServiceAccount` `node-ca-injector` in the release namespace. +- `ClusterRole`/`ClusterRoleBinding` `educates-node-ca-injector` + granting `get/list/watch` on Ingresses (controller watches them to + derive the registry-host list). +- `Role`/`RoleBinding` `node-ca-injector` granting full ConfigMap + management in the release namespace (controller writes the + `educates-registry-hosts` ConfigMap; DaemonSet pods mount it). +- `Deployment` `node-ca-injector-controller` (1 replica, runs + `controller` subcommand). +- `DaemonSet` `node-ca-injector` (privileged, runs `sync` subcommand, + mounts the CA Secret + the hosts ConfigMap + hostPath + `/etc/containerd/certs.d`). +- `SecretCopier` auto-derived when the CA ref's namespace is foreign. + +**Relationship to the per-pod ca-trust-store init container:** these +are two complementary mechanisms. + +- *Per-pod init container* (in session-manager and lookup-service + Deployments) writes the CA into `/etc/pki/ca-trust` *inside the + pod*. Targets specific pods that need to verify TLS against the + private CA from inside their own process tree. +- *node-ca-injector* writes containerd registry-CA configuration to + `/etc/containerd/certs.d` *on the host node*. Targets the + container runtime itself — image pulls from registries fronted by + the private CA, including pulls performed by pods we don't render + ourselves (third-party operators, kubelet, docker-in-docker workers + inside workshop sessions). + +Both can be enabled independently; both consume the same +`global.clusterIngress.caCertificateRef`. + +**Why disabled by default:** the DaemonSet runs privileged on every +node and writes host filesystem state (`/etc/containerd/certs.d`). +Defaulting it to off matches v3's behaviour and avoids surprising +chart users who don't have a private CA. + +### Schema validation split: umbrella validates the umbrella + globals; subcharts validate themselves + +**Date:** 2026-05-03. +**Decision:** The umbrella chart has its own `values.schema.json` +focused on validating the cross-cutting `global:` block and the +top-level shape (subchart toggles, no unknown keys). It does NOT +re-validate each subchart's full values surface — every subchart +ships its own `values.schema.json` and Helm validates each +`.Values.` block against the matching subchart schema +independently. Subchart blocks at the umbrella level are typed as +opaque `{ "type": "object" }`. + +**Why split this way:** + +- *No duplication.* Subchart shapes already live in subchart schemas; + copying them into the umbrella would mean two places to update on + every change. +- *Catches the typos that fall through everywhere else.* Subchart + schemas treat `global` as opaque (correctly — they shouldn't + dictate the umbrella's contract). That meant a typo like + `global.clusterSecuirty.policyEngine: Kyverno` produced no error; + every subchart fell back to its local `clusterSecurity` defaults + and the user's intended override was silently dropped. The + umbrella schema closes this gap: `additionalProperties: false` on + every level of `global:` rejects the misspelling at template time. +- *Catches unknown top-level keys.* Same `additionalProperties: + false` discipline at the umbrella root catches a user who + accidentally writes e.g. `sesion-manager:` (typo in subchart name) + — Helm would otherwise treat it as inert top-level data. + +**Verified:** all three classes of typo trigger a schema error at +`helm template` time: +- misspelled global key (e.g., `global.clusterSecuirty`), +- misspelled global nested field (e.g., + `global.imageRegistry.namespece`), +- unknown top-level key (e.g., `sesion-manager`). + +**Reconsider trigger:** if global shapes start churning faster than +the chart release cadence, or if cross-subchart validation invariants +emerge that no single schema can express (e.g., "if X global is set +then Y subchart toggle must be true"), revisit. Helm doesn't natively +support cross-chart schema invariants — those would need a CI lint +rather than a schema. + +### `imageRegistry` is a development override; publish-time defaults live in Chart.yaml annotations + +**Date:** 2026-05-05. +**Decision:** The user-facing image-registry knob is renamed to +`development.imageRegistry` (subchart-local) and +`global.development.imageRegistry` (umbrella). It is **empty by default** +and intended to be left empty in normal use. The publish-time default +registry — what consumers of an upstream/fork chart see for chart-pod ++ runtime-children image refs — is sourced from Chart.yaml annotations: + +```yaml +annotations: + educates.dev/image-registry-host: "ghcr.io" + educates.dev/image-registry-namespace: "educates" +``` + +The release workflow updates these annotations per fork (one `yq -i` +call per Chart.yaml). Each subchart's helper resolves the effective +prefix as: `development.imageRegistry` (user override) → +`global.development.imageRegistry` (umbrella global) → Chart.yaml +annotation → `fail`. + +The `development.imageRegistry` knob has TWO simultaneous effects when +set: + +1. **Chart-rendered + runtime-spawned image refs** resolve against + `{host}/{namespace}` instead of the annotation defaults (chart pod, + pause container, every Educates-published entry in the + `imageVersions` helper). +2. **The runtime config blob's `imageRegistry` field** is emitted with + the same `{host}/{namespace}`. The runtime exports + `IMAGE_REPOSITORY={host}/{namespace}` into workshop sessions, so + workshop YAMLs containing `$(image_repository)/:` + placeholders resolve there. + +When `development.imageRegistry` is empty (normal use), effect (2) +emits an empty `imageRegistry` block into the runtime config — the +runtime falls back to `registry.default.svc.cluster.local` +(`session-manager/handlers/operator_config.py:35`), the in-cluster +Service routing to the local development registry. Released workshops +have fully-qualified content image refs in their YAMLs without +`$(image_repository)` placeholders (the workshop's own publish workflow +substitutes them at workshop-publish time), so the in-cluster fallback +only matters for the local-dev workflow. + +**Why two helpers, not one:** + +- `resolvedImageRegistry` (with annotation fallback) → used to compose + chart-rendered refs. Always returns a populated value in normal use + (annotation provides it). +- `resolvedDevelopmentImageRegistry` (NO annotation fallback, user/global + only) → used to compose the runtime config blob's `imageRegistry` + field. Returns empty in normal use, populated when the user overrides. + +This split is the whole point: chart pods need refs that work without +user input (annotations supply them); the runtime config's +`imageRegistry` field deliberately stays empty in normal use to avoid +silently breaking the local-dev workflow when a user later runs +`educates publish-workshop` against a "normal" install. + +**Why this supersedes the earlier `imageRegistry` decision:** + +The previous shape (`imageRegistry: { host: "ghcr.io", namespace: +"educates" }` populated in subchart `values.yaml`) tangled three +concerns: + +1. Where chart pods + runtime children pull their images from (a + publish-time concern — depends on which fork shipped the chart). +2. The `IMAGE_REPOSITORY` env var workshops see (a per-install concern + — should be empty for the in-cluster fallback in normal use). +3. The user-facing override knob (a relocation/dev concern). + +Conflating (1) and (2) silently broke the dev workflow on installs +that left the populated default in place — a workshop with a +`$(image_repository)` placeholder would resolve to `ghcr.io/educates/...`, +not `localhost:5001`, and the pull would fail. v3 avoided this with +its `imageRegistry: ""` default by-design schema (build-time refs were +baked into the OCI bundle separately). The new split restores that +separation: annotations carry (1), `development.imageRegistry` carries +(3), the runtime config carries (2) only when (3) is set. + +**Why the `development:` namespace:** + +Renaming from `imageRegistry` to `development.imageRegistry` makes the +intent explicit. The block is signal-named — anyone reading the values +file sees "this is for development" before they read the comment. +Mirrors the explicit framing in v3's schema comment +(`carvel-packages/installer/.../00-schema.yaml:28-35`). + +**Consequences to be aware of:** + +- The release workflow MUST update Chart.yaml annotations per fork + (alongside `appVersion`). Without that step, a fork's published chart + points at upstream `ghcr.io/educates/...` rather than the fork's + registry. Document this in the release runbook. +- Local-dev users set `global.development.imageRegistry` (umbrella) or + `.development.imageRegistry` (standalone install) to point + at their local registry. `educates publish-workshop` and the workshop + runtime's `$(image_repository)` resolution then both honour the same + setting. +- Helpers across the four image-rendering subcharts duplicate the + annotation-fallback logic (~10 lines each). Same scale of duplication + as the existing `resolvedImageRegistry` helpers; revisit only if a + library chart becomes warranted. + +**Reconsider trigger:** if Chart.yaml annotation editing turns out to +be brittle in the release workflow (e.g., `yq` formatting drift), move +the publish-time defaults to a chart-bundled `published-defaults.yaml` +file loaded by the helper instead. + +### Operator project strips kubebuilder's `config/` kustomize tree; controller-gen targets the Helm chart directly + +**Date:** 2026-05-06. +**Decision:** The v4 operator project at `installer/operator/` is +bootstrapped with `kubebuilder init` + `kubebuilder create api`, but +the generated `config/` kustomize tree is removed. `controller-gen` +is configured (via the operator's `Makefile`) to write CRDs and RBAC +manifests directly into the operator Helm chart at +`installer/charts/educates-installer/crds/` and +`installer/charts/educates-installer/templates/rbac/` respectively. +**Why:** The Helm chart is the artefact users consume — both for +imperative `helm install` and declarative GitOps. Maintaining a +parallel kustomize representation under `config/` would mean two +sources of truth for the same manifests, with a copy/transform step +between them. Stripping `config/` makes the chart the canonical +output and `make manifests` the single regeneration step. +**Consequences to be aware of:** +- `kubebuilder edit` and other kubebuilder subcommands that assume + the standard project layout will not work as documented. Project + edits go through `Makefile` targets and direct file edits instead. +- The operator's `Makefile` carries explicit `controller-gen` invocations + with chart-path output flags, replacing kubebuilder's default ones. +- `kubebuilder` generators (`kubebuilder create webhook` etc.) may + still drop files into `config/` if invoked; treat this as a chore to + clean up, not a recurring concern (we don't re-scaffold often). +**Reconsider trigger:** if we end up needing the `config/` tree for +something kubebuilder-native (e.g., webhook bootstrap), revisit and +either (a) re-introduce it as a build intermediate gitignored from +the chart output, or (b) generate webhook manifests by hand into the +chart. + +### Operator CRD types: spec is full r3 from Phase 0; status grows alongside reconcilers + +**Date:** 2026-05-06. +**Decision:** Phase 0 lands the *full* r3 spec surface for all four +CRDs (EducatesClusterConfig, SecretsManager, LookupService, +SessionManager) as Go types with kubebuilder validation and default +markers. The status surface, however, is minimal at Phase 0: +`observedGeneration`, `phase`, and `conditions` only. Richer status +fields described in the r3 doc (`ingress`, `policyEnforcement`, +`imageRegistry`, `bundledChartVersions`, `deploymentRef`, `url`, +`installedVersion`, etc.) are added in the phase whose reconciler +first produces them. +**Why:** Spec is the user-facing API contract — locking it early +catches drift in CI and lets users (and the migration tool) write +against it before reconcilers exist. Status, by contrast, is +implementation-coupled: a status field with no producer is dead API +surface that drifts from r3 silently. Growing status alongside +reconcilers keeps the Go types and the controller behaviour +consistent. +**Consequences to be aware of:** +- `docs/architecture/educates-crd-draft-v1alpha1-r3.md` remains the + *target* status spec; the Go types catch up phase by phase. When a + status field lands in Go, the corresponding doc section is the + source of truth for shape and semantics. +- Conditions follow Kubernetes convention (`Ready` plus PascalCase + domain-specific types). The list of condition types grows by phase + — Phase 0 ships only `Ready`; phase-specific conditions + (`ValidationSucceeded`, `CertificatesReady`, `ClusterConfigAvailable`, + etc.) are added with their producers. +**Reconsider trigger:** if a downstream consumer (CLI, GitOps tooling) +needs to read a status field before its reconciler exists, promote +that specific field early with a clear "not yet populated" semantics +and document it. + +### Operator image: local `make docker-build` only at Phase 0; publish wiring deferred to Phase 6 + +**Date:** 2026-05-06. +**Decision:** At Phase 0, the operator chart's `image.repository` / +`image.tag` defaults are a local-dev placeholder +(e.g. `ghcr.io/educates/educates-operator:dev`), the operator +`Makefile` ships a `docker-build` target that builds and tags that +image locally, and `make smoke-test` uses it directly against a kind +cluster (loading the image into kind nodes via `kind load`). No +publish-time annotation pattern, no release workflow integration, no +CI image build — those land in Phase 6 alongside the broader release +process work. +**Why:** Phase 0 is the skeleton phase. The image only needs to exist +for the local smoke test; replicating the runtime chart's +annotation-driven publish-time defaults would be premature scaffolding +for a release process that hasn't been built yet. Phase 6 designs +the operator's release flow as a whole and adds annotations + a +release workflow at that point. +**Consequences to be aware of:** +- A user trying to install the chart from a clone without first running + `make docker-build` + `kind load` will see `ImagePullBackOff`. The + chart's README and CLAUDE.md should call this out for as long as + Phase 0's image story is in effect. +- When Phase 6 introduces publish-time defaults, mirror the runtime + chart's `educates.dev/image-registry-host` / + `-namespace` Chart.yaml annotation pattern (see "`imageRegistry` is + a development override" decision) so the two charts share a single + release-workflow contract. +**Reconsider trigger:** if Phase 1 or 2 work needs the operator image +in a published location (e.g., for an external test cluster), promote +the publish wiring earlier rather than working around it. + +### ClusterIssuer access via `unstructured.Unstructured`; ClusterIssuer watch deferred to Phase 2 + +**Date:** 2026-05-06. +**Decision:** Phase 1 Inline validation reads ClusterIssuers via +`unstructured.Unstructured` against +`cert-manager.io/v1`/`ClusterIssuer`, NOT via vendored cert-manager +Go types. The reconciler's `Watches()` setup intentionally omits a +ClusterIssuer watch — it watches Secrets (cache-restricted to the +operator namespace) and IngressClasses (cluster-scoped) only. +**Why unstructured for reads:** Phase 1 only needs existence + the +`Ready` status condition. Vendoring `cert-manager.io` Go types pulls +in the cert-manager module (and a few hundred transitive packages) +for two field reads. Unstructured is cheap, requires no go.mod +addition, and cleanly degrades when the cert-manager CRD is absent +(`meta.IsNoMatchError` is surfaced as a validation error, not a +reconcile retry). +**Why no ClusterIssuer watch yet:** an unstructured `Watches()` +needs the GVK resolvable at cache-startup; if the cert-manager CRD +is absent, manager startup fails hard. Inline-mode users may run +without cert-manager (using `StaticCertificate`-style external TLS +or no TLS issuer at all), so making the watch unconditional in +Phase 1 would block startup on installs that don't need it. CRD +discovery at startup is a workable alternative but adds startup +complexity for a behaviour that's only relevant when a +ClusterIssuer is actually referenced. +**What this means in practice:** In Phase 1, an Inline user whose +referenced ClusterIssuer transitions from Ready=False to Ready=True +will not see status flip without a spec touch. Acceptable Phase 1 +limitation given the scope cut. +**Phase 2 promotion:** Phase 2 Managed mode unconditionally installs +cert-manager via the Helm SDK, so the CRD is guaranteed present. +Phase 2 vendors `cert-manager.io/v1` Go types (the operator interacts +with them more deeply: ClusterIssuer creation, Certificate creation + +Ready waiting) and adds the ClusterIssuer watch unconditionally at +that point. The Phase 1 unstructured read in +`internal/controller/config/validator.go::checkClusterIssuer` gets +refactored to typed access in the same change. +**Reconsider trigger:** if Phase 1 users complain about manual +re-trigger for ClusterIssuer drift before Phase 2 lands, add CRD +discovery at startup and conditionally install the watch — costs +~30 lines. + +### Phase 1 reconciler defensive guard for mode==Inline && spec.inline==nil + +**Date:** 2026-05-06. +**Decision:** The Phase 1 EducatesClusterConfig reconciler carries a +defensive guard: when `spec.mode == Inline` but `spec.inline == nil`, +mark the resource Degraded with the message +`spec.inline: Inline mode requires spec.inline to be set`. The CEL +exclusivity rule that lands alongside this code (Phase 1 step 1) +already makes the case structurally unreachable through the apiserver, +so the guard is belt-and-suspenders. +**Why guard anyway:** CEL rules can be bypassed in pathological +scenarios (a controller writing directly to etcd; a future webhook +configuration disabling CEL evaluation; CRD reapply during upgrade +when a new rule is added but old objects predate it). The guard is +~5 lines and produces a much better failure mode than a nil-pointer +panic. +**Reconsider trigger:** when admission webhooks land (post-v1alpha1) +and CEL bypass becomes infeasible, the guard becomes pure dead code +and can be removed. Flagged in the development plan's Phase 1 carry- +over list for v1beta1 review. + +### No `educates-cluster-services` umbrella chart; the operator is the sole installer + +**Date:** 2026-05-06. +**Decision:** Cluster services (cert-manager, Contour, Kyverno, +external-dns) are installed exclusively by the v4 operator via Helm SDK +calls against vendored upstream charts. There is no, and there is no +plan for, an `educates-cluster-services` umbrella chart that would offer +a standalone Helm-only install path for these services. The only +umbrella chart in the v4 design remains `educates-training-platform`, +which packages the Educates runtime components. +**Why:** A standalone cluster-services chart would duplicate what +`mode: Managed` already does (single action installs all four services) +without serving a real audience: BYO users go `mode: Inline` and bring +their own cluster services, so they don't want a chart from us either. +The operator is the single integration point — it owns ordering, +readiness checks, finalizer-driven uninstall, and ClusterIssuer/ +Certificate creation, none of which a plain Helm install can provide. +This consolidates earlier statements in `decisions.md:73-83` ("Subcharts +do not vendor upstream charts" — runtime subcharts package only Educates +components; cluster services are operator-installed) into a positive +decision so the question doesn't recur. +**Reconsider trigger:** if a concrete user demand emerges for installing +cluster services via plain Helm without the operator. Until then, the +operator is the only consumer and the only installer. + +### Vendored upstream charts live as tarballs at `installer/vendored-charts/` + +**Date:** 2026-05-06. +**Decision:** Upstream Helm charts the operator drives (cert-manager +first, then Contour, Kyverno, external-dns) are vendored into the +repository as tarballs under `installer/vendored-charts/-.tgz`. +A `make vendor-charts` target pulls them from upstream and verifies +checksums; the tarballs themselves are checked in. The operator's Helm +SDK loader reads chart bytes from this path at runtime (the tarballs are +embedded into the operator image at build time, or — during +development — read from disk). +**Why tarballs over unpacked directories:** Helm SDK's `loader.Load` +accepts both, but tarballs are atomic, content-addressable, and don't +invite ad-hoc local edits that drift from the upstream chart. Diff +review of a chart bump is `git show` of the tarball replacement plus +the README update, not a directory-wide diff that mingles real changes +with reformatting noise. The intent is "we ship the upstream chart +unmodified"; the tarball makes that intent enforceable. +**Why vendor at all:** Per development-plan open item #2, every chart +update must be a deliberate, testable change — not whatever the +upstream registry happens to serve at install time. Vendoring also +enables air-gapped installs without runtime registry access, and gives +us a single point of control for image-relocation rewrites in Phase 6. +**Layout consequence:** With no `educates-cluster-services` umbrella +(see preceding entry), `installer/vendored-charts/` has a single +consumer — the operator — so there is no need to expose it as a Helm +`file://` repository. If a future consumer appears, the same on-disk +location can be referenced via `repository: file://...` from a +`Chart.yaml` `dependencies` block without moving the bytes. + +**Amendment — 2026-05-11.** Directory relocated from +`installer/vendored-charts/` to `installer/operator/vendored-charts/`. +Phase 2 Session 2 established that the operator is the sole consumer in +practice, and `//go:embed` (the build-time mechanism this decision +already endorsed) requires the embedded path to live inside the +embedding Go module. The substantive content of the decision — tarballs +over directories, checksum-verified, no runtime registry pulls — is +unchanged. A hypothetical future consumer can still reach the bytes via +`file://...` references; the path inside `installer/operator/` is no +more or less accessible than a sibling directory would have been. + +### cert-manager CRDs are an operator install prerequisite (all modes) + +**Date:** 2026-05-06. +**Decision:** Starting with Phase 2, the cert-manager.io CRDs must be +installed in the cluster *before* the v4 operator starts — including +for Inline-mode-only installs that never reference a ClusterIssuer. +Managed-mode installs satisfy the prerequisite inherently (the operator +installs cert-manager); Inline-mode-only installs must apply the +cert-manager CRDs (or full cert-manager) up front. The operator chart +documents this; chart-level enforcement (e.g., a pre-install hook that +checks for the CRD) is deferred — failure mode at startup is loud +enough. +**Why:** The reconciler now uses a typed `Watches(&cmv1.ClusterIssuer{}, +...)` on the manager, and controller-runtime requires the GVK to be +resolvable at cache startup. A missing CRD causes hard manager startup +failure. Conditional CRD discovery + dynamic watch addition is workable +(~30 lines, flagged as the alternative in the Phase 1 deferral entry) +but not worth the complexity once cert-manager is a first-class +dependency for the project's primary install path. Even Inline users +typically have cert-manager already, since BYO ingress + TLS is the +common reason to use Inline. +**Reconsider trigger:** if a meaningful population of users emerges +with no cert-manager at all (e.g., StaticCertificate-only installs in +restricted environments), make the watch conditional on CRD discovery +at startup. Costs ~30 lines and an extra startup probe. + +**Amendment — 2026-05-13 (reversal).** This decision is reversed: +the operator chart no longer documents cert-manager CRDs as a +prerequisite. End-to-end testing during Phase 2 Session 2 / start +of Phase 3 surfaced the prerequisite as a real friction point +(users must apply cert-manager CRDs out-of-band before `helm +install educates-installer`, contradicting the project goal of a +single-command install with no preceding steps), and the same +friction would compound in Phase 3 as Contour, Kyverno, and +external-dns each add their own CRDs. + +**First attempt (failed):** flip the typed +`Watches(&cmv1.ClusterIssuer{}, ...)` to unstructured-with-GVK +(`Watches(&unstructured.Unstructured{...}, ...)`) on the +assumption that unstructured sidesteps the GVK-at-startup +requirement. It does not — controller-runtime's Kind source +resolves the GVK via discovery whether the watch is typed or +unstructured, and a missing CRD makes its polling-retry loop hang +forever, blocking cache sync and preventing the controller's +workers from ever starting. Verified on a vanilla kind cluster. + +**Actual resolution (deferred-watch pattern):** register only the +always-available watches (Secret, IngressClass, Deployment, the +EducatesClusterConfig itself) in `SetupWithManager`, capture the +underlying `controller.Controller` via `Builder.Build(r)`, and +attach a `manager.Runnable` (`internal/controller/config/crd_watcher.go`) +that polls the discovery client and calls `Controller.Watch(src)` +to register each deferred kind once its CRD becomes available. +Verified against controller-runtime v0.23.3: `Controller.Watch` +is safe to call post-Start, and a source added that way is +`Start()`-ed immediately under the controller's mutex +(pkg/internal/controller/controller.go:237-250). The CRDWatcher +exits cleanly once every target watch is registered. + +Code paths that Get / Create / SSA-patch cert-manager kinds still +use the typed `cmv1.*` types — those calls only execute after +`ensureCertManagerReady` confirms cert-manager is up, at which +point the CRDs are present and typed access works normally. + +**Known limitation (captured in follow-up-issues.md):** once a +deferred watch is activated, controller-runtime offers no API to +remove or stop a Source short of cancelling the entire controller +context. If cert-manager CRDs are subsequently deleted (helm +uninstall, or `kubectl delete crd`), the Kind source's polling +retry loop spams "if kind is a CRD, it should be installed" +errors every 10s until the operator pod restarts. The +operator's own code paths classify the missing-CRD state and +surface a `CertificatesReady=False reason=CertManagerCRDsMissing` +condition + `Degraded` phase, so the user-facing status is +clean; the noisy log line at the controller-runtime layer is a +cosmetic gap pending an upstream contribution. See +follow-up-issues.md "Quiet the controller-runtime Kind source +after cert-manager CRDs are removed". + +### Image pre-pull feature named `imagePrePuller` + +**Date:** 2026-05-27. +**Decision:** The optional node-level image pre-pull feature is named +`imagePrePuller` across every surface — the `SessionManager` CRD +(`spec.imagePrePuller`), the session-manager subchart +(`imagePrePuller.{enabled,pauseImage,images}`), and the forthcoming +Phase 5 CLI config kinds. The list of images to pre-pull is the field +`images` (renamed from the chart's earlier `prePullImages`). The +DaemonSet resource, ServiceAccount, and template filename keep the +shorter `image-puller` name — they describe the running mechanism, not +the user-facing knob. + +**Why:** Three names were in play — v3's `imagePuller`, CRD draft r3's +`imageCache`, and the chart's `imagePuller`. `imageCache` describes the +side effect (images cached on nodes); `imagePuller` describes the actor +but not the *ahead-of-time* intent that is the whole point of the +feature. `imagePrePuller` names the action and its timing: it pre-pulls +workshop images onto every node so session startup isn't blocked on +pulls. It keeps continuity with the existing `imagePuller`/`image-puller` +terminology while making the "pre" explicit. The list field became +`images` to avoid the `imagePrePuller.prePullImages` stutter. The rename +was cheap: v1alpha1 has no users, Phase 4 left the CRD field reserved +(`_ = obj.Spec.ImagePrePuller`, unwired), and the chart is at +`4.0.0-alpha.1` with no standalone users. This supersedes the +`imageCache` name in CRD draft r3 (now updated) and closes the +follow-up "Revisit `imageCache` naming". + +### Platform components install as per-component vendored subcharts into a shared `educates` namespace + +**Date:** 2026-05-14 (recorded 2026-06-10). +**Decision:** The Phase 4 platform reconcilers do not install the +umbrella `educates-training-platform` chart. Each reconciler installs +its component as its own Helm release from a vendored subchart tarball +under `installer/operator/vendored-charts/` — `secrets-manager`, +`lookup-service`, and `session-manager` (the latter also installing the +`node-ca-injector` and `remote-access` extras as separate releases when +enabled) — all into the single `educates` namespace, mirroring v3's +shared-namespace layout. The umbrella chart remains the standalone +no-operator install path and is what the project publishes for users +who don't want the operator. + +**Why:** One release per CR keeps install, upgrade, and finalizer-drain +boundaries aligned with the CR that owns them — deleting a +`LookupService` CR uninstalls exactly the lookup-service release, +without helm three-way-merging a shared umbrella release from three +independent reconcilers. The umbrella's value remains packaging +convenience for humans; the operator needs per-component control. The +subchart tarballs are vendored and SHA256-verified through the same +`make vendor-charts` machinery as the upstream cluster-service charts. + +### CLI config is a kind ladder of scenario configs plus an escape hatch + +**Date:** 2026-05-20. +**Decision:** The Phase 5 CLI consumes kind-discriminated YAML config +files under API group `cli.educates.dev/v1alpha1`. The ladder: +`EducatesLocalConfig` (laptop kind cluster; narrow and opinionated; +empty file valid), `EducatesGKEConfig` and `EducatesEKSConfig` (Managed +prod on GKE/EKS), `EducatesInlineConfig` (BYO / Inline mode), and +`EducatesConfig` — the escape hatch exposing the full CRD surface. A +new scenario kind is only admitted once a tested sample CR exists in +`installer/samples/`. Naming scheme is `Educates*Config`, escape hatch +bare `EducatesConfig`. + +**Why:** A single config shape must either expose everything (and stop +being opinionated) or hide things (and dead-end power users). Narrow +kinds make the common scenarios short, validated, and defaultable; the +escape hatch guarantees no expressiveness ceiling. The sample-CR +admission rule keeps the ladder from sprawling into untested shapes. + +### CLI data home unchanged from v3; `EDUCATES_CLI_DATA_HOME` overrides + +**Date:** 2026-05-20. +**Decision:** All Educates CLI state stays under +`$XDG_DATA_HOME/educates/` (subdirs `{config.yaml, secrets/, kind/, +resolver/, workshops/}` unchanged). A new `EDUCATES_CLI_DATA_HOME` env +var takes precedence when set. `config.yaml` holds an +`EducatesLocalConfig` only — singular, one per machine (or one per +`EDUCATES_CLI_DATA_HOME` value); no profiles. Non-Local kinds live in +the user's own repo (docs-recommended convention: +`educates-.yaml`). + +**Why:** Keeping the v3 path avoids churning ~18 `GetEducatesHomeDir()` +call sites and avoids migrating existing on-disk user state (secrets, +kind, resolver caches all keep working). The env var gives CI and +power users relocation without touching XDG. One-Local-per-machine +mirrors how the laptop flow is actually used; profile demand can +reopen this later. + +### CLI schema strategy: embedded JSON schema per kind; `EducatesConfig` generated from CRDs + +**Date:** 2026-05-20. +**Decision:** Every CLI config kind has a JSON schema embedded into the +binary via `//go:embed` at +`client-programs/pkg/config/v1alpha1/schemas/.schema.json`. +Scenario-kind schemas are hand-authored; the `EducatesConfig` schema is +generated from the CRD OpenAPI output via `make generate-cli-schemas` +(no hand-maintained schema for the escape hatch). Schemas drive +command-time validation, `local config set` path/type checks, and IDE +support; publishing them at +`https://schemas.educates.dev/cli/v1alpha1/.json` plus +SchemaStore.org registration is Phase 6 work. + +**Why:** One artifact serves validation, tooling, and docs without +drifting from the code. Generating the escape-hatch schema from the +CRDs makes "the CLI accepts exactly what the CRDs accept" a build-time +guarantee rather than a maintenance promise. + +### `EducatesConfig` escape hatch carries CR specs verbatim (layout B1) + +**Date:** 2026-05-20. +**Decision:** The escape-hatch kind uses section keys named by +camelCase CRD kind (`educatesClusterConfig`, `secretsManager`, +`lookupService`, `sessionManager`), each body being that CR's `.spec` +verbatim; the CLI wraps `apiVersion`/`kind`/`metadata.name: cluster` at +translate time. An optional `target:` block (provider + the Local +kind's `cluster`/`resolver` shapes) controls CLI side-effects; when +absent the CLI just applies what's declared. No CLI-inferred defaults, +no invariants — every CRD field is settable; only apiserver-side +kubebuilder defaults apply. `educates local cluster create` accepts +`EducatesLocalConfig` or `EducatesConfig` with `target.provider: kind`; +nothing else. + +**Why:** Verbatim passthrough means translation is mechanical YAML +slicing — no field-level mapping to maintain, no possibility of the +escape hatch lagging the CRDs. Defaults and invariants are exactly +what the user escalated away from; injecting them back in would +recreate the ceiling the kind exists to remove. + +### v3→v4 config migration is a silent first-run shim, not a command + +**Date:** 2026-05-20 (implemented 2026-06-06, Phase 5 step 10). +**Decision:** There is no `educates migrate-config` command. On first +v4 CLI use, a v3 `values.yaml` under the data home is silently +translated to a v4 `config.yaml` (`EducatesLocalConfig`) only when +`clusterInfrastructure.provider` is `kind` or empty; the original is +stashed as `values.yaml.v3-backup`. Any other provider leaves the file +untouched and subsequent CLI operations error with instructions to +re-declare against a v4 kind. This supersedes the development plan's +original "migration tool produces valid CRs for three real v3 configs" +criterion. + +**Why:** The laptop case is the only one where the v3 file is the +system of record the CLI itself owns — migrating it silently preserves +the "it just keeps working" experience. Cloud/BYO configs live in user +repos with intent the CLI can't infer (DNS, ACME, identity wiring); +a lossy auto-translation would produce plausible-but-wrong CRs, which +is worse than an honest error. v3 and v4 installs can't coexist +anyway, so there's no runtime adapter to maintain. + +### `imagePrePuller` default image list is chart-derived; CRD exposes only the toggle + +**Date:** 2026-06-10. +**Decision:** When `imagePrePuller.enabled: true` and +`imagePrePuller.images` is empty, the session-manager subchart derives +the pre-pull list itself — `training-portal` + `base-environment`, +resolved through the `session-manager.imageVersions` inventory helper +(new helper `session-manager.prePullImages`). A non-empty `images` +list replaces the default verbatim. The `SessionManager` CRD keeps +only `spec.imagePrePuller.enabled`; the operator passes the toggle +through and never computes image refs. This supersedes the chart +comment that said the operator (or chart user) always supplies fully +qualified refs. + +**Why:** The chart's imageVersions helper is the single source of +truth for resolved, relocation-aware image references — duplicating +that inventory in the operator would drift on every image addition, +and an enabled-but-empty DaemonSet that pre-pulls nothing is a silent +no-op. The default set mirrors v3 exactly: its image-puller DaemonSet +always pre-pulled `training-portal` plus a `prePullImages` list +defaulting to `["base-environment"]`. Per-image control remains a +chart-level concern (standalone users set `imagePrePuller.images`; +operator users needing custom lists escalate via the chart, not the +CRD). + +### Release versions are stamped in CI at publish time; charts are pushed to OCI under `charts/` + +**Date:** 2026-06-11. +**Decision:** Releases stay "tag and go": the committed tree carries a +development version (`4.0.0-alpha.1` charts, `appVersion: 3.7.1` +runtime placeholder) and is never bumped by a release commit. On a tag +push, `hack/stamp-release-version.sh` stamps the git tag as both +`version` AND `appVersion` across `educates-installer`, the +`educates-training-platform` umbrella (including its +`dependencies[].version` pins) and the five runtime subcharts, rewrites +the `educates.dev/image-registry-{host,namespace}` annotations to +`ghcr.io/` (the fork-rewrite that was always planned +for these annotations), repackages the five runtime subchart tarballs +into `installer/operator/vendored-charts/` at the stamped version, +rewrites the `//go:embed` filenames + `ChartVersion` constants in +`embed.go`, refreshes `SHA256SUMS`, and regenerates the CLI's embedded +chart copy. The script's `--charts-only` mode (pure perl, no +helm/yq) lets the macOS CLI build runners stamp the embedded chart. +Upstream cluster-service charts (cert-manager, Contour, external-dns, +Kyverno) are NOT touched — they stay pinned until a human re-vendors +them. The release workflow runs the script in three places: before the +operator image build (so the image embeds released-version subcharts), +in the four CLI binary builds, and in the new `publish-charts` job, +which `helm package`s + `helm push`es both charts to +`oci://ghcr.io//charts/` and attaches the tarballs (with +checksums) to the GitHub release. + +**Why:** Every other release artifact already gets its version from +the tag at build time (CLI via ldflags, images via +docker/metadata-action), so commit-then-tag would add a mandatory bump +commit per release while protecting nothing — the stamped inputs are +fully derived from the tag plus the committed tree. Stamping +`appVersion` too (superseding the umbrella Chart.yaml comment that it +lags at 3.7.1) makes each release self-consistent: the runtime images +the charts reference are exactly the ones the same workflow run +published, which is also what makes fork releases work without +upstream-published images. The `charts/` OCI prefix keeps chart +packages visually separate from the ~15 container images in the same +ghcr.io namespace. + +### Image relocation is a published digest-pinned list + name-preserving mirror; helm dt rejected + +**Date:** 2026-06-11. +**Decision:** Air-gapped/mirrored installs are served by a per-release +artifact `educates-images-.txt` (generated by +`hack/generate-image-list.sh`, attached to the GitHub release): +one digest-pinned reference per line covering the platform images + +workshop base-environment at the released version plus the upstream +cluster-service images extracted by rendering the vendored chart +tarballs with default values (a deliberate slight superset of what the +operator enables). Users mirror name-preserving with standard tools +(skopeo/crane) and install with the existing registry overrides +(`development.imageRegistry` for the charts, +`EducatesClusterConfig.spec.imageRegistry.prefix` for operator-driven +installs). A CLI wrapper (`educates admin platform images copy`, +tar export/import via the already-vendored Carvel registry libraries) +is a follow-up for single-command transport UX. Workshop environment +images beyond base-environment (jdk*, conda) stay out of the list; +users append them as needed. + +**Why:** The Phase-6 candidate `helm dt` relicensed from Apache-2.0 to +a proprietary Broadcom license effective 2026 (vmware-labs/ +distribution-tooling-for-helm#132; use restricted to "in connection +with Broadcom products"), which binds end users running `unwrap`, not +just our pipeline — and no community Apache fork exists. Independent +of licensing, dt's differentiator (rewriting image refs in chart +values at unwrap) is a no-op on our charts: values image fields are +deliberately empty (refs compose from the educates.dev annotations), +and most images are installed by the operator from embedded subcharts +or computed upstream-chart values that no chart-rewriting tool can +reach — relocated installs need the prefix overrides regardless. An +imgpkg bundle was also rejected for the consumption hop: `imgpkg copy +--to-repo` flattens all images into a single digest-addressed +repository, resolvable only via the rewritten ImagesLock (kbld-style +resolution the v4 design explicitly excludes from the install path). +Both tools reduce, for our chart shape, to "generated image inventory ++ transport" — so we publish the inventory and use boring, +name-preserving transport that matches how the charts already resolve +images. Maintaining a frozen Apache-era dt fork was rejected as +all-cost-no-benefit. + +### CLI JSON schemas publish to GitHub Pages from this repo; discovery via modeline + SchemaStore + +**Date:** 2026-06-11. +**Decision:** The `publish-schemas` release job deploys the +`cli.educates.dev/v1alpha1` schemas to this repository's GitHub Pages +site on every release tag, at the `$id` paths Phase 5 baked into them +(`/cli/v1alpha1/.json`; published names drop the `.schema` +infix). Upstream maps `schemas.educates.dev` to the Pages site +(one-time repo setting + DNS CNAME, documented in +`developer-docs/json-schemas.md`); forks serve from +`.github.io/...` and the job is `continue-on-error` so a fork +without Pages enabled doesn't break its release. `$id` stays the +canonical upstream URL even in fork-published copies (editors fetch +the configured URL, not `$id`; no cross-schema `$ref`s exist). +Editor discovery is two-pronged: `local config init` writes a +`# yaml-language-server: $schema=...` modeline, and a new +kind-discriminated umbrella schema (`EducatesAnyConfig`, oneOf over +the five kinds, not embedded in the CLI) backs a SchemaStore catalog +entry with `**/educates/config.yaml` + `*.educates.yaml` fileMatch +patterns — the catalog PR is filed manually after the first release +makes the URLs live. + +**Why:** Publishing serves editors and external validation (GitOps +CI), not the CLI itself — the schemas are embedded for command-time +validation regardless, but Phase 5's `$id` URLs are dead links until +hosted, and the scenario kinds are designed to be hand-edited in user +repos where language-server support matters. Pages-from-this-repo +keeps schema deployment versioned with the release that embeds the +same schemas, with no extra repo or external hosting dependency. +Schema hosting is deliberately upstream-centric (unlike images and +charts, where fork self-containment is load-bearing): a fork that +changes schema shape carries a patch. + +### Ingress protocol override lives on SessionManager, surfaced as `externalTLSTermination` in the CLI kinds + +**Date:** 2026-06-11. +**Decision:** The restored v3 `clusterIngress.protocol` capability is +modelled as `SessionManager.spec.ingressOverrides.protocol` +(http|https, optional; empty derives from TLS presence as the chart +already does), NOT as a new `EducatesClusterConfig` certificates +provider. The reconciler threads it to the session-manager chart's +existing `clusterIngress.protocol` value. The CLI exposes it as a +boolean `externalTLSTermination: true` on `EducatesGKEConfig`, +`EducatesEKSConfig` and `EducatesInlineConfig` (translating to +protocol: https); `EducatesConfig` reaches the field directly via the +CRD-generated schema. `EducatesLocalConfig` does not expose it. + +**Why:** The protocol is a URL-generation concern owned by the +session-manager and workshops — an assertion that the public edge is +https when TLS is terminated at an external load balancer — not a +certificate-provisioning concern, so it belongs on the component CR +rather than in the cluster config's certificates discriminated union. +The boolean naming on the kinds describes the scenario (cloud LB in +front) rather than the mechanism, making it hard to misuse; the +generic http|https enum remains available on the CR for completeness. +This is deliberately the minimal slice of the "External load balancer +support" follow-up: certificate-less installs, LookupService URL +coherence and envoy exposure modes remain open there — a full +end-to-end externalLoadBalancer capability likely touches runtime +internals, which are out of scope for v4. + +### Operational blocks trimmed to BundledContour only + +**Date:** 2026-06-11. +**Decision:** The `operational` block (replicas, resources, +tolerations, nodeSelector, priorityClassName, podAnnotations, +podLabels) is removed from `bundledCertManager`, `bundledExternalDNS`, +and the Kyverno config in `EducatesClusterConfig` — the empty +`kyverno.bundled` wrapper went with it. Only `bundledContour` keeps +the block, where the reconciler applies `replicas` to the Contour +controller Deployment (`contour.replicaCount`); the remaining knobs +stay accepted-but-unwired. This diverges from the r3 draft's "every +Bundled block exposes the same operational knobs" pattern; the draft +carries a dated amendment. + +**Why:** Verifying the plumbing against the vendored upstream charts +showed the shared shape didn't hold. external-dns 1.21.1 hardcodes +`replicas: 1` in its Deployment template and exposes no replica value +(its values.schema.json has top-level `additionalProperties: true`, +so the operator's `replicaCount` was silently swallowed) — the +controller is deliberately single-instance. Kyverno's chart scales +per-controller and upstream HA guidance wants 3+ replicas for the +admission controller only, so fanning one count across all four +controllers had wrong semantics. cert-manager spans controller + +webhook + cainjector Deployments and its block was never consumed. +Shipping no-op or misleading v1alpha1 surface is worse than re-adding +per-service shapes (cert-manager per-deployment sub-blocks, Kyverno +per-controller counts) validated against each chart's real values +when a concrete need emerges — tracked in the r3 open items. diff --git a/docs/architecture/educates-crd-draft-v1alpha1-r3.md b/docs/architecture/educates-crd-draft-v1alpha1-r3.md new file mode 100644 index 000000000..43f269ac6 --- /dev/null +++ b/docs/architecture/educates-crd-draft-v1alpha1-r3.md @@ -0,0 +1,935 @@ +# Educates CRDs — v1alpha1 Draft (revision 3) + +> **Status:** Draft for team review. Revision 3: incorporates feedback on +> infrastructure shape, DNS placement, ACME solvers, policy structure, Helm +> values customization, image pull secrets, defaults/status strategy, and CA +> naming. + +## Overview + +Four CRDs, all cluster-scoped, all enforced as singletons named `cluster`: + +1. **`EducatesClusterConfig`** (`config.educates.dev/v1alpha1`) — cluster-wide infrastructure and services. Two modes: **Managed** (operator installs cluster services) and **Inline** (user declares pre-existing resources). +2. **`SecretsManager`** (`platform.educates.dev/v1alpha1`) — secrets-manager component. +3. **`LookupService`** (`platform.educates.dev/v1alpha1`) — lookup-service component. +4. **`SessionManager`** (`platform.educates.dev/v1alpha1`) — the session-manager component. Requires `SecretsManager` to be Ready. + +**Component contract with `EducatesClusterConfig`:** components read exclusively from `EducatesClusterConfig.status`. They don't look at `.spec`, don't care about mode. Their precondition is "an `EducatesClusterConfig` exists with `Ready: True`." + +--- + +## Shared concepts + +### Singleton enforcement + +Each CRD includes a CEL validation rule: + +```yaml +x-kubernetes-validations: + - rule: "self.metadata.name == 'cluster'" + message: "This resource must be named 'cluster' (singleton per cluster)." +``` + +### Mode immutability (`EducatesClusterConfig` only) + +```yaml +x-kubernetes-validations: + - rule: "self.spec.mode == oldSelf.spec.mode" + message: "spec.mode is immutable. To switch modes, delete and recreate this resource." +``` + +### Common status conventions + +```yaml +status: + observedGeneration: + phase: Pending | Installing | Validating | Ready | Degraded | Uninstalling + conditions: + - type: Ready + status: "True" | "False" | "Unknown" + reason: + message: + lastTransitionTime: + observedGeneration: +``` + +### Defaulting strategy + +- **Static defaults go in the CRD schema** (`default:` in OpenAPI). They populate `spec` at admission time, making `kubectl get -o yaml` self-documenting. +- **Computed defaults** (those depending on other fields, e.g., `bundledContour.replicas` varying by infrastructure provider) are resolved by the reconciler. +- **Status publishes effective values** so components and humans have a single source of truth, regardless of whether values came from schema defaults, user input, or operator computation. +- **Status is kept minimal** — only the inter-CR contract plus conditions. Full config introspection is not a status concern. + +### Inline-mode validation + +When `EducatesClusterConfig.spec.mode: Inline`, the operator validates referenced resources before publishing status: + +- Secrets exist in the operator namespace with the expected keys. +- ClusterIssuer exists and is `Ready: True` (if `clusterIssuerRef` set). +- IngressClass exists. + +On failure, `phase: Degraded`, `Ready: False`, condition with a message pointing at the offending field. Components see the config as not Ready and refuse to proceed. + +**Inline validation — required vs optional fields:** + +| Field | Required? | Validated as | +|---|---|---| +| `inline.ingress.domain` | Required | Non-empty string, DNS-compliant | +| `inline.ingress.ingressClassName` | Required | IngressClass with this name exists | +| `inline.ingress.wildcardCertificateSecretRef.name` | Required | Secret exists, has `tls.crt` and `tls.key` keys, cert is valid for `*.` | +| `inline.ingress.caCertificateSecretRef.name` | Optional | If present: Secret exists, has `ca.crt` key | +| `inline.ingress.clusterIssuerRef.name` | Optional | If present: ClusterIssuer exists and is `Ready: True` | +| `inline.policyEnforcement.clusterPolicyEngine` | Required | Enum value | +| `inline.policyEnforcement.workshopPolicyEngine` | Required | Enum value | + +### Secret key conventions + +- TLS secrets: exactly `tls.crt` and `tls.key`. Standard Kubernetes `kubernetes.io/tls` type. +- CA secrets: exactly `ca.crt`. No alternative names accepted. Users with certs under other key names must rewrap. +- ImagePullSecrets: standard `dockerconfigjson` type, key `.dockerconfigjson`. Standard Kubernetes convention. + +### Operator watches + +The operator reconciles on: + +1. Changes to the CR itself (`generation` bump). +2. Changes to **referenced resources** (Secrets, ClusterIssuers, IngressClasses) via name-targeted watches. + +This means external changes — like a user deleting the TLS Secret — are detected within seconds and reflected in status. Without this, a CR could show `Ready: True` while reality has drifted. + +### CEL validation strategy + +All structural validation (mode/inline exclusivity, singleton name, immutability, field-presence rules) uses CEL in the CRD schema. Semantic validation (referenced resources exist and are usable) happens in the reconciler. Admission webhooks are not used in v1alpha1. + +### Operational block pattern + +> **Amended 2026-06-11:** in v1alpha1 only `bundledContour` carries an +> `operational` block. The cert-manager, external-dns, and kyverno +> blocks were removed after verifying their semantics against the +> vendored upstream charts: the kubernetes-sigs external-dns chart +> hardcodes `replicas: 1` and exposes no replica value (the controller +> is deliberately single-instance); Kyverno scales per-controller with +> its own HA rules (3+ replicas for the admission controller only), so +> one shared count fanned across its four controllers had wrong +> semantics; cert-manager spans controller + webhook + cainjector +> Deployments and never consumed the block. Each returns as a +> per-service shape validated against the chart's real values surface +> when a concrete need emerges. See the decisions log. + +The `bundledContour` block exposes the `operational` knobs: + +```yaml +operational: + replicas: + resources: + requests: { cpu, memory } + limits: { cpu, memory } + tolerations: [...] + nodeSelector: { ... } + priorityClassName: + podAnnotations: { ... } + podLabels: { ... } +``` + +The shape is intentionally use-site-local rather than factored out, because multi-deployment charts (e.g., cert-manager with controller + webhook + cainjector) need deployment-specific variants when they regain the block. Duplication is cheaper than a clever schema reference. + +--- + +## 1. `EducatesClusterConfig` + +### Spec + +```yaml +apiVersion: config.educates.dev/v1alpha1 +kind: EducatesClusterConfig +metadata: + name: cluster +spec: + + # -- MODE (immutable) ------------------------------------------------------- + mode: Managed | Inline + + # ========================================================================= + # MANAGED MODE FIELDS + # CEL rule: mode == 'Managed' → these are valid; inline is forbidden. + # ========================================================================= + + infrastructure: + provider: Kind | Minikube | EKS | GKE | OpenShift | VCluster | Generic + + # Common cloud config — used when provider is a cloud. + # Omit for Kind/Minikube/OpenShift/VCluster/Generic. + cloud: + project: # GCP project / AWS account alias / etc. + region: + serviceAccounts: + # Opaque identity strings, interpreted by provider: + # GKE: GCP service account email (e.g., foo@project.iam.gserviceaccount.com) + # EKS: IAM role ARN (e.g., arn:aws:iam::123:role/my-role) + # Other providers: documented per-provider. + certManager: + externalDNS: + + ingress: + domain: # wildcard subdomain, e.g., educates.example.com + ingressClassName: # required; name of IngressClass used by Educates. + # In Bundled mode: operator creates IngressClass with this name. + # In External mode: existing IngressClass name. + + controller: + provider: BundledContour | ExternalIngressController + # Explicit — no default. User must choose. + + bundledContour: # when provider: BundledContour + # replicas default: 1 for Kind/Minikube, 2 otherwise (reconciler-computed) + operational: + replicas: + resources: { ... } + tolerations: [...] + nodeSelector: { ... } + priorityClassName: + podAnnotations: { ... } + podLabels: { ... } + + # externalIngressController: no further config needed — ingressClassName above is the contract + + certificates: + provider: BundledCertManager | ExternalCertManager | StaticCertificate + + bundledCertManager: + issuerType: ACME | CustomCA + + acme: # when issuerType: ACME + email: + solvers: + dns01: # required — needed for wildcard certs + provider: Route53 | CloudDNS | Cloudflare | AzureDNS + + route53: # when provider: Route53 + hostedZoneID: + region: # optional, defaults to infrastructure.cloud.region + + cloudDNS: # when provider: CloudDNS + zone: # GCP-style zone name + project: # optional, defaults to infrastructure.cloud.project + + cloudflare: # when provider: Cloudflare + apiTokenSecretRef: + name: + key: api-token # default "api-token" + + azureDNS: # when provider: AzureDNS + resourceGroup: + subscriptionID: + + http01: # optional, rarely needed given DNS01 is required for wildcards + ingressClassName: # defaults to spec.ingress.ingressClassName + + customCA: # when issuerType: CustomCA + caCertificateRef: + name: # Secret in operator namespace, keys: tls.crt, tls.key (the CA's own cert+key) + # no operational block (removed 2026-06-11 — see "Operational block pattern") + + externalCertManager: # cert-manager assumed installed; operator creates only the Certificate + clusterIssuerRef: + name: + + staticCertificate: # user provides the wildcard TLS cert directly; no cert-manager + tlsSecretRef: + name: # keys: tls.crt, tls.key + caCertificateRef: # optional + name: # key: ca.crt + + dns: + provider: BundledExternalDNS | Manual | None + # Static default: None (works for Kind/Minikube; cloud users must set explicitly) + + bundledExternalDNS: # when provider: BundledExternalDNS + # no operational block (removed 2026-06-11 — the upstream chart is single-instance by design) + # Note: zone auto-discovery from Ingress hostnames is default behavior. + # Explicit zone configuration deferred to later revision. + + # Manual: user pre-created DNS records. No operator action. + # None: no DNS concern (Kind/Minikube with nip.io, etc.). + + policyEnforcement: + clusterPolicy: + engine: Kyverno | PodSecurityStandards | OpenShiftSCC | None + # Static default: Kyverno + + workshopPolicy: + engine: Kyverno | None + # Static default: Kyverno + # Setting to None disables workshop isolation — user takes responsibility. + + kyverno: # required if any engine above is Kyverno + provider: Bundled | External + # Static default: Bundled + + # No per-provider sub-blocks. Bundled installs the vendored chart + # with default per-controller scaling (the former bundled.operational + # block was removed 2026-06-11 — see "Operational block pattern"); + # External: no fields — user ensures Kyverno CRDs are installed. + + imageRegistry: # optional + prefix: # e.g., internal-registry.corp.local/educates + # When set, all bundled charts have image refs rewritten to use this prefix. + # For pre-relocated bundles (via Helm dt wrap/unwrap), this is not needed. + + pullSecrets: # optional + - name: # Secret in operator namespace, type dockerconfigjson + + # ========================================================================= + # INLINE MODE FIELDS + # CEL rule: mode == 'Inline' → this block is required; managed fields forbidden. + # ========================================================================= + + inline: + ingress: + domain: # required + ingressClassName: # required + wildcardCertificateSecretRef: + name: # required; Secret with tls.crt + tls.key + caCertificateSecretRef: # optional + name: # Secret with ca.crt + clusterIssuerRef: # optional + name: # must exist and be Ready + + policyEnforcement: + clusterPolicyEngine: Kyverno | PodSecurityStandards | OpenShiftSCC | None + workshopPolicyEngine: Kyverno | None + + imageRegistry: # optional (same shape as Managed) + prefix: + pullSecrets: + - name: +``` + +### Status + +```yaml +status: + observedGeneration: + phase: Pending | Installing | Validating | Ready | Degraded | Uninstalling + mode: Managed | Inline + + conditions: + - type: Ready # aggregate + - type: ValidationSucceeded # Inline only; false if refs missing/invalid + - type: InfrastructureConfigured # Managed only + - type: IngressReady + - type: CertificatesReady + - type: DNSReady + - type: PolicyEnforcementReady + + # Minimal published interface — only what components need + ingress: + domain: + ingressClassName: + wildcardCertificateSecretRef: + namespace: # always operator namespace + name: + caCertificateSecretRef: # optional, present if a CA exists + namespace: + name: + clusterIssuerRef: # optional + name: + + policyEnforcement: + clusterPolicyEngine: # resolved effective value + workshopPolicyEngine: + + imageRegistry: # always populated in status, even if empty + prefix: # may be empty string + pullSecrets: + - name: + + bundledChartVersions: # informational; Managed mode only + # Useful for users going External later — they know which chart/version we used. + # May change between Educates releases. Not a stable API. + contour: + cert-manager: + external-dns: + kyverno: +``` + +### Design notes + +- **`mode` is immutable.** To switch between Managed and Inline, delete and recreate the CR. +- **Mode-specific CEL rules** enforce exclusivity: Managed mode fields forbidden in Inline, and vice versa. +- **Schema defaults + status** mean users can leave most fields blank and still see meaningful config in `kubectl get -o yaml` (defaults populate spec) and in status (effective values). +- **`bundledChartVersions` is documented as informational.** Users going External for a service can see which chart we use internally as a reference for their own install. + +--- + +## 2. `SecretsManager` + +### Spec + +```yaml +apiVersion: platform.educates.dev/v1alpha1 +kind: SecretsManager +metadata: + name: cluster +spec: + image: # optional override + repository: + tag: + + logLevel: debug | info | warn | error # static default: info + + resources: + requests: { cpu, memory } + limits: { cpu, memory } +``` + +### Status + +```yaml +status: + observedGeneration: + phase: Pending | Installing | Ready | Degraded | Uninstalling + conditions: + - type: Ready + - type: ClusterConfigAvailable + - type: Deployed + + installedVersion: + deploymentRef: + namespace: + name: +``` + +### Design notes + +- **No `replicas`**: secrets-manager is singleton at the pod level (today it can't scale beyond 1). +- **No `clusterConfig` block**: reads from `EducatesClusterConfig.status` implicitly. +- **ImagePullSecrets** come from `EducatesClusterConfig.status.imageRegistry.pullSecrets`. + +--- + +## 3. `LookupService` + +### Spec + +```yaml +apiVersion: platform.educates.dev/v1alpha1 +kind: LookupService +metadata: + name: cluster +spec: + ingress: + prefix: # required, e.g., "educates-api" + # Full hostname: . + + tlsSecretRef: # optional override of cluster wildcard + name: + + image: + repository: + tag: + + logLevel: debug | info | warn | error # default: info + + resources: + requests: { cpu, memory } + limits: { cpu, memory } + + # Auth, rate-limiting, storage settings — to be added when lookup-service owner specifies them +``` + +### Status + +```yaml +status: + observedGeneration: + phase: ... + conditions: + - type: Ready + - type: ClusterConfigAvailable + - type: IngressReady + - type: Deployed + + url: # full URL: https://. + installedVersion: +``` + +--- + +## 4. `SessionManager` + +### Spec + +```yaml +apiVersion: platform.educates.dev/v1alpha1 +kind: SessionManager +metadata: + name: cluster +spec: + # -- DEPENDENCIES --------------------------------------------------------- + # Requires SecretsManager.Ready and EducatesClusterConfig.Ready. + # No explicit refs — singletons. + + # -- INGRESS OVERRIDES (rare) --------------------------------------------- + # session-manager uses the bare domain from EducatesClusterConfig.status.ingress.domain + # directly. TrainingPortal CRs prefix it for individual portal hostnames. + + ingressOverrides: # optional + tlsSecretRef: + name: + caCertificateSecretRef: + name: + protocol: http | https # optional (added post-r3, 2026-06-11). + # Asserts the scheme of generated portal/workshop URLs when TLS is + # terminated outside the cluster (external load balancer / proxy + # forwarding plain HTTP inward). Empty derives from TLS presence. + # Restores v3's clusterIngress.protocol for URL generation; full + # certificate-less installs remain a follow-up (see + # follow-up-issues.md "External load balancer support"). + + # -- WORKSHOP POLICY OVERRIDE --------------------------------------------- + workshopPolicyOverride: # optional + engine: Kyverno | None + # When set, overrides EducatesClusterConfig's workshopPolicy engine. + + # -- IMAGES --------------------------------------------------------------- + # Image registry prefix and pullSecrets come from EducatesClusterConfig.status.imageRegistry. + # Here we only allow per-image overrides. + images: + overrides: # optional, open list + - name: # e.g., "session-manager", "jdk17-environment" + image: # full image ref including tag or digest + + # -- THEMES --------------------------------------------------------------- + themes: + - name: + source: + type: ConfigMap | Secret | URL + configMapRef: + name: + namespace: + # additional source types TBD by owner + + defaultTheme: + + # -- ANALYTICS / TRACKING ------------------------------------------------- + tracking: + googleAnalytics: + trackingId: + amplitude: + trackingId: + clarity: + trackingId: + webhook: + url: + + # -- DEFAULTS ------------------------------------------------------------- + defaultAccessCredentials: # optional + username: + passwordSecretRef: + name: + + sessionCookieDomain: + allowedEmbeddingHosts: + - + + # -- STORAGE -------------------------------------------------------------- + storage: + storageClass: + storageGroup: + storageUser: + + # -- NETWORK -------------------------------------------------------------- + network: + packetSize: + blockedCidrs: + - + + # -- IMAGE PRE-PULLER ----------------------------------------------------- + imagePrePuller: + enabled: + + # -- REGISTRY MIRRORS ----------------------------------------------------- + # For workshop containers pulling from mirrored registries. + registryMirrors: + - mirror: + url: + + # -- LOG LEVEL ------------------------------------------------------------ + logLevel: debug | info | warn | error # default: info +``` + +### Status + +```yaml +status: + observedGeneration: + phase: ... + conditions: + - type: Ready + - type: ClusterConfigAvailable + - type: SecretsManagerAvailable + - type: ComponentsDeployed + - type: CRDsRegistered # training.educates.dev CRDs present + + installedVersion: + trainingCRDsGroup: training.educates.dev + components: + - name: session-manager + image: + ready: + - name: training-portal + image: + ready: + # ... etc +``` + +### Design notes + +- **No `replicas`**: today each component is pod-singleton. +- **No `images.registry` field**: centralized in `EducatesClusterConfig.spec.imageRegistry.prefix`. +- **`images.overrides` is an open list** of name/image pairs, matching today's `imageVersions` shape. Any image the operator knows about can be overridden by name. + +--- + +## Config-to-CR mapping table + +| Today's config path | New CR | New path | +|---|---|---| +| `localKindCluster.*` | — | CLI-only | +| `localDNSResolver.*` | — | CLI-only | +| `clusterInfrastructure.provider` | EducatesClusterConfig | `spec.infrastructure.provider` | +| `clusterInfrastructure.gcp.project` | EducatesClusterConfig | `spec.infrastructure.cloud.project` | +| `clusterInfrastructure.gcp.cloudDNS.zone` | EducatesClusterConfig | `spec.ingress.certificates.bundledCertManager.acme.solvers.dns01.cloudDNS.zone` | +| `clusterInfrastructure.gcp.workloadIdentity.certManager` | EducatesClusterConfig | `spec.infrastructure.cloud.serviceAccounts.certManager` | +| `clusterInfrastructure.gcp.workloadIdentity.externalDNS` | EducatesClusterConfig | `spec.infrastructure.cloud.serviceAccounts.externalDNS` | +| `clusterInfrastructure.aws.region` | EducatesClusterConfig | `spec.infrastructure.cloud.region` | +| `clusterInfrastructure.aws.route53.hostedZone` | EducatesClusterConfig | `spec.ingress.certificates.bundledCertManager.acme.solvers.dns01.route53.hostedZoneID` | +| `clusterInfrastructure.aws.irsaRoles.certManager` | EducatesClusterConfig | `spec.infrastructure.cloud.serviceAccounts.certManager` | +| `clusterInfrastructure.aws.irsaRoles.externalDNS` | EducatesClusterConfig | `spec.infrastructure.cloud.serviceAccounts.externalDNS` | +| `clusterInfrastructure.caCertificateRef` | EducatesClusterConfig | `spec.ingress.certificates.bundledCertManager.customCA.caCertificateRef` OR `spec.inline.ingress.caCertificateSecretRef` | +| `clusterPackages.contour.enabled` | EducatesClusterConfig | implicit via `spec.ingress.controller.provider: BundledContour` | +| `clusterPackages.contour.settings.*` | EducatesClusterConfig | `spec.ingress.controller.bundledContour.operational.*` | +| `clusterPackages.cert-manager.enabled` | EducatesClusterConfig | implicit via `spec.ingress.certificates.provider: BundledCertManager` | +| `clusterPackages.external-dns.enabled` | EducatesClusterConfig | implicit via `spec.dns.provider: BundledExternalDNS` | +| `clusterPackages.certs.enabled` | EducatesClusterConfig | implicit — created when `certificates.provider` is Bundled or External | +| `clusterPackages.kyverno.enabled` | EducatesClusterConfig | implicit via `spec.policyEnforcement.kyverno.provider: Bundled` | +| `clusterPackages.kapp-controller.enabled` | — | Dropped | +| `clusterSecurity.policyEngine` | EducatesClusterConfig | `spec.policyEnforcement.clusterPolicy.engine` | +| `workshopSecurity.rulesEngine` | EducatesClusterConfig | `spec.policyEnforcement.workshopPolicy.engine` | +| `clusterIngress.domain` | EducatesClusterConfig | `spec.ingress.domain` | +| `clusterIngress.tlsCertificateRef` | EducatesClusterConfig | Managed: `spec.ingress.certificates.staticCertificate.tlsSecretRef`; Inline: `spec.inline.ingress.wildcardCertificateSecretRef` | +| `clusterPackages.educates.settings.imageVersions[]` | SessionManager | `spec.images.overrides[]` | +| `clusterPackages.educates.settings.clusterIngress` | EducatesClusterConfig | `spec.ingress.*` (no duplication) | +| `clusterPackages.educates.settings.clusterSecurity` | EducatesClusterConfig | `spec.policyEnforcement.clusterPolicy` | +| `clusterPackages.educates.settings.workshopSecurity` | EducatesClusterConfig | `spec.policyEnforcement.workshopPolicy` | +| `lookupService.enabled` | — | Implicit: create a `LookupService` CR to enable | +| `lookupService.ingressPrefix` | LookupService | `spec.ingress.prefix` | + +--- + +## Example scenarios + +### Scenario A — Local kind development (Managed, CustomCA) + +```yaml +--- +apiVersion: config.educates.dev/v1alpha1 +kind: EducatesClusterConfig +metadata: + name: cluster +spec: + mode: Managed + infrastructure: + provider: Kind + ingress: + domain: educates.test + ingressClassName: contour + controller: + provider: BundledContour + bundledContour: + operational: + replicas: 1 + certificates: + provider: BundledCertManager + bundledCertManager: + issuerType: CustomCA + customCA: + caCertificateRef: + name: educates.test-ca + dns: + provider: None + policyEnforcement: + clusterPolicy: + engine: Kyverno + workshopPolicy: + engine: Kyverno + kyverno: + provider: Bundled +--- +apiVersion: platform.educates.dev/v1alpha1 +kind: SecretsManager +metadata: + name: cluster +spec: {} +--- +apiVersion: platform.educates.dev/v1alpha1 +kind: SessionManager +metadata: + name: cluster +spec: {} +--- +# Optional +apiVersion: platform.educates.dev/v1alpha1 +kind: LookupService +metadata: + name: cluster +spec: + ingress: + prefix: educates-api +``` + +### Scenario B — GKE production (Managed, ACME DNS01 via CloudDNS) + +```yaml +--- +apiVersion: config.educates.dev/v1alpha1 +kind: EducatesClusterConfig +metadata: + name: cluster +spec: + mode: Managed + infrastructure: + provider: GKE + cloud: + project: educates-testing + region: us-central1 + serviceAccounts: + certManager: demo-cert-manager@educates-testing.iam.gserviceaccount.com + externalDNS: demo-external-dns@educates-testing.iam.gserviceaccount.com + ingress: + domain: gcp.educates.academy + ingressClassName: contour + controller: + provider: BundledContour + bundledContour: + operational: + replicas: 2 + certificates: + provider: BundledCertManager + bundledCertManager: + issuerType: ACME + acme: + email: ops@educates.academy + solvers: + dns01: + provider: CloudDNS + cloudDNS: + zone: educates-academy-zone + # project inherited from infrastructure.cloud.project + dns: + provider: BundledExternalDNS + policyEnforcement: + clusterPolicy: + engine: Kyverno + workshopPolicy: + engine: Kyverno + kyverno: + provider: Bundled +--- +apiVersion: platform.educates.dev/v1alpha1 +kind: SecretsManager +metadata: + name: cluster +spec: {} +--- +apiVersion: platform.educates.dev/v1alpha1 +kind: SessionManager +metadata: + name: cluster +spec: {} +``` + +### Scenario C — EKS production (Managed, ACME DNS01 via Route53, mirrored registry) + +```yaml +apiVersion: config.educates.dev/v1alpha1 +kind: EducatesClusterConfig +metadata: + name: cluster +spec: + mode: Managed + infrastructure: + provider: EKS + cloud: + project: "123456789012" # AWS account ID + region: eu-west-1 + serviceAccounts: + certManager: arn:aws:iam::123456789012:role/educates-cert-manager + externalDNS: arn:aws:iam::123456789012:role/educates-external-dns + ingress: + domain: aws.educates.example.com + ingressClassName: contour + controller: + provider: BundledContour + bundledContour: + operational: + replicas: 3 + certificates: + provider: BundledCertManager + bundledCertManager: + issuerType: ACME + acme: + email: ops@example.com + solvers: + dns01: + provider: Route53 + route53: + hostedZoneID: Z1234ABCDEFGHI + dns: + provider: BundledExternalDNS + policyEnforcement: + clusterPolicy: + engine: Kyverno + workshopPolicy: + engine: Kyverno + kyverno: + provider: Bundled + imageRegistry: + prefix: 123456789012.dkr.ecr.eu-west-1.amazonaws.com/educates + pullSecrets: + - name: ecr-pull-secret +``` + +### Scenario D — Partial BYO (Managed, mixed bundled and external) + +Existing Contour and Kyverno; operator manages cert-manager only. + +```yaml +apiVersion: config.educates.dev/v1alpha1 +kind: EducatesClusterConfig +metadata: + name: cluster +spec: + mode: Managed + infrastructure: + provider: Generic + ingress: + domain: educates.example.com + ingressClassName: contour # existing IngressClass + controller: + provider: ExternalIngressController + certificates: + provider: BundledCertManager + bundledCertManager: + issuerType: ACME + acme: + email: ops@example.com + solvers: + dns01: + provider: Cloudflare + cloudflare: + apiTokenSecretRef: + name: cloudflare-token + dns: + provider: Manual + policyEnforcement: + clusterPolicy: + engine: Kyverno + workshopPolicy: + engine: Kyverno + kyverno: + provider: External # existing Kyverno +``` + +### Scenario E — Full BYO on OpenShift (Inline mode) + +User has cert-manager, ingress, SCC, Kyverno all in place; wildcard cert pre-provisioned. + +```yaml +--- +apiVersion: config.educates.dev/v1alpha1 +kind: EducatesClusterConfig +metadata: + name: cluster +spec: + mode: Inline + inline: + ingress: + domain: apps.openshift.example.com + ingressClassName: openshift-default + wildcardCertificateSecretRef: + name: educates-wildcard-tls + caCertificateSecretRef: + name: corporate-ca + clusterIssuerRef: + name: letsencrypt-prod + policyEnforcement: + clusterPolicyEngine: OpenShiftSCC + workshopPolicyEngine: Kyverno +--- +apiVersion: platform.educates.dev/v1alpha1 +kind: SecretsManager +metadata: + name: cluster +spec: {} +--- +apiVersion: platform.educates.dev/v1alpha1 +kind: SessionManager +metadata: + name: cluster +spec: {} +``` + +### Scenario F — Standalone LookupService (Inline, no cluster services) + +```yaml +--- +apiVersion: config.educates.dev/v1alpha1 +kind: EducatesClusterConfig +metadata: + name: cluster +spec: + mode: Inline + inline: + ingress: + domain: lookup.example.com + ingressClassName: nginx + wildcardCertificateSecretRef: + name: lookup-wildcard-tls + policyEnforcement: + clusterPolicyEngine: None + workshopPolicyEngine: None +--- +apiVersion: platform.educates.dev/v1alpha1 +kind: LookupService +metadata: + name: cluster +spec: + ingress: + prefix: api + # URL: https://api.lookup.example.com +``` + +--- + +## Open items for v1alpha1 → v1beta1 + +1. **SessionManager.spec.themes structure** — owner review needed. +2. **LookupService component-specific settings** (auth, rate limiting, storage) — owner review needed. +3. **external-dns explicit zones** — deferred, add if needed. +4. **Per-service operational shapes** — the shared `operational` block was removed from bundledCertManager / bundledExternalDNS / kyverno on 2026-06-11 (only bundledContour keeps it). When concrete scaling/scheduling needs emerge, each service gains its own shape validated against its upstream chart: cert-manager needs per-deployment sub-blocks (controller + webhook + cainjector), Kyverno needs per-controller counts honouring its HA rules, external-dns stays single-instance. +5. **Inline-mode re-validation on external changes** — implementation detail. With watches set up on referenced resources, validation runs on every change. Confirm behavior matches expectation. +6. **Validation error surfacing** — condition messages should be specific enough to guide fixes. Review wording during implementation. + +--- + +## What's intentionally NOT in this draft + +- Dev-mode overrides (`--package-repository`, `--version`) — CLI flags only. +- Per-image digest pinning in spec — release-artifact concern. +- Multi-instance support — singleton via name constraint. +- Cross-cluster references — each cluster self-contained. +- Old-config compatibility — `educates migrate-config` CLI handles translation. +- Raw Helm values passthrough — curated operational blocks only. +- Managed ↔ Inline mode transitions — explicitly unsupported; requires delete + recreate. diff --git a/docs/architecture/educates-current-state.md b/docs/architecture/educates-current-state.md new file mode 100644 index 000000000..24efe3906 --- /dev/null +++ b/docs/architecture/educates-current-state.md @@ -0,0 +1,321 @@ +# Educates Training Platform — Current State Summary + +> Source: public documentation at docs.educates.dev and educates.dev blog posts (accessed April 2026), +> plus the repository at github.com/educates/educates-training-platform (structure deduced from +> vendir.yml, release artifacts, and issues — not from direct code reading). +> +> **Confidence levels:** +> - **High confidence:** installer CLI behavior, config structure, supported providers, cluster packages. +> - **Medium confidence:** exact repo directory layout (deduced, not browsed file-by-file). +> - **Inferred:** runtime operator internals (session-manager, training-portal) — known to be Python+kopf +> from error logs, but not studied in detail for this summary. + +--- + +## 1. What Educates Is + +A Kubernetes-based platform for hosting interactive workshop environments. Self-hosted, CNCF-adjacent, +Apache 2.0. Spun out of VMware/Broadcom, now independent. + +**Core runtime components** (deployed into the cluster, not the installer): + +- `session-manager` — Python/kopf operator managing `Workshop`, `WorkshopEnvironment`, `WorkshopSession`, `WorkshopRequest`. +- `training-portal` — user-facing web UI for browsing/starting workshops, plus REST API. +- `secrets-manager` — custom secret copier/injector (replaces Carvel secretgen for security reasons). +- `tunnel-manager` — for exposing services out of workshop sessions. +- `lookup-service`, `assets-server`, `image-cache`, `docker-registry` — supporting services. +- Workshop runtime images: `base-environment`, `jdk{8,11,17,21}-environment`, `conda-environment`, `docker-in-docker`, `loftsh-vcluster`, multiple `rancher-k3s` versions. + +**Core CRDs** (`training.educates.dev/v1beta1`): + +- `TrainingPortal` — top-level, what admins create to expose workshops. +- `Workshop` — definition of a single workshop. +- `WorkshopEnvironment`, `WorkshopSession`, `WorkshopRequest` — internal, created by the training portal. + +--- + +## 2. Current Installer Architecture (Educates 3.x) + +### The CLI + +- Binary name: `educates` +- Language: **Go** +- Distribution: single-binary releases for `{darwin,linux}-{amd64,arm64}`. +- Key design choice: **embeds Carvel tools as Go libraries**, not as shell-outs. Uses ytt for templating, kbld for image resolution, kapp for apply/reconcile. This is in-process, no external binaries needed at runtime. + +### The two installation paths (must produce equivalent cluster state) + +**Path 1 — Imperative (CLI):** +``` +educates deploy-platform --config config.yaml [--verbose] +``` +- User runs CLI from their laptop / CI. +- CLI reads config, expands it via YTT, resolves images, applies via kapp. +- Blocks until reconciled. +- Counterpart: `educates delete-platform` (or similar; exact name TBD). + +**Path 2 — Declarative (kapp-controller):** +```bash +# 1. Install kapp-controller (if not already present) +kubectl apply -f https://github.com/vmware-tanzu/carvel-kapp-controller/releases/latest/download/release.yml + +# 2. Install RBAC (namespace educates-installer is created here) +kubectl apply -f https://github.com/educates/educates-training-platform/releases/latest/download/educates-installer-app-rbac.yaml + +# 3. Create the config secret +kubectl create secret generic educates-installer -n educates-installer \ + --from-file config.yaml --save-config + +# 4. Create the App CR that references the installer bundle +kubectl apply -f https://github.com/educates/educates-training-platform/releases/latest/download/educates-installer-app.yaml +``` +- kapp-controller reconciles the App CR. +- Updates: replace the secret; kapp-controller re-reconciles (or `kctrl app kick -a installer.educates.dev -n educates-installer`). +- Uninstall: `kubectl delete -n educates-installer app/installer.educates.dev`. + +### Additional CLI commands worth knowing + +- `educates create-cluster` — local kind cluster + platform (all in one). +- `educates delete-cluster` — tears down local kind cluster. +- `educates admin platform config --local-config` — generate a minimal config template. +- `educates admin platform values --local-config` — show the expanded internal values (after YTT transformation). This is the "internal" view. +- `educates local config` — local environment settings (resolvers, mirrors etc.). +- `educates deploy-workshop -f ` — deploy an individual workshop. +- `educates cluster workshop-request` — test portal REST API. + +### Key observation: two configurations today + +1. **User-facing config** (what they write) — minimal, e.g.: + ```yaml + clusterInfrastructure: + provider: kind + clusterPackages: + contour: {enabled: true} + kyverno: {enabled: true} + educates: {enabled: true} + clusterSecurity: {policyEngine: kyverno} + clusterIngress: {domain: 172.20.10.12.nip.io} + workshopSecurity: {rulesEngine: kyverno} + ``` + +2. **Expanded internal values** (what actually drives the installer) — detailed, per-package, with image pins, per-provider defaults. Produced by YTT transformation of (1). + +Same schema top-level, different level of detail. This duality is one of the pain points the user flagged. + +--- + +## 3. Configuration Schema (Current) + +Top-level sections: + +| Section | Purpose | Example keys | +|---------|---------|-------------| +| `clusterInfrastructure` | Which K8s flavour + cloud-specific params | `provider`, `gcp.*`, `aws.*` | +| `clusterPackages` | Which cluster services to install and how | `contour`, `cert-manager`, `external-dns`, `certs`, `kyverno`, `kapp-controller`, `educates` | +| `clusterSecurity` | Cluster-wide policy engine | `policyEngine`: kyverno / pod-security-policies / security-context-constraints | +| `clusterIngress` | Ingress domain config | `domain`, TLS refs | +| `workshopSecurity` | Per-workshop policy engine | `rulesEngine`: kyverno | + +**Supported infrastructure providers:** + +- `kind` — local Docker-based +- `minikube` — local +- `eks` — Amazon EKS (needs `aws.region`, `aws.route53.hostedZone`, `aws.irsaRoles.{external-dns,cert-manager}`) +- `gke` — Google GKE (needs `gcp.project`, `gcp.cloudDNS.zone`, `gcp.workloadIdentity.{external-dns,cert-manager}`) +- `openshift` — uses SCC instead of kyverno for cluster security, native OpenShift ingress +- `vcluster` — Loft vCluster (minimal install, no ingress controller from installer) +- `generic` — user brings ingress + DNS, installer does minimum +- `custom` — user provides everything themselves + +**Cluster packages (things the installer installs alongside Educates):** + +| Package | Default state | Purpose | +|---------|---------------|---------| +| `contour` | Usually enabled (not on vcluster/openshift) | Ingress controller | +| `cert-manager` | Enabled on eks/gke | TLS cert management | +| `external-dns` | Enabled on eks/gke | DNS record management | +| `certs` | Enabled on eks/gke | Creates ACME wildcard ClusterIssuer | +| `kyverno` | Enabled by default | Policy engine (cluster + workshop) | +| `kapp-controller` | Enabled only on specific cases | Needed if workshops themselves use it | +| `educates` | Always enabled | The actual training platform | + +--- + +## 4. Repo Structure (Deduced) + +``` +educates-training-platform/ +├── README.md +├── vendir.yml # Tracks upstream vendored deps +├── project-docs/ # Sphinx docs (what's at docs.educates.dev) +├── carvel-packages/ +│ └── installer/ +│ └── bundle/ +│ └── config/ +│ └── ytt/ +│ └── _ytt_lib/ +│ ├── infrastructure/ # Per-provider overlays +│ │ ├── kind/ +│ │ ├── gke/ +│ │ ├── eks/ +│ │ ├── openshift/ +│ │ ├── vcluster/ +│ │ └── ... +│ └── packages/ # Each cluster service +│ ├── cert-manager/ +│ │ └── upstream/ # Vendored via vendir +│ ├── contour/ +│ ├── external-dns/ +│ ├── kyverno-restricted/ +│ ├── kyverno-baseline/ +│ ├── kyverno-policies/ +│ └── educates/ # The training platform chart/ytt +├── client-programs/ # Likely the Go CLI source +├── session-manager/ # Python/kopf operator +├── training-portal/ # Python/Django web app +├── secrets-manager/ # Python/kopf operator +├── tunnel-manager/ # Likely Go +├── workshop-images/ +│ ├── base-environment/ +│ ├── jdk8-environment/ +│ ├── jdk11-environment/ +│ └── ... +└── [other component directories] +``` + +Related repos in the `educates` org: +- `educates-training-platform` — main monorepo (above) +- `lab-*` — sample workshops +- `labs-installation-guides` — workshops about installation +- `educatesenv` — version manager for the CLI + +--- + +## 5. Local vs Cloud Differences + +### Local (`kind`, `minikube`) + +- Ingress: Contour bound to `hostPorts` so it's reachable via `localhost`. +- DNS: `nip.io` (embeds IP in hostname) or Educates Local Resolver (macOS DNS resolver config). +- Registry: local image registry deployed alongside the cluster. +- TLS: self-managed certs (CLI manages a local CA). +- Policy: kyverno (default). +- No external-dns, no cert-manager. +- One-command: `educates create-cluster` does kind + registry + platform. + +### Cloud (`gke`, `eks`) + +- Ingress: Contour with a cloud LB service. +- DNS: external-dns reconciling Route53 / Cloud DNS, needs IAM/Workload Identity. +- TLS: cert-manager with ACME ClusterIssuer. +- Workload identity must be set up *before* installer runs. +- No one-command; user creates cluster first, then `educates deploy-platform`. + +### vCluster / OpenShift + +- Assume the host cluster has ingress + DNS handled. +- Install only Educates + minimal policy (Kyverno or OpenShift SCC). + +--- + +## 6. Known Pain Points (From User's Own Framing) + +1. **Carvel is poorly maintained** (former team gone, mostly dependabot updates). +2. **Owning the "cluster services" story** (cert-manager, external-dns, kyverno, contour, kapp-controller) is a drag — updates lag because installer vendors them. +3. **kapp is great imperatively, but the declarative story requires kapp-controller** — users don't want it. +4. **Two configurations** (user config + expanded internal config) is a duality users don't see but that shapes the implementation. +5. **Configuration mixes three concerns** that should be separate: local-dev-only settings, infrastructure provider config, Educates-proper config. + +--- + +## 7. Proposed Future Architecture (Validated) + +### High-level shape + +``` +┌──────────────────────────────────────────┐ +│ User runs `helm install educates-...` │ +│ OR points ArgoCD/Flux at it │ +└──────────────┬───────────────────────────┘ + │ + ▼ +┌──────────────────────────────────────────┐ +│ Thin Helm chart: educates-installer │ +│ - Installs operator Deployment │ +│ - Installs CRDs (EducatesPlatform + ... )│ +│ - Installs RBAC │ +└──────────────┬───────────────────────────┘ + │ + ▼ +┌──────────────────────────────────────────┐ +│ User (or CLI) applies EducatesPlatform CR│ +│ (cluster-scoped, named `cluster`) │ +│ │ +│ spec.infrastructure: ... │ +│ spec.clusterServices: ... │ +│ spec.educates: ... │ +└──────────────┬───────────────────────────┘ + │ reconciled by + ▼ +┌──────────────────────────────────────────┐ +│ Go operator (new) │ +│ - Uses Helm Go SDK to install upstream │ +│ charts: cert-manager, contour, │ +│ external-dns, kyverno │ +│ - Creates ClusterIssuer, Certificate │ +│ etc. as CRs after deps are ready │ +│ - Installs educates-training-platform │ +│ Helm chart │ +│ - Has finalizer → clean uninstall in │ +│ reverse order │ +└──────────────┬───────────────────────────┘ + │ + ▼ +┌──────────────────────────────────────────┐ +│ Educates runtime (unchanged): │ +│ - session-manager (Python/kopf) │ +│ - training-portal (Python/Django) │ +│ - secrets-manager │ +│ - etc. │ +└──────────────────────────────────────────┘ +``` + +### CLI role (thin) + +- `educates install` → `helm install` + `kubectl apply` of CR (or just renders, user applies). +- `educates uninstall` → delete CR (wait for finalizer) + `helm uninstall`. +- `educates apply -f config.yaml` → render CR and apply. +- `educates render -f config.yaml` → output CR to stdout (for GitOps). +- Local-dev-only commands (`create-cluster`, `delete-cluster`) stay as they are — they're orthogonal to the platform install, they're about kind setup + calling the platform install. + +### Where current pieces map + +| Current | Future | +|---------|--------| +| Go CLI with embedded Carvel libs | Go CLI (much thinner) + Go operator (new) | +| Carvel bundles vendoring cert-manager etc. | Helm SDK calls to upstream charts | +| YTT overlays for per-provider config | Operator Go code (switch on `spec.infrastructure.provider`) | +| ytt-rendered Educates manifests | `educates-training-platform` Helm chart | +| Config secret + App CR | `EducatesPlatform` CR (singleton) | +| Python/kopf session-manager, training-portal | **Unchanged** — these are runtime, not install | + +### What we'd NOT rewrite + +- `session-manager` (Python/kopf) — leave it. +- `training-portal` (Python/Django) — leave it. +- `secrets-manager` — leave it. +- Workshop image build pipeline — leave it. + +The migration is purely about the installer + CLI. Everything else is fine. + +--- + +## 8. Open Questions to Validate Before Implementation + +1. Which user flows must remain unchanged? (e.g., `educates create-cluster` one-shot on a laptop) +2. Does "one `EducatesPlatform` per cluster" hold? (Answered: yes, per earlier conversation.) +3. Will the new CR schema be `v1alpha1` with an explicit migration path from the old YAML config? +4. Does the local `kind` flow need to bypass the operator entirely (since it's known-good)? Or go through the same code path as cloud? +5. What's the strategy for upstream chart versions — vendored as values, or discovered at runtime? +6. For `cert-manager` specifically, what's the ordering contract? (Install chart → wait for webhook ready → create ClusterIssuer → wait for ready → install rest.) +7. Are users OK with a persistent operator in-cluster, or should we consider a run-once Job model as simpler alternative? diff --git a/docs/architecture/educates-v4-development-plan.md b/docs/architecture/educates-v4-development-plan.md new file mode 100644 index 000000000..3b0fc648c --- /dev/null +++ b/docs/architecture/educates-v4-development-plan.md @@ -0,0 +1,850 @@ +# Educates v4 Installer — Development Plan + +> **Status:** Living document. Update as decisions are made and phases complete. +> **Owner:** Solo work, primary developer + Claude as collaborator. +> **Target:** Educates v4 — breaking change from v3, replacing the Carvel-based +> installer with a Helm chart + Go operator while leaving the runtime +> (session-manager, secrets-manager, lookup-service, training-portal, +> workshop images) functionally unchanged. + +--- + +## 1. What we're building, and why + +### Goals + +- Replace the Carvel-based installer (ytt + kbld + kapp + kapp-controller) with a Helm chart + Go operator. +- Preserve a single user-facing workflow that works identically for imperative install (CLI) and declarative install (GitOps via ArgoCD/Flux). +- Provide opinionated zero-to-hero installation while supporting Bring-Your-Own (BYO) for cluster services like cert-manager, ingress controllers, policy engines. +- Cleanly separate three configuration concerns: local laptop setup, cluster infrastructure + services, Educates-specific runtime. +- Establish a path off Carvel, which is poorly maintained and burdensome to keep current. + +### Non-goals + +- Re-implementing or modifying the Educates runtime (session-manager, secrets-manager, lookup-service, training-portal, workshop images, tunnel-manager). +- Backwards compatibility with the v3 configuration format at runtime. A one-shot migration tool will translate v3 configs to v4 CRs; nothing else. +- Multi-tenant Educates installations on a single cluster. +- Cross-cluster references between component CRs. + +### Scope of the v4 change + +- **Replaces:** `carvel-packages/installer/`, the kapp-based deploy/delete CLI commands, the YTT/kbld toolchain. +- **Adds:** A new Go operator with four CRDs, a Helm chart for the operator, a Helm chart for the Educates runtime (with three subcharts: secrets-manager, lookup-service, session-manager), thinner CLI commands wrapping these. +- **Touches but doesn't change:** The CLI's local-cluster commands (`educates local cluster create`, etc.) — they'll still work, but their internals call the new install path. +- **Leaves alone:** Everything in `session-manager/`, `secrets-manager/`, `training-portal/`, `lookup-service/`, `tunnel-manager/`, `workshop-images/`, `node-ca-injector/`, `assets-server/`, `image-cache/`. These continue to function exactly as in v3. + +### Reference documents + +These should live in `docs/architecture/` once the repo is set up: + +- **`crd-draft-v1alpha1.md`** — the four CRD designs (EducatesClusterConfig, SecretsManager, LookupService, SessionManager). Currently at revision 3. +- **`installer-research.md`** — the survey of how kube-prometheus-stack, ArgoCD, Flux, Backstage, Crossplane, Tanzu handle multi-chart packaging. Background context for design choices. +- **This document** — the development plan. + +--- + +## 2. Architecture summary + +### High-level shape + +``` +User runs `helm install` (or points GitOps at it) + ↓ +educates-installer Helm chart + - operator Deployment + - 4 CRDs (cluster-scoped) + - RBAC + ↓ +User (or CLI) applies CRs: + - EducatesClusterConfig (singleton, named 'cluster') + - SecretsManager (singleton, named 'cluster') + - SessionManager (singleton, named 'cluster') + - LookupService (singleton, named 'cluster', optional) + ↓ +Operator reconciles each CR: + - EducatesClusterConfig in Managed mode: installs cluster services + (cert-manager, contour, kyverno, external-dns) via Helm SDK, + creates ClusterIssuer + Certificate, publishes status. + - EducatesClusterConfig in Inline mode: validates user-provided refs, + publishes status without installing anything. + - Component CRs read EducatesClusterConfig.status, install via the + educates-training-platform Helm chart's relevant subchart, watch + dependencies (e.g., SessionManager waits on SecretsManager.Ready). + ↓ +Educates runtime (unchanged from v3): + - secrets-manager + - session-manager + training-portal + - lookup-service +``` + +### Key design decisions (already made) + +| Decision | Choice | +|---|---| +| Install mechanism | Helm chart for the operator + 4 cluster-scoped singleton CRDs | +| Operator language | Go with controller-runtime / Kubebuilder | +| Cluster-service installation | Helm Go SDK calls to upstream charts (no vendoring) | +| Runtime packaging | One umbrella chart `educates-training-platform` with three subcharts | +| Configuration approach | Capability-oriented CRDs (e.g., `certificates.provider`) not config dumps | +| BYO support | Each cluster service has a `Bundled | External` discriminator | +| Mode model | EducatesClusterConfig has `mode: Managed | Inline` (immutable) | +| CRD validation | CEL for structural; reconciler for semantic; no admission webhooks in v1alpha1 | +| Default policy engine | Kyverno (cluster + workshop), explicitly opt-out | +| Image relocation | Build-time wrap with `helm dt` (or equivalent) for air-gapped; `imageRegistry.prefix` on CR for online mirroring | +| Air-gapped digest pinning | Out of scope for v1alpha1; published values files per release | +| Multi-component dependency | SessionManager requires SecretsManager.Ready; runtime check, not spec field | +| Status as interface | EducatesClusterConfig.status is the contract components consume | +| Singleton enforcement | CEL rule: `metadata.name == 'cluster'` | +| CRD versioning | Start at v1alpha1; expect breaking changes before v1beta1 | + +--- + +## 3. Phased plan + +Work proceeds in sequenced phases. Each phase has a definition of done that must be met before the next phase starts. + +### Pre-phase: educates-training-platform Helm chart (1–2 weeks) + +**Build this in parallel with Phase 0.** It's separable from the operator and de-risks Phase 4 substantially. + +**What to build:** +- Umbrella chart `educates-training-platform`. +- Three subcharts: + - `secrets-manager` — installs the existing secrets-manager Deployment with values for image, log level, image pull secrets, resources. + - `lookup-service` — installs the existing lookup-service with values for ingress (hostname, TLS), image, log level, resources. + - `session-manager` — installs session-manager, training-portal, and supporting services (assets-server, image-cache, docker-registry) with values for domain, TLS, themes, registry mirrors, image overrides. +- Dependencies declared with `condition` flags so subcharts can be enabled/disabled. +- Image refs use values placeholders so `helm dt wrap`/`unwrap` can relocate them. + +**Done when:** +- `helm install educates-training-platform ./chart -f values-test.yaml` works against a kind cluster with manually-set-up cert-manager + contour + kyverno + a wildcard cert. +- All three subcharts can be enabled/disabled independently. +- The runtime works end-to-end: user can browse to the training portal, request a workshop, get a session. + +**Why first:** This proves the runtime *can* be installed via Helm. It's a reality-check on the whole approach. If something about the runtime resists Helm packaging, you want to know now, not in Phase 4. + +**Note:** This chart is what the Educates project will publish ongoing as the canonical Helm install for the runtime. Even users who don't want the operator can `helm install educates-training-platform`. + +### Pre-phase follow-up: bundle v3 Kyverno policies into the chart *(done — 2026-04)* + +Vendored into the `session-manager` subchart in commit `8e659b5c` under +`installer/charts/educates-training-platform/charts/session-manager/files/kyverno-policies/`: + +- `cluster-policies/` — applied directly as cluster-wide ClusterPolicy + resources (mirrors v3's `01-clusterpolicies.yaml`: PSS baseline + + restricted profiles plus operational best-practices). +- `workshop-policies/` — concatenated into the `kyverno-policies.yaml` + key of the `educates-config` Secret; session-manager clones each rule + per workshop environment with a namespace selector added (mirrors v3's + `06-secrets.yaml` feed). + +Source provenance is recorded in `files/kyverno-policies/README.md`. +Kyverno *engine* installation remains out of scope for the runtime +chart — that's the operator's job at cluster-services scope (Phase 2/3). + +The current toggle shape (`bundledKyvernoPolicies.{cluster,workshop}Policies`, +`additionalKyvernoPolicies.{cluster,workshop}Policies`, `openshift.enabled`) +is superseded by `clusterSecurity` / `workshopSecurity` in the typed-values +follow-up below; the on-disk policy files do not move. + +### Pre-phase follow-up: typed runtime-config values *(done — 2026-04-30)* + +Landed in commits `41fab46f` (typed session-manager values + JSON +schema), `2a14a50c` (scenarios converted to typed values), and +`ea3c6cae` (decisions.md superseding entry). The "Done when" criteria +below were all met; later refactors promoted `imageRegistry` under +`development.` and cross-cutting values to umbrella `global:` (see +decisions.md). Original section preserved below for the rationale. + +**Trigger met (2026-04):** scenarios 01–06 now cover local-HTTP, TLS +wildcard, cert-manager issuer, website theme, image-pull secrets, and +additional Kyverno policies. That's enough validation surface to +refactor the values shape against without regressing tested behaviour. + +**Canonical target shape:** + +The full target values surface and JSON schema live as docs-of-record at: + +- `docs/architecture/session-manager-chart-values.yaml` +- `docs/architecture/session-manager-chart-values-schema.json` + +These are the source of truth for this follow-up. If something below +diverges from those documents, the documents win — update the plan, not +the docs. + +**Problem this solves:** + +The current pre-phase chart has the well-known runtime config as an +opaque map under `session-manager.config`, plus a separately-typed +`session-manager.secretPropagation` block, plus ad-hoc toggles for +Kyverno bundling and OpenShift. The same input often appears twice in +slightly different forms (e.g., the wildcard TLS Secret name + +namespace shows up both as runtime config and as secret-propagation +upstream). Standalone chart users (the audience for the pre-phase +chart per its own "Note" above) end up needing to know the v3 schema +by heart and write opaque YAML for most of the runtime config. + +**What to build:** + +Refactor the `session-manager` subchart `values.yaml` and JSON schema to +match the docs-of-record. Concretely, promote out of `config` and +restructure into these top-level blocks (full field list in the doc): + +- `clusterIngress` — `domain` (required after merging with `.global.clusterIngress`), + `class`, `protocol` (auto from TLS ref), `tlsCertificateRef`, + `caCertificateRef`, `caNodeInjector.enabled`. Promoted to umbrella + `global.clusterIngress` so lookup-service (Ingress) and session-manager + (chart-rendered ca-trust-store init container) read a single source of + truth. +- `clusterSecurity` — `policyEngine: Kyverno | PodSecurityStandards | + OpenShiftSCC | None`, `additionalKyvernoPolicies[]`. Promoted to + umbrella `global.clusterSecurity` so SCC ClusterRoleBindings in BOTH + session-manager and secrets-manager are gated on the same value. + Replaces the previous `bundledKyvernoPolicies.clusterPolicies` toggle, + the per-subchart `openshift.enabled` toggles, and + `additionalKyvernoPolicies.clusterPolicies`. +- `workshopSecurity` — `rulesEngine: Kyverno | None`, + `additionalKyvernoPolicies[]`. Replaces + `bundledKyvernoPolicies.workshopPolicies` and + `additionalKyvernoPolicies.workshopPolicies`. +- `development.imageRegistry` — local-development override (subchart- + local + umbrella `global.development.imageRegistry`). Empty by default; + publish-time defaults come from Chart.yaml annotations + (`educates.dev/image-registry-host` / `-namespace`, updated per-fork by + the release workflow). When set, ONE knob redirects both (a) chart- + rendered + runtime-spawned Educates image refs and (b) the + `IMAGE_REPOSITORY` env var workshop sessions see for `$(image_repository)` + content placeholder resolution. Mirrors v3's `imageRegistry` schema knob. + Upstream pins (docker-in-docker, loftsh-*, debian-base) are NOT + relocated; override their `imageVersions` entries directly when + mirroring. +- `imageVersions[]` — empty by default; chart-shipped defaults are + produced by the `session-manager.imageVersions` template helper, + mirroring v3's `images.yaml`. Educates-published entries derive their + tag from `Chart.AppVersion`; upstream pins (`docker-in-docker`, + `loftsh-*`, `debian-base`) are hard-coded to specific tags. User + values are merged BY NAME — overrides replace just the matching + default, other defaults pass through, names not in the default list + are appended (forward-compat). Used for airgap relocation and feature- + image variants. +- Top-level `image`, `imagePullSecrets[]` (chart-pod pull only — distinct + from `secretPropagation.imagePullSecretNames`), `resources`, + `clusterAdmin` (default `false`, changed from v3 default of `true`). +- `trainingPortal.credentials.{admin,robot}` and + `trainingPortal.clients.robot` — empty-by-default; runtime generates. +- `sessionCookies.domain`. +- `clusterStorage` — `class`, `user`, `group`. +- `clusterRuntime.class`. +- `clusterNetwork.blockCIDRs[]` — defaults to AWS metadata IPv4 + IPv6. +- `dockerDaemon` — `networkMTU`, `proxyCache.{remoteURL,username,password}`. +- `workshopAnalytics` — `google`, `clarity`, `amplitude`, `webhook`. +- `websiteStyling` — replaces flat `websiteTheme: {}` map. Structured + inline blocks (`workshopDashboard`, `workshopInstructions`, + `workshopStarted`, `workshopFinished`, `trainingPortal`) plus + `defaultTheme`, `themeDataRefs[]`, `frameAncestors[]`. +- `imagePrePuller` — `enabled`, `pauseImage`, `images[]` (renamed from + v3's `imagePuller` / `prePullImages`; see decisions log). +- `secretPropagation` — `imagePullSecretNames[]` and + `upstream.{imagePullSecrets,websiteThemes}[]`. The `upstream.ingressTLS` + and `upstream.ingressCA` fields are **removed** — auto-derived from + `clusterIngress.tlsCertificateRef.namespace` and + `clusterIngress.caCertificateRef.namespace` when those differ from the + release namespace. +- `config` — opaque escape hatch, deep-merged on top of the + typed-derived `educates-operator-config.yaml` Secret content. + +The chart composes the `educates-config` Secret from these typed values. +Auto-creates SecretCopiers for ingress TLS/CA, themes, and pull secrets +whose source namespace differs from the release namespace. + +**Defaulting policy — important note:** + +Be deliberate about what the chart defaults vs. what it leaves empty for +the session-manager runtime to handle: + +- **Empty is correct for `trainingPortal.credentials.*` and + `trainingPortal.clients.robot.*`** — most installs leave these unset, + and the session-manager's `operator_config.py` already has + `generate_password(...)` fallbacks that produce the right thing at + runtime. The chart **must not** materialise `randAlphaNum`-generated + values for these — they would rotate on every `helm upgrade` and break + workshops mid-session. The session-manager owns credential generation; + the chart only renders user-supplied values when present. +- **Sensible defaults are fine for** `clusterIngress.protocol` (auto + `http` when no `tlsCertificateRef`, `https` otherwise — matches the + runtime's own derivation), `clusterSecurity.policyEngine` (default + `Kyverno` per the v4 mode decision), `workshopSecurity.rulesEngine` + (default `Kyverno`), `clusterStorage.group` (default `1`), + `clusterNetwork.blockCIDRs` (default AWS metadata IPv4 + IPv6), + `clusterAdmin` (default `false`), `dockerDaemon.networkMTU` (default + `1400`). +- **No defaults — required input** for `clusterIngress.domain`. The + chart fails fast at template time if missing, not silently fall through + to the runtime's `educates-local-dev.test` fallback. + +**Validation:** + +Add a JSON schema (`values.schema.json`) to the subchart, derived from +`docs/architecture/session-manager-chart-values-schema.json`. Helm +enforces it on `helm install`/`upgrade`/`template`, catching shape errors +before they reach the runtime. + +**Done when:** + +- The `session-manager` subchart `values.yaml` matches the shape in the + docs-of-record. +- A `values.schema.json` exists in the subchart and matches the schema + doc. +- All six existing scenarios (`01-local-http-nip-io`, `02-kind-tls-wildcard`, + `03-kind-cert-manager-issuer`, `04-website-theme`, + `05-image-pull-secrets`, `06-additional-kyverno-policies`) pass after + their `chart-values.yaml` files are updated to the typed shape (no + `config:` block needed for the cases they cover; no + `secretPropagation.upstream.ingressTLS/ingressCA`; no + `bundledKyvernoPolicies` / `additionalKyvernoPolicies.{cluster,workshop}Policies` + / `openshift.enabled`). +- A new scenario exercises one or more still-opaque fields via the + `config:` escape hatch, proving deep-merge semantics. +- `decisions.md` has an entry that supersedes the earlier "Runtime chart + values shape is operator-driven, not v3-driven" decision, with the + reasoning above. + +### Phase 0: Foundations (1–2 weeks) *(done — 2026-05)* + +**Layout (decided 2026-05-06):** +- Operator code: `installer/operator/` — kubebuilder project, with the + generated `config/` kustomize tree stripped. `controller-gen` writes + CRDs and RBAC directly into the operator chart. See decisions log. +- Operator chart: `installer/charts/educates-installer/` — sibling to + `educates-training-platform/`. Installs operator Deployment, RBAC, + and the four CRDs (in `crds/`). +- Module path: `github.com/educates/educates-training-platform/installer/operator`, + added to `go.work`. +- API packages: `api/config/v1alpha1/` (EducatesClusterConfig) and + `api/platform/v1alpha1/` (SecretsManager, LookupService, + SessionManager). + +**What to build:** +- Bootstrap with `kubebuilder init --domain educates.dev` + four + `kubebuilder create api` invocations (groups: `config`, `platform`). + Strip the generated `config/` kustomize tree; `controller-gen` is + pointed at the chart paths instead. +- Translate the r3 CRD draft into Go types with `kubebuilder` markers + (`+kubebuilder:validation:*`, `+kubebuilder:default=*`). + - **Spec: full r3 shape**, including static defaults. + - **Status: minimal** — `observedGeneration`, `phase`, `conditions` + only. Richer status fields (`ingress`, `policyEnforcement`, + `imageRegistry`, `bundledChartVersions`, etc.) are added in the + phase that introduces the reconciler producing them. Avoids dead + API surface. See decisions log. +- Generate CRD manifests (`make manifests`) directly into + `installer/charts/educates-installer/crds/`. +- Add CEL validation rules — Phase 0 scope is narrowed: + - Singleton name (`self.metadata.name == 'cluster'`) on all four CRDs. + - Mode immutability (`self.spec.mode == oldSelf.spec.mode`) on + `EducatesClusterConfig`. + - **Mode-field exclusivity** (Managed fields forbidden when + `mode: Inline`, vice versa) is deferred to Phase 1 — it's + structural validation tied to fields whose semantics Phase 1 is the + first to exercise. +- Four trivial reconcilers wired into the manager: each logs that it + observed the CR and returns. No status writes, no watches on + referenced resources, no finalizers. +- Minimal RBAC in the chart: `get/list/watch/update/patch` on the four + CRDs and their `/status` + `/finalizers` only. Watches on referenced + Secrets/ClusterIssuers/IngressClasses are added in Phase 1 with the + validator. +- Operator image story: `make docker-build` for local development + only. Chart `image.repository`/`tag` defaults to a local-dev + placeholder. Publish-time annotations (mirroring the runtime chart's + `educates.dev/image-*` pattern) are deferred to Phase 6. See + decisions log. +- One envtest spec exercising "valid CR is accepted; CR with + `metadata.name != 'cluster'` is rejected" against each kind. Ginkgo, + in-process apiserver via `setup-envtest`. Runs locally via + `make test`; CI runs the same target. +- Local-only `make smoke-test`: `kind create` + `helm install` + + `kubectl apply` of sample CRs + `kubectl logs` assertion that the + reconcile log line appeared. Not in CI yet — kind-in-CI lands in + Phase 2 alongside chart-install testing. +- CI workflow `installer-operator-ci.yaml`: `make manifests`/`generate` + drift check, `go vet`, `go test` (envtest), `golangci-lint`. +- CLAUDE.md updates pointing at the new directory and conventions. + +**Done when:** +- All four CRDs install into envtest and a kind cluster. +- Applying a valid CR triggers a log line from the operator. +- Applying a CR named anything other than `cluster` is rejected by the + apiserver. +- Mutating `EducatesClusterConfig.spec.mode` is rejected on update. +- `make test` passes locally and in CI. +- `make smoke-test` passes locally. +- No reconcile logic beyond the log line. + +### Phase 1: EducatesClusterConfig in Inline mode (2–3 weeks) *(done — 2026-05)* + +**Why Inline first:** Inline mode is pure validation and status writing — no chart installs, no orchestration. It exercises the full controller pattern (watches, status conditions, finalizers) without the complexity of cluster-service installation. Lessons here apply everywhere. + +**What was built:** +- Mode-field exclusivity CEL (deferred from Phase 0): two structural + rules — Managed-mode top-level fields forbidden when `mode: Inline`; + `spec.inline` forbidden when `mode: Managed`. +- Extended status surface — the inter-CR contract Phase 4 components + will read: `status.mode`, `status.ingress` (with `NamespacedSecretRef` + for the wildcard + optional CA), `status.policyEnforcement`, + `status.imageRegistry` (always populated, empty struct when unset). +- Operator namespace plumbing: chart Deployment downward-API env + (`OPERATOR_NAMESPACE`) → main.go reads → reconciler struct field. + Manager `cache.Options.ByObject` restricts the Secret cache to that + namespace. +- RBAC for referenced resources: `get/list/watch` on Secrets, + ClusterIssuers, IngressClasses — read-only, kubebuilder markers + generate into the chart's ClusterRole. +- Inline-mode validator (`validator.go`): IngressClass existence; + wildcard Secret existence + `tls.crt` + `tls.key` keys; optional CA + Secret with `ca.crt`; optional ClusterIssuer existence + Ready. + ClusterIssuer access is via `unstructured.Unstructured` — + cert-manager Go types vendored in Phase 2. +- Reconcile flow: finalizer + (`educatesclusterconfig.config.educates.dev/finalizer`) added on + first sight, drained on delete (Phase 1 cleanup is a no-op; Phase 2 + Managed mode reuses the plumbing for chart uninstall). On Inline + validation success: populate the status contract + flip + `Ready=True`/`ValidationSucceeded=True`. On failure: `Phase=Degraded`, + both conditions `False` with field-specific message + (`: `). +- Watches: Secret (cache-restricted to operator namespace) + + IngressClass (cluster-scoped), each with an `EnqueueRequestsFromMapFunc` + returning the singleton request. ClusterIssuer watch deferred to + Phase 2 (see decisions.md — unstructured-watch-vs-absent-CRD + trade-off). +- 12 envtest specs (6 EducatesClusterConfig CRD validation, 3 platform + CRD validation, 5 Inline-mode reconciler, 1 manager-driven drift + test verifying Secret deletion flips status to Degraded). + +**Done when (verified):** +- ✅ An Inline-mode `EducatesClusterConfig` reaches `Ready: True` only + when all referenced resources exist and are valid. +- ✅ Deleting a referenced Secret causes status to flip to `Degraded` + within seconds (envtest: `watches_test.go`). +- ✅ All integration tests pass (12 specs, config-package coverage 64.5%). + +**Carried into Phase 2:** +- ClusterIssuer watch (vendor cert-manager types + add unconditional + watch since Managed mode always installs cert-manager when bundled). +- Mode-field exclusivity CEL is structurally enforced; the reconciler + also has a defensive guard for `mode==Inline && spec.inline==nil` + (CEL bypass case) that becomes redundant once webhooks are added — + flagged for review in v1beta1. + +### Phase 2: One Bundled service end-to-end (3–4 weeks) *(done 2026-05-11)* + +**Pick cert-manager as the first Bundled service.** It's the hardest to get right (CRDs, webhook readiness, ClusterIssuer ordering), and getting it right teaches the patterns that apply to the others. Easier services first leave you to discover hard problems later. + +**Session 1 — groundwork (done 2026-05):** vendoring + Helm SDK + +typed cert-manager access landed without changing user-visible +behaviour. Concretely: + +- **Decisions recorded** in `decisions.md`: + no `educates-cluster-services` umbrella (operator is the sole + installer); vendored upstream charts live as tarballs at + `installer/operator/vendored-charts/-.tgz`; cert-manager CRDs + are an operator install prerequisite for **all** modes (Inline-only + too — typed watches require GVK at cache startup). +- **cert-manager Go types vendored**: `github.com/cert-manager/cert-manager v1.20.2` + added; `cmv1` registered on the manager scheme; Phase 1's + `unstructured.Unstructured` ClusterIssuer access in + `validator.go::checkClusterIssuer` refactored to typed. +- **ClusterIssuer watch unconditional** on the EducatesClusterConfig + reconciler. envtest gets the vendored ClusterIssuer CRD via + `internal/controller/config/testdata/crds/cert-manager/`; new spec + asserts ClusterIssuer deletion flips status to Degraded (mirrors the + Phase 1 Secret-drift test). +- **`internal/helm` package** built around Helm SDK v4 (`helm.sh/helm/v4 + v4.1.4`): `Client.Install/Upgrade/Uninstall/Status` keyed by release + name, `LoadArchive` for vendored tarballs, a `*rest.Config`-backed + `restClientGetter` adapter, and a `NewMemoryClient` test factory using + the in-memory release driver + `kubefake.PrintingKubeClient`. +- **First vendored chart**: `installer/operator/vendored-charts/cert-manager-v1.20.2.tgz` + with `SHA256SUMS` integrity record; `make vendor-charts` (download + + verify) and `make verify-vendored-charts` (verify on disk) targets in + `installer/operator/Makefile`. A unit test in `internal/helm` loads + the real vendored tarball end-to-end. + +**Session 2 — Managed-mode end-to-end (done 2026-05-11):** +landed in three commits. + +*Commit 1 — install path and validation:* + +- Helm SDK chart-install pipeline: `internal/helm.Client.Status` → + `Install` on absent / `Upgrade` on chart-version drift. Vendored + chart embedded via `//go:embed` from + `installer/operator/vendored-charts/`; the canonical directory + moved inside the operator module to satisfy embed's + same-module constraint (decisions.md amended 2026-05-11). +- Managed-mode validator covers the Phase 2 happy path: + BundledContour + BundledCertManager + CustomCA, with CustomCA + Secret reference + `tls.crt`/`tls.key` key presence. Other + providers (ACME, ExternalCertManager, StaticCertificate, + non-BundledContour) return explicit "not yet supported in + v1alpha1" validation errors rather than silently no-op. +- `status.bundledChartVersions["cert-manager"]` populated after + install; `ensureNamespace` helper labels and owner-refs the + cluster-service namespace (reused in Phase 3). +- `HelmClientFor` factory on the reconciler lets tests inject + `helm.NewMemoryClient`. Memory client bumped to report + KubeVersion v1.31.0 so charts with `kubeVersion: >= 1.22` + render. + +*Commit 2 — wildcard certificate end-to-end:* + +- Readiness gate: all three cert-manager Deployments + (controller, webhook, cainjector) must report + `Available=True`. The originally-proposed + `GET /apis/cert-manager.io/v1` probe was rejected: that endpoint + resolves from CRD presence alone and doesn't exercise the + webhook pod. Synthetic admission-probe hardening (DryRunAll + Certificate against the live webhook) is captured in + `follow-up-issues.md` for when/if the Deployment-only gate + proves insufficient. +- CustomCA Secret copied operator-ns → cert-manager-ns via SSA + (cert-manager's CA-typed ClusterIssuer reads from + cluster-resource-namespace, default `cert-manager`). Owner + reference back to the EducatesClusterConfig. +- ClusterIssuer + wildcard Certificate applied via server-side + apply with field manager `educates-installer`. DNSNames cover + `` and `*.`. Wildcard tls Secret lands in + operator namespace. +- Watches added on `appsv1.Deployment` (cert-manager namespace + readiness) and `cmv1.Certificate` (wildcard readiness). Both + fire the singleton-reconcile mapping. +- `status.ingress` published (domain, ingressClassName, + wildcardCertificateSecretRef, clusterIssuerRef) and + `CertificatesReady=True` / aggregate `Ready=True` / + `Phase=Ready` once the Certificate reports Ready. + +*Commit 3 — finalizer-driven teardown:* + +- `cleanupManaged` runs on `DeletionTimestamp`: wildcard + Certificate → ClusterIssuer → copied CustomCA Secret → helm + uninstall cert-manager → cert-manager namespace. Each step + IgnoreNotFound so retried reconciles after partial failure are + safe. +- RBAC extended with `delete` verbs on the resources the operator + owns; `kubebuilder:rbac` markers re-generate into + `installer/charts/educates-installer/templates/rbac/role.yaml`. + +*Test coverage:* 18 envtest specs; config-package coverage 74.8%. +The Managed-mode happy-path spec drives Deployments.Available and +Certificate.Ready manually (envtest has no controllers), the +teardown spec exercises the finalizer drain end-to-end. CertificateCRD vendored into envtest testdata alongside the existing +ClusterIssuer CRD. + +**Done when (all met):** + +- Applying a Managed-mode `EducatesClusterConfig` with + `certificates.provider: BundledCertManager, issuerType: CustomCA` + results in cert-manager installed, ClusterIssuer + wildcard + Certificate created, status populated, all within reconcile-loop + timeouts. ✅ +- `kubectl delete educatesclusterconfig cluster` cleans up + everything in reverse install order. ✅ +- The reconciler tolerates in-progress states (cert-manager + installing, Certificate provisioning) — they surface as + `CertificatesReady=False` with reasons + `WaitingForCertManager` / `WaitingForCertificate` rather than + spurious errors. ✅ + +**Followed into Phase 3:** + +- Synthetic admission-probe hardening (see + `follow-up-issues.md`) — only file the issue if the + Deployment-availability gate proves insufficient in practice. +- kind-based integration tests (not envtest) — deferred to + Phase 6's "test against real environments" alongside GKE/EKS/OpenShift. +- Image-registry-prefix rewriting in chart values (the + Managed-mode `renderCertManagerValues` is a stub today; it + rewrites nothing). Lands alongside Phase 3's Contour/Kyverno + chart wiring, which has the same need. + +### Phase 3: Remaining cluster services (2–3 weeks) — done (2026-05-14) + +Now that the patterns are proven, repeat for: + +- **Contour** (BundledContour) — easiest. Chart, Service, IngressClass. Ordering: install before anything that uses ingress. +- **external-dns** (BundledExternalDNS) — easy. Chart, identity wiring (workload identity / IRSA annotation on ServiceAccount). +- **Kyverno** (Bundled) — medium. Has its own webhook readiness gotcha similar to cert-manager. Two engines (clusterPolicy and workshopPolicy) reference one Kyverno install. + +For each: install chart, real readiness check, status fields, finalizer order. 2–4 days each in flow. + +**Done when:** +- A Managed-mode `EducatesClusterConfig` matching the local kind scenario (Scenario A in the CRD draft) reaches `Ready: True` end-to-end. ✅ — `installer/samples/01-local-kind-customca.yaml`. +- A Managed-mode config matching the GKE production scenario (Scenario B) installs all four cluster services in correct order. ✅ — `installer/samples/02-gke-clouddns-acme.yaml` verified on a real GKE cluster with CloudDNS + Workload Identity + ACME. +- Deletion cleans up in reverse order without orphans. ✅ — finalizer drains Kyverno → external-dns → Contour → cert-manager. + +ACME-DNS01 (Route53 IRSA + CloudDNS Workload Identity) lands here ahead of schedule because real-cluster verification required it. Static-credentials Secrets, Cloudflare/AzureDNS, ACME staging-server docs, and external-dns `domainFilters` configurability are captured in `follow-up-issues.md` for post-Phase-3 polish. + +### Phase 4: Component CRDs (3–4 weeks) *(done — 2026-05-14)* + +Landed in three sessions, one per component (commits `acf69f00`, +`966da457`, `1dfb7cff`), in the planned order. Deviation from the +original sketch below: components are **not** installed via the +umbrella `educates-training-platform` chart. Each reconciler installs +its own vendored subchart tarball (secrets-manager, lookup-service, +session-manager, plus the node-ca-injector and remote-access extras) +as its own Helm release in the shared `educates` namespace; the +umbrella chart remains the standalone no-operator install path. See +decisions.md. + +**Carried out of Phase 4** (tracked in follow-up-issues.md): + +- Four SessionManager spec blocks reserved but unwired + (`themes`/`defaultTheme`, `defaultAccessCredentials`, + `imagePrePuller`, `registryMirrors`) — "SessionManager: wire + remaining spec fields into chart values". +- Deleting EducatesClusterConfig before the platform CRs wedges + SessionManager's helm uninstall (Kyverno CRDs already drained) — + "Block EducatesClusterConfig finalize while platform CRs exist". +- Scenario E (full BYO on OpenShift, Inline mode) has never been + verified on a real cluster — folded into Phase 6's real-environment + testing matrix. + +Order: SecretsManager → LookupService → SessionManager. + +**Why this order:** +- SecretsManager is smallest, exercises the cross-CR dependency pattern (it depends on EducatesClusterConfig.Ready, but nothing depends on it, so failures are isolated). +- LookupService introduces the prefix-and-domain pattern. +- SessionManager is biggest, depends on both EducatesClusterConfig and SecretsManager, and exercises the runtime-chart-with-subchart pattern. + +**For each component:** +- Reconciler reads `EducatesClusterConfig.status` (refuse to proceed unless Ready). +- For SessionManager: also check `SecretsManager.status` (refuse unless Ready). +- Install the component via the corresponding subchart of `educates-training-platform`. + - Pass values derived from CR + cluster config status. +- Status: install status, deployment refs, URLs (for LookupService). +- Conditions: `ClusterConfigAvailable`, `Deployed`, plus component-specific. +- Finalizer with chart uninstall. + +**Done when:** +- Scenario A from the CRD draft works fully end-to-end: local kind cluster install with `EducatesClusterConfig` + `SecretsManager` + `SessionManager` (+ optionally `LookupService`), all reaching Ready. ✅ — verified on kind, and again end-to-end via `educates local cluster create` during Phase 5. +- Scenario B (GKE production with all components) works end-to-end. ✅ — verified on a real GKE cluster. +- Scenario E (full BYO on OpenShift, Inline mode) works. ❌ — never verified; moved to Phase 6 real-environment testing. +- Deletion order is correct: SessionManager → LookupService → SecretsManager → EducatesClusterConfig. ⚠️ — correct when deleted in that order; deleting EducatesClusterConfig first wedges SessionManager (open follow-up, `PlatformCRsPresent` guard). + +### Phase 5: CLI rewrite (1–2 weeks) *(done — 2026-06-06)* + +The CLI shrank dramatically because the operator owns the heavy +lifting. This section was rewritten after the fact (2026-06-10): the +original "thin wrapper" sketch predated the two design sessions +(2026-05-19/20) that locked the config-file format, which gated every +Phase 5 task. The locked design is recorded in decisions.md (kind +ladder, data home, schema strategy, escape-hatch layout, silent +migration); the step-by-step implementation plan lived outside the +repo and its still-open follow-ups are now in follow-up-issues.md. + +**Locked design (see decisions.md for rationale):** +- CLI config is a **kind ladder** under `cli.educates.dev/v1alpha1`: + `EducatesLocalConfig` (laptop kind cluster; the only kind living at + `/config.yaml`), narrow scenario kinds + `EducatesGKEConfig` / `EducatesEKSConfig` / `EducatesInlineConfig` + (live in the user's repo), and `EducatesConfig` — the escape hatch + carrying the four CR `.spec`s verbatim with no CLI defaults and no + invariants. New scenario kinds only ship when a tested sample CR + exists in `installer/samples/`. +- Data home stays `$XDG_DATA_HOME/educates/`; + `EDUCATES_CLI_DATA_HOME` env var overrides it. +- One JSON schema per kind, embedded via `//go:embed` at + `client-programs/pkg/config/v1alpha1/schemas/`; the + `EducatesConfig` schema is generated from the CRD OpenAPI schemas + (`make generate-cli-schemas`). +- **No `migrate-config` command.** First-run silent migration + translates v3 `values.yaml` → `config.yaml` when the v3 provider is + kind/empty (old file stashed as `values.yaml.v3-backup`); any other + provider gets a refuse-with-instructions error. This supersedes the + original "migration tool for three real v3 configs" done-criterion. + +**What landed (steps 1–11, 2026-06-05/06):** +- Kind-discriminated loader + translator (kind → operator chart + values + 4 CRs) + embedded schemas (steps 1–3). +- `educates admin platform render / deploy / delete` (steps 4–6): + deploy owns the CRD lifecycle (apply CRDs, wait Established), + helm-installs the embedded operator chart + (`client-programs/pkg/deployer/chart/files/`, refreshed by `make + embed-installer-chart`), applies CRs, waits for Ready with + structured progress; delete drains CRs in reverse order then + uninstalls, with `--yes` and `--purge`. +- Schema-aware `educates local config init/get/set/view/edit` + (step 7). +- `educates local cluster create` tail-calls platform deploy, with + preflight (cached-CA existence, cluster existence, port + availability) (step 8). +- Carvel install path deleted: ytt/kbld/kapp install code paths, v3 + `InstallationConfig` types, `carvel-packages/` sources, `vendir.yml` + (step 9). Carvel libraries remain in the CLI for workshop tooling + only. +- First-run v3→v4 schema migration shim (step 10). +- Scenario kinds GKE / EKS / Inline (step 11). + +**Still open from Phase 5** (tracked in follow-up-issues.md): +CI drift checks for the embedded chart and generated schemas; mocked +tests for the cluster-touching deploy path; `--force-finalizers` on +delete; operator-image rebuild guidance; helm release +labels/annotations; apply-all-then-wait-all CR orchestration; +local-config UX papercuts (path suggestions, tab completion, list +`set`, `unset`); scenario-kind regression tests (escape-hatch +round-trip, sample-CR parity); schema publishing at +`schemas.educates.dev` + SchemaStore registration (Phase 6). + +### Phase 6: Polish and release prep (2–3 weeks) + +- Documentation rewrite (current `docs.educates.dev` content for installation). +- Migration guide for v3 → v4 users. +- Helm chart distribution (OCI registry, GitHub releases). +- Operator image publish story: publish-time `educates.dev/image-*` + annotations + release workflow (deferred from Phase 0; today the + chart defaults to a local-dev placeholder image). +- ~~Image relocation pipeline: evaluate `helm dt`, decide Apache fork or alternative, integrate into release pipeline.~~ *(done 2026-06-11: `helm dt` rejected — relicensed proprietary-Broadcom in 2026, and its values-rewriting is a no-op on our annotation-ladder charts. Decision: per-release digest-pinned image list (`hack/generate-image-list.sh`, attached to the GitHub release) + name-preserving skopeo/crane mirroring + existing registry overrides; `educates admin platform images copy` CLI wrapper tracked in follow-up-issues.md. See decisions.md.)* +- Release process documentation. +- ~~Remove the dangling carvel release machinery~~ *(done 2026-06-10: + the leftover `carvel-packages/` build artifacts (gitignored, never + tracked), their `.gitignore` entries, and the broken + `publish-carvel-bundles` job + its `educates-installer-app*.yaml` + release attachments are gone.)* The v4 chart-publish step that + replaces the bundle publish lands with the chart-distribution item + above. +- Publish CLI JSON schemas at `https://schemas.educates.dev/cli/v1alpha1/` + and register filename patterns with SchemaStore.org. +- Test against real environments: GKE, EKS, OpenShift (Inline mode), local kind. + EKS and OpenShift have never been exercised; OpenShift covers the + outstanding Scenario E criterion from Phase 4. + +**Done when:** +- A user external to the project can install Educates v4 from published artifacts following the docs alone. +- All scenarios in the CRD draft are demonstrably working. +- A release tag exists. + +--- + +## 4. Estimate and pacing + +Solo, full-time-equivalent estimate per phase: + +| Phase | Estimate | +|---|---| +| Pre-phase: runtime chart | 1–2 weeks | +| Phase 0: Foundations | 1–2 weeks | +| Phase 1: Inline mode | 2–3 weeks | +| Phase 2: First Bundled service | 3–4 weeks | +| Phase 3: Remaining cluster services | 2–3 weeks | +| Phase 4: Component CRDs | 3–4 weeks | +| Phase 5: CLI rewrite | 1–2 weeks | +| Phase 6: Polish and release | 2–3 weeks | +| **Total** | **15–23 weeks** | + +Actual elapsed time will be longer because solo development isn't full-time-equivalent and there are always interruptions. Plan for **5–7 months** of calendar time as a realistic target. + +**Don't sub-divide phases until you're inside them.** Sub-tasks emerge from doing the work; planning them all upfront wastes time and produces wrong plans. + +--- + +## 5. Working with Claude — playbook + +This is the section that codifies how the human-AI collaboration works on this project. Update it as patterns emerge. + +### Tools and where to use them + +- **Claude Desktop (web/app):** for design discussions, CRD revisions, planning, document drafting, reviewing scenarios. Conversations happen in a project so they share context. +- **Claude Code (terminal):** for actual coding, building, testing, git operations. Reads `CLAUDE.md` from the repo on every session for context. +- **Project knowledge in Claude Desktop:** the durable memory across Desktop conversations. Key documents (this plan, the CRD draft, decisions log) live here. Update them as decisions are made. +- **CLAUDE.md in the repo:** the durable memory for Claude Code. Mirrors the most important decisions from project knowledge in condensed form. Updated alongside project knowledge. + +### What Claude is good at + +- Architectural sounding board, especially when a question has multiple valid answers. +- Boilerplate generation: Go types from CRD specs, status condition helpers, watch setups, test scaffolds. +- Translating designs to code: "here's what the field should mean; write the reconciler logic that implements it." +- Reading and synthesizing: comparing chart values schemas, summarizing how other projects solved similar problems. +- First-draft documentation: reference docs, runbooks, migration guides. + +### What Claude is unreliable at + +- Anything requiring observation of the live cluster — without an MCP, Claude can't see what's actually running. +- Subtle Kubernetes semantics (finalizer/namespace race conditions, cache coherence). 80% accurate is dangerous because the 20% wrong looks plausible. +- Knowing exact current values of upstream Helm charts. Always verify with `helm show values`. +- Long-term consistency across sessions. Claude doesn't remember; the docs do. +- Picking what to do next. The plan is yours; Claude executes against it. + +### Workflow patterns + +**Design questions:** in Claude Desktop. Hash them out, save the result to project knowledge as a document. Don't let design decisions live only in chat history. + +**Implementation:** in Claude Code, scoped tightly per session. "Write the EducatesClusterConfig types" is one session. "Add the watch on referenced Secrets" is another. Avoid trying to implement whole phases in one chat — quality drops as context fills. + +**Debugging:** paste actual error messages, not summaries. If using read-only Kubernetes MCP, let Claude check cluster state directly. Otherwise, paste `kubectl describe` and log output verbatim. + +**Code review:** paste the code, ask Claude to look for issues. Decent at catching obvious bugs, race conditions, missed cases. Not a substitute for testing. + +**When stuck:** explain the situation in chat. Often clarifies your own thinking. If not, Claude might spot something. + +### Anti-patterns + +- **Don't ask Claude to drive the project.** "What should I do today?" produces mediocre answers. The plan picks tasks; Claude executes them. +- **Don't trust generated code blindly.** Especially for Helm SDK calls, controller-runtime patterns, and Kubernetes API usage. Verify against current docs. +- **Don't let chat-only artifacts accumulate.** If something good came out of a conversation, save it as a file. Otherwise it's lost. +- **Don't re-litigate decisions.** When Claude suggests something contrary to a documented decision, point at the document. If you keep relitigating, the decision wasn't well-documented — fix the document. + +### Keeping documents current + +Whenever an architectural decision changes, three places need updating: + +1. The CRD draft (if it affects the schema). +2. This plan (if it affects scope, phases, or estimates). +3. CLAUDE.md (always, since it's the briefing for Claude Code). + +A simple rule: **don't merge a code change that contradicts the docs without updating the docs in the same PR.** + +### Decisions log + +Maintain a separate `docs/architecture/decisions.md` with one-paragraph entries for each significant architectural decision and its rationale. Reference it from CLAUDE.md. This is what prevents relitigation and orients new contributors (or future you) faster than reading commit history. + +Format: short title, date, what was decided, why. No need for full ADR formality unless the team grows. + +--- + +## 6. Risks and mitigations + +| Risk | Likelihood | Mitigation | +|---|---|---| +| Helm SDK or controller-runtime quirk costs significant time in Phase 2 | High | Budget extra time for Phase 2; treat it as the learning phase. | +| Solo development pace drops due to context-switching with other responsibilities | High | Document state at end of each work session; resume sessions from docs, not memory. | +| `helm dt` (or chosen image-relocation tool) becomes unmaintained | Medium | Don't make the install path depend on it; keep it as build-time only. Identify backup tool early. | +| Educates runtime turns out to require something Helm can't express cleanly | Low | The pre-phase chart shakes this out before operator work starts. | +| CRD design reveals gaps once implementation starts | High | Plan for one CRD revision (v1alpha2) before v1beta1. Don't fight it. | +| Phase estimates are wrong in aggregate | High | The estimate is a range, not a date. Communicate phase completion, not deadlines. | + +--- + +## 7. Open items at start of work + +These are unresolved as of the start of Phase 0 / pre-phase: + +1. **Repo location:** Decision has been made to use a new directory `helm-charts` in current repository. +2. **Vendor upstream charts vs pull from registry at runtime.** Decision has been made to use upstream charts, but to vendor them into the repository at build time. Make the update of every chart a conscious decision, so that changes can be curated and properly tested. +3. **OperationalBlock pattern:** deferred per CRD draft r3. Add when it becomes necessary. +4. **Image relocation tool:** `helm dt` evaluated; license check required. Backup options: `relok8s`, custom Go using `go-containerregistry`. Decide in Phase 6. +5. **Read-only Kubernetes MCP setup for Claude Code:** decide once Phase 1 has something running. Not needed earlier. +6. **`SecretsManager.spec.clusterConfig` block existence:** noted in CRD draft as possibly unnecessary. Confirm during Phase 4. + +--- + +## 8. What good looks like at the end + +Concrete success criteria for v4 release: + +- A user with a fresh GKE cluster can install Educates v4 with a single `helm install` of the installer chart followed by `kubectl apply` of three CRs (or a single `educates admin platform deploy` command). Working portal in ~10 minutes. +- A user with an existing OpenShift cluster, their own cert-manager, and their own ingress can deploy Educates v4 with an Inline-mode `EducatesClusterConfig` and three component CRs without the operator installing anything cluster-level. +- An ArgoCD-managed cluster reconciles a Git repo containing the operator chart and CR YAML files and brings up Educates without human intervention. +- A v3 user runs `educates migrate-config v3-config.yaml > v4-crs.yaml`, then deletes their v3 install and applies the v4 CRs, and gets back to a working state. +- The operator's own uninstall (delete EducatesClusterConfig) cleans up everything it installed, in correct order, with no orphans. + +When all five of those work reliably, v4 is ready to release. diff --git a/docs/architecture/follow-up-issues.md b/docs/architecture/follow-up-issues.md new file mode 100644 index 000000000..3c8b6f2cf --- /dev/null +++ b/docs/architecture/follow-up-issues.md @@ -0,0 +1,1232 @@ +# Follow-up issues + +GitHub issues to open once the v4 chart-based install ships in +`develop`. Each entry is a near-ready issue draft — title, motivating +context, scope, acceptance criteria — that can be transcribed to the +GitHub issue tracker with minimal further editing. + +The format mirrors `decisions.md`: one heading per issue, prose body, +date the entry was added. New issues append at the end. + +Mark items here as `*(opened: )*` once the issue is +filed in the tracker, and `*(landed: )*` once resolved. +Items that turn out to be irrelevant after further work get +`*(dropped)*` with a one-line reason. Don't delete — the history is +itself useful for future planning. + +--- + +### Simplify `operator_config.py` IMAGE_REPOSITORY resolution + +**Date added:** 2026-05-05. +**Trigger to file:** v4 chart shipped in `develop`; users no longer +install via the v3 carvel installer for new clusters. + +**Context:** + +`session-manager/handlers/operator_config.py:26-35` currently composes +`IMAGE_REPOSITORY` from the runtime config's `imageRegistry.host` + +`imageRegistry.namespace`, with a fallback to +`registry.default.svc.cluster.local` when the host is empty. +`secrets-manager/handlers/operator_config.py` reads its own +`OPERATOR_NAMESPACE` from the same blob. + +In v3, that compose logic mattered because the carvel-installer baked +image refs into the OCI bundle at build time AND populated +`imageRegistry` in the operator config so workshops with +`$(image_repository)` placeholders could resolve runtime-spawned +images consistently. The runtime's `image_reference()` function used +`IMAGE_REPOSITORY` as the default prefix when an image wasn't listed +in `imageVersions`. + +In v4 the chart populates `imageVersions` with the full set of +runtime-spawned image refs explicitly — every short-name the runtime +knows about (`training-portal`, `base-environment`, the loftsh +images, etc.) is present with a fully-qualified reference, sourced +from Chart.yaml annotations. The `IMAGE_REPOSITORY` fallback is +hit only by: + +1. `$(image_repository)` placeholders in workshop content YAMLs, when + workshops authored in dev are deployed to dev clusters via + `educates publish-workshop` + `educates deploy-workshop`. Released + workshops have these placeholders pre-resolved. +2. Hypothetical short-names not yet in `imageVersions`. None known + today. + +**Scope:** + +Tighten `operator_config.py` so the runtime stops mixing the two +conceptual roles `imageRegistry` was playing in v3: + +- Drop the `imageRegistry.host` + `imageRegistry.namespace` compose + logic. Read `IMAGE_REPOSITORY` directly from a single + `imageRepository` field in the operator config (the chart can emit + this directly when `development.imageRegistry` is set), with the + same `registry.default.svc.cluster.local` fallback. +- Drop the runtime-side fallback path in `image_reference()` for + images not in `imageVersions`. Treat unknown short-names as a config + error rather than silently composing an unresolvable ref against + `IMAGE_REPOSITORY`. + +**Why now (after develop ships) and not earlier:** + +Until v4 is in `develop`, the v3 carvel installer is the production +install path. Changing `operator_config.py` shape would force a +coordinated v3 carvel-installer + runtime change. Easier to wait until +v4 owns the install and then simplify the runtime to match the +narrower contract the chart actually provides. + +**Acceptance criteria:** + +- `operator_config.py` reads `IMAGE_REPOSITORY` from a single config + field (`imageRepository: ""` populated by the chart, or empty for + the in-cluster fallback). No host/namespace compose logic. +- `image_reference()` raises a clear error for short-names absent from + `imageVersions` instead of composing a default ref. +- Chart's `session-manager.operatorConfigYAML` helper updated to emit + the simplified field (or kept emitting the existing shape for + backward compatibility during a deprecation window — decide at + filing time). +- All 8 chart scenarios still pass. +- Workshop with a `$(image_repository)/` placeholder still + resolves correctly when `development.imageRegistry` is set. + +--- + +### Drop `clusterIngress.tlsCertificate` / `caCertificate` inline forms from `operator_config.py` + +**Date added:** 2026-05-05. +**Trigger to file:** when filing the previous issue, or independently. + +**Context:** + +`session-manager/handlers/operator_config.py:52-65` accepts an inline +`clusterIngress.tlsCertificate: { tls.crt, tls.key }` block as an +alternative to the `tlsCertificateRef` form, materialising a Secret +named `-tls` from the inline content. Same for +`clusterIngress.caCertificate`. + +The v4 chart only emits the `*Ref` forms — references to existing +Secrets (typically populated by cert-manager or a pre-install hook). +The inline form is dead code in v4-installed clusters. + +**Scope:** + +Drop the inline-form parsing in `operator_config.py`. The `*Ref` forms +remain as the single way to reference TLS / CA material. + +**Why:** simplifies the runtime, narrows the attack surface (no inline +TLS material flowing through the runtime config), and matches what the +v4 chart actually emits. + +**Acceptance criteria:** + +- Inline-form code paths removed from `operator_config.py`. +- Existing scenarios still pass (none use the inline form). +- v3 release notes / migration guide flag the removal as a + `migrate-config`-handled translation. + +--- + +### CI lint: Chart.yaml annotations stay in sync across subcharts + +**Date added:** 2026-05-05. +**Status:** landed 2026-06-11 — `hack/lint-chart-versions.sh`, run as +the `chart-sync-lint` job in `installer-operator-ci.yaml`. Covers the +optional extension too (version/appVersion parity umbrella ↔ subcharts +↔ educates-installer, dependency pins, and embed.go/tarball alignment), +since the CI-stamping release model +(`hack/stamp-release-version.sh`, see decisions.md) depends on the +committed tree staying uniform. +**Trigger to file:** any time after the `development.imageRegistry` + +annotations refactor lands. + +**Context:** + +The four image-rendering subcharts each carry their own copy of +`educates.dev/image-registry-host` and `-namespace` annotations in +their `Chart.yaml`. The release workflow updates them per fork. If a +release accidentally updates only some, image refs across subcharts +would diverge silently. + +**Scope:** + +Add a CI step (or pre-commit hook) that asserts all four subchart +Chart.yamls have identical values for the two annotations. Failing the +lint blocks the merge. + +**Acceptance criteria:** + +- CI step checks all four `Chart.yaml`s have matching + `educates.dev/image-registry-host` and `-namespace` annotations. +- Lint fails with a clear error pointing at the offending subchart. + +**Optional extension:** also check that all five `Chart.yaml`s +(umbrella + subcharts) share the same `version` and `appVersion`. +The umbrella's `dependencies[].version` should match the subchart +versions too. + +--- + +### Document the chart release workflow's annotation update step + +**Date added:** 2026-05-05. +**Status:** landed 2026-06-11 — the annotation update is now automated +(`hack/stamp-release-version.sh` rewrites the annotations per fork at +publish time; no manual `yq -i` step exists). The runbook +(`developer-docs/release-procedures.md`, "Release Versioning and +Stamping") documents the stamping model with the upstream and fork +worked examples this issue asked for, and points at the +`chart-sync-lint` CI job that enforces annotation consistency. +**Trigger to file:** before the first chart release that consumers +will install from a fork. + +**Context:** + +The `development.imageRegistry` + annotations design relies on the +release workflow updating each subchart's +`educates.dev/image-registry-host` and `-namespace` annotations per +fork. The release runbook currently only mentions `appVersion` +bumping. + +**Scope:** + +Update `docs/release-runbook.md` (or wherever the release runbook +lives — create if missing) with the annotation-update step, including +the `yq -i` command pattern and the rationale (decisions.md entry). + +**Acceptance criteria:** + +- Release runbook documents the annotation update across all four + Chart.yamls (or refers to the CI lint that enforces consistency). +- Worked example for the upstream release case AND the fork release + case. + +--- + +### Harden cert-manager readiness with a synthetic admission probe + +**Date added:** 2026-05-11. +**Trigger to file:** if we observe `CertificatesReady=True` flips +while the cert-manager admission webhook is in fact unhealthy — i.e., +Certificates created in the same reconcile pass fail with +`InternalError`/`failed calling webhook` despite the operator +considering cert-manager ready. + +**Context:** + +Phase 2 Session 2 commit 2 implemented cert-manager readiness as +"all three cert-manager Deployments (controller, webhook, cainjector) +report `Available=True`." This is what v3's installer used and what +most cert-manager-driven operators ship. The Phase 2 carry-forward +originally proposed adding `GET /apis/cert-manager.io/v1` against +the API server as the readiness gate, but that endpoint resolves +from CRD presence alone — it does not exercise the admission webhook +pod — so it was rejected as a stronger probe (see Phase 2 Session 2 +plan amendment). + +The Deployment-availability check has a real (if rare) failure mode: +the webhook pod can be Available per its readiness probe while its +mutating/validating admission path is broken (TLS rotation race, +webhook handler panic-and-recover loop, mis-wired Service Endpoints). +In that window the operator races ahead, creates a ClusterIssuer and +Certificate, the apiserver calls the webhook, the webhook errors, +and the user sees confusing failures on resources the operator just +created. + +**Scope:** + +Add an *Option B* readiness gate alongside the existing Deployment +check: + +1. Construct a sentinel `Certificate` object in-memory — `metadata.name` + derived from `EducatesClusterConfig` UID so it's stable per + instance — pointing at the wildcard issuer with `dnsNames` for the + wildcard domain. Do **not** persist it. +2. Issue a server-side dry-run create via the typed client: + `r.Create(ctx, sentinel, client.DryRunAll)`. This forces the + apiserver to invoke cert-manager's admission webhook end-to-end + without writing anything to etcd. +3. Treat a successful dry-run as "webhook is serving"; treat + `webhook unavailable`, `i/o timeout`, or `connection refused` + errors as "not ready, retry." +4. Gate ClusterIssuer/Certificate SSA on this probe in addition to + Deployment availability. + +The dry-run approach is preferable to a real-persistent canary +because it requires no cleanup, generates no garbage in the cluster, +and exercises exactly the path the real Certificate will take. + +**Acceptance criteria:** + +- New helper `probeCertManagerAdmission(ctx, owner)` returns + nil/error. +- `reconcileCertManager` invokes it after the Deployment-availability + gate and before SSA of the ClusterIssuer. +- Errors surface as `CertificatesReady=False reason=WebhookUnavailable` + with the underlying admission error in the message; reconcile is + retried with backoff. +- envtest spec: stand up a webhook config pointing at a non-existent + Service, assert the probe returns an error and CertificatesReady + stays False until the webhook is wired correctly. + +**Cost note:** the dry-run is a real apiserver round-trip, so it +adds latency per reconcile. Reconcile triggers are watch-driven, so +this stays cheap in steady-state; it only fires when something +upstream changed. Acceptable trade for correctness. + +--- + +### Narrow EducatesClusterConfig watches with object-scoped predicates + +**Date added:** 2026-05-12. +*(landed: 2026-05-13, at the start of Phase 3 — predicates were +implemented as per-kind mapping functions rather than separate +predicate.Predicate objects; same outcome, slightly less ceremony.)* + +**Trigger to file:** end of Phase 3 cleanup, once Contour / Kyverno / +external-dns watches have been added and the noise has compounded. + +**Context:** + +Today `mapToSingleton` enqueues the singleton EducatesClusterConfig on +*any* change to *any* of its watched kinds anywhere in the cluster: + +- every Secret in the operator namespace (regardless of name); +- every IngressClass cluster-wide; +- every ClusterIssuer cluster-wide; +- every Certificate cluster-wide; +- every Deployment cluster-wide. + +This is correct (the reconciler is idempotent, so over-enqueuing +just wastes CPU) but noisy. During cert-manager bootstrap the +reconciler fires ~20 times in 2 minutes because cert-manager's +chart-installed Deployments roll out, cainjector annotates webhook +configs, the Certificate transitions Issuing → Ready, the wildcard +tls Secret gets created, etc. — none of which is "the operator +needs to re-evaluate anything but cert-manager's readiness". + +The noise also widens the cache-staleness race surface: more +reconciles means more chances to fire one against a cached obj +whose status was just updated by the previous reconcile but whose +watch event hasn't reached the informer yet. We already mitigate +the conflict with RetryOnConflict + live-read in +updateStatusWithTransitionLog, but the underlying cost (extra +apiserver round-trips, log churn) scales with the noise. + +Phase 3 will add Contour, Kyverno, and external-dns watches — +roughly doubling the watched-kind surface. Adding predicates *after* +that change consolidates the cleanup into one focused commit +instead of spreading it across each phase. + +**Scope:** + +Replace the unconditional `EnqueueRequestsFromMapFunc(mapToSingleton)` +calls in `SetupWithManager` with predicate-filtered watches. Each +predicate filters at the source — events that don't match never +reach the work queue. Concrete filters: + +1. **Secrets**: enqueue only if `name` matches one referenced from + spec.inline or spec.ingress.certificates.bundledCertManager.customCA. + The reconciler already knows these names; the predicate looks them + up from the singleton CR (refetched on each predicate call, or + cached behind a sync.Map updated from Reconcile). +2. **IngressClass**: enqueue only if `name` matches + spec.ingress.ingressClassName. +3. **ClusterIssuer**: enqueue only if `name == wildcardClusterIssuer` + (operator-owned) or matches a user-supplied reference from Inline + mode. +4. **Certificate**: enqueue only if + `name == wildcardCertificate && namespace == operatorNamespace`. +5. **Deployment**: enqueue only if `namespace == certManagerNamespace` + (Phase 3 will add Contour/Kyverno/external-dns namespaces here). + +**Acceptance criteria:** + +- Reconcile rate during cert-manager bootstrap drops by 5–10× + (measure with `controller_runtime_reconcile_total{controller="config-..."}` + before/after). +- envtest specs that exercise drift (Secret deletion, ClusterIssuer + deletion, etc.) still pass — predicates must not filter out the + events the reconciler legitimately reacts to. +- No regression in time-to-Ready for fresh installs. + +**Risks:** + +- A predicate filter that's too aggressive silently swallows + legitimate drift signals — the reconciler stops noticing + user-driven changes. Mitigation: each predicate is unit-tested + with both matching and non-matching events, and the envtest + drift specs are the integration safety net. +- Predicates that look up spec from the singleton CR add a hot-path + read; cache it explicitly rather than calling r.Get per event. + +**Alternative considered (and rejected for this issue):** logging +each watch event at V(1) inside the mapper. Tells the operator +*what* fired but doesn't reduce work-queue churn — adds observability +without addressing the underlying cost. Worth considering only if +predicate filtering turns out to be insufficient. + +--- + +### Remove the cert-manager CRD operator-startup prerequisite + +**Date added:** 2026-05-12. +*(landed: 2026-05-13 via the deferred-watch pattern — +`internal/controller/config/crd_watcher.go` — after an initial +attempt with unstructured Watches proved insufficient. The +unstructured form still requires GVK resolution at cache-sync +time, which fails on a vanilla cluster. The deferred pattern +registers the cert-manager watches at runtime via +Controller.Watch() once discovery confirms the CRDs exist. See +decisions.md amendment on the 2026-05-06 entry for the full +design + verified mechanics.)* + +**Trigger to file:** start of Phase 3, before any additional typed +watches on bundled-service CRDs (Contour HTTPProxy, Kyverno +ClusterPolicy, etc.) are added — applying the same pattern to all +cluster-service kinds at once is cheaper than retrofitting it later. + +**Context:** + +Today the operator chart documents that cert-manager.io CRDs must +be installed in the cluster *before* the operator pod starts (see +decisions.md → "cert-manager CRDs are an operator install +prerequisite"). The reason is purely mechanical: the reconciler +uses typed `Watches(&cmv1.ClusterIssuer{}, ...)` and +`Watches(&cmv1.Certificate{}, ...)`, and controller-runtime +requires the GVK to be resolvable at cache startup. + +End-to-end testing during Phase 2 Session 2 surfaced that this +prerequisite is a real friction point — the user has to apply +cert-manager CRDs out-of-band before `helm install +educates-installer`, which contradicts the project goal of "one +install command, no preceding steps". The original decision +accepted the friction in exchange for typed ergonomics in the +validator; with Phase 3 about to add three more bundled cluster +services (each with their own CRDs), the friction multiplies and +the decision should be reversed. + +**Decision (reversal of decisions.md 2026-05-06 entry):** + +The operator must start successfully on any vanilla cluster, with +no CRD prerequisites. Bundled-mode installs are then responsible +for applying their own CRDs via the chart they install. + +**Design — split typed vs unstructured by use site:** + +The GVK-at-startup constraint only applies to `Watches()`. API +calls (Get/Create/Update/Patch) resolve GVKs at request time, so +typed clients work fine *after* the CRDs exist in the cluster. +That lets us keep most of the ergonomic typed code we have today, +and only pay the unstructured tax on the watch layer: + +1. **Watches: always unstructured.** + Replace + `Watches(&cmv1.ClusterIssuer{}, ...)` and + `Watches(&cmv1.Certificate{}, ...)` in + `educatesclusterconfig_controller.go::SetupWithManager` with + unstructured-kind watches: + ``` + ci := &unstructured.Unstructured{} + ci.SetGroupVersionKind(schema.GroupVersionKind{ + Group: "cert-manager.io", Version: "v1", Kind: "ClusterIssuer"}) + Watches(ci, handler.EnqueueRequestsFromMapFunc(mapToSingleton)) + ``` + Unstructured watches start successfully whether or not the CRD + exists; events flow once the CRD lands. + +2. **Validator read paths: unstructured.** + `validator.go::checkClusterIssuer` reverts to the Phase 1 + pre-typed implementation (Get an `unstructured.Unstructured`, + read `status.conditions[Ready]` by field path). The field access + is a handful of lines — not worth the typed-package import for + a single read. + +3. **Owned-resource create/update: keep typed.** + `certmanager.go::ensureClusterIssuer` and + `ensureWildcardCertificate` keep constructing typed + `cmv1.ClusterIssuer{...}` / `cmv1.Certificate{...}` and + SSA-patching them. These calls only execute *after* + `ensureCertManagerReady` has confirmed cert-manager is up, + which means the CRDs are in the apiserver. Typed is more + readable and SSA serialization works the same. + +4. **certificateReady read: typed.** + Same reasoning — it only runs after cert-manager is up. + +**Phase 3 corollary:** + +Apply the same pattern uniformly to Contour, Kyverno, external-dns: +- Watches against any of their CRD-defined kinds → unstructured. +- Validation reads of user-supplied references → unstructured. +- Operator-owned creates/updates → typed (resources of the + bundled service can only be created after the bundled service + is installed, by definition). + +**Acceptance criteria:** + +- `helm install educates-installer` on an empty kind cluster + (no cert-manager CRDs, no anything) succeeds and the operator + pod reaches Ready without manual intervention. +- A Managed-mode `EducatesClusterConfig` then installs cert-manager + (including its CRDs via the chart) and reaches Ready end-to-end. +- An Inline-mode `EducatesClusterConfig` referencing an existing + ClusterIssuer still works — the unstructured watch picks up + drift on the referenced object once the CRD exists. +- envtest specs still pass with the typed CRD vendored under + `testdata/crds/cert-manager/` (envtest can register typed CRDs + even when the runtime path is unstructured). +- decisions.md's "cert-manager CRDs prerequisite" entry is amended + with a reversal block dated when this lands; the original + decision text is preserved so the reversal is honest. +- CLAUDE.md "Watches:" and "ClusterIssuer access" bullet points + are updated to reflect the unstructured-at-the-edge / typed-in- + the-middle split. + +**Risks:** + +- Unstructured field access is stringly-typed and easier to + fat-finger than typed reads. Mitigation: keep the unstructured + surface narrow (validator reads only), and unit-test the + field-path expressions against a real CRD-shaped object. +- The pre-existing envtest drift spec (`ClusterIssuer deletion + → status flips to Degraded`) currently runs against the typed + watch path. It should still pass with unstructured watches, + but the test setup needs to register the kind for the + unstructured client — verify on the first pass. + +**Alternative considered (and rejected):** ship cert-manager (and +later Contour / Kyverno / external-dns) CRDs in the +`educates-installer` chart's `crds/` directory. Mechanically +cleanest user experience but couples the operator chart's +lifecycle to four upstream CRD shapes; chart bumps require +re-vendoring CRDs in lockstep; Inline-mode users who never +install cert-manager would still get its CRDs in their cluster. +The user prefers a leaner operator install that imposes nothing +beyond its own kinds. + +--- + +### Quiet the controller-runtime Kind source after cert-manager CRDs are removed + +**Date added:** 2026-05-13. +*(partially landed: 2026-05-13 via `cmd/logsink.go` — a +`logr.LogSink` wrapper that demotes the specific controller-runtime +ERROR message "if kind is a CRD, it should be installed before +calling Start" to V(1)/debug. The visual noise is suppressed in +default operation; the underlying controller-runtime gap — no API +to tear down a registered Source — remains and would need an +upstream contribution to fully fix.)* + +**Trigger to file:** post-Phase-3 release prep, or sooner if a +user reports the log noise as a real concern. Cosmetic — does not +affect correctness. + +**Context:** + +The deferred-watch pattern (decisions.md → "cert-manager CRDs +prerequisite" 2026-05-13 amendment) registers cert-manager watches +at runtime once their CRDs are present. The operator's own code +paths classify CRD-removal cleanly via +`isCertManagerCRDMissingErr` and surface a +`CertificatesReady=False reason=CertManagerCRDsMissing` / +`phase=Degraded` status, so the user-visible state is correct. + +But controller-runtime offers no public API to remove or stop a +registered `Source` short of cancelling the entire controller's +context (verified: `pkg/internal/controller/controller.go` only +adds to `startWatches`, never removes; `Source` interface has no +`Stop()`). Once `CRDWatcher` activates the cert-manager.io +watches and cert-manager is later uninstalled (the normal end of +a Managed-mode teardown, or a user `kubectl delete crd`), the +Kind source's polling-retry loop spams "if kind is a CRD, it +should be installed before calling Start" every 10s in the +operator pod log until the pod restarts. + +**Scope sketches (two complementary mitigations):** + +1. **Self-restart after successful cleanupManaged drain.** When + the finalizer is removed and the EducatesClusterConfig is + about to be GC'd, signal the operator process to exit cleanly + (e.g., os.Exit(0) after a brief delay, or close the manager's + context). Kubernetes restarts the pod; the new pod starts + fresh, no stale sources. Crude but practical. Doesn't help + the abnormal-deletion case (user deletes CRDs out-of-band + while the CR still exists) — that one only resolves on + manual pod restart. + +2. **Upstream controller-runtime contribution** to expose a way + to remove a Source, or to stop one's underlying informer. + Significant design discussion. Possibly there's an alternative + shape — a `Source` that wraps the Kind source and can be + externally stopped — that we could prototype downstream first. + +**Acceptance criteria:** + +- After a normal `kubectl delete educatesclusterconfig cluster` + on a Managed-mode install, the operator log goes quiet within + a pod restart window (≤ ~30s); no recurring retry-loop + errors. +- The abnormal-deletion case (CRDs deleted out-of-band) at + least surfaces a clear instruction to the user via the + `CertManagerCRDsMissing` condition message; log noise is + best-effort. + +**Out of scope here:** the operator's own error-path +classification — that lands with the deferred-watch pattern and +is the user-facing fix. + +--- + +### Expose an external-dns `domainFilters` override on the CRD + +**Date added:** 2026-05-14. +**Trigger to file:** when a user reports they want external-dns +to manage records under a domain different from +`spec.ingress.domain`, or to manage multiple domains, or to +narrow further by record name. v1alpha1 hard-codes +`domainFilters: [spec.ingress.domain]` to match what the v3 +Carvel installer did; this is fine for the single-domain Educates +flow but doesn't cover legitimate multi-tenant / multi-domain +setups. + +**Context:** + +`renderExternalDNSValues` (installer/operator/internal/controller/ +config/externaldns.go) currently sets +`domainFilters: [spec.ingress.domain]` unconditionally. The v3 +installer's EKS/GKE overlays optionally let the user point at a +different zone via `clusterInfrastructure.aws.route53.hostedZone` +or `clusterInfrastructure.gcp.cloudDNS.zone`. Our zoneIdFilters +(for AWS) is already driven from +`spec.dns.bundledExternalDNS.route53.hostedZoneID`, so the AWS +case is partially covered — but the `domainFilters` value is +still pinned to the ingress domain. + +**Scope:** + +Add an optional `domainFilters []string` field on +`BundledExternalDNSConfig`. Use `spec.ingress.domain` as the +default when unset (current behaviour). Pass through verbatim +when the user sets it. Same `[]string`→`[]any` translation as +the other slice values (helm values.schema.json gotcha). + +**Concrete scenario (observed 2026-05-14, GKE + CloudDNS):** + +User has a single top-level CloudDNS zone `google.educates.dev`. +First install with `domain: academy-01.google.educates.dev` +failed to publish DNS records *until the user created a dedicated +sub-zone* `academy-01.google.educates.dev` with NS delegation +from the parent. Reason: external-dns `--domain-filter` is a +*record-name* filter, not a zone selector. With the filter +pinned to `academy-01.google.educates.dev`, external-dns +rejected the parent zone `google.educates.dev` as "wrong +suffix" — even though a record like `*.academy-01...` could +legitimately live inside the parent zone in DNS terms. + +In v3 carvel, the user worked around this by setting +`domain_filter` to the parent zone name (see +`carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/ +external-dns/overlays/defaults.star`). v1alpha1 doesn't expose +the same knob — this follow-up fixes that. + +**Scope (v1alpha1 — option 1):** + +Add an optional `domainFilters []string` field on +`BundledExternalDNSConfig`. Use `spec.ingress.domain` as the +default when unset (current behaviour). Pass through verbatim +when the user sets it. Same `[]string`→`[]any` translation as +the other slice values (helm values.schema.json gotcha). + +This is backwards-compatible — users with a dedicated sub-zone +keep working unchanged; users with only a parent zone set +`domainFilters: [google.educates.dev]` and external-dns writes +records into the parent. + +**Acceptance criteria (v1alpha1):** + +- `spec.dns.bundledExternalDNS.domainFilters: ["a.example.com", + "b.example.com"]` results in external-dns watching both + domains. +- Empty / unset preserves the current single-domain default. +- envtest spec covers both cases. + +**Potential follow-on (deferred — option 3):** + +If users start sharing a single CloudDNS project across +multiple clusters with overlapping `domainFilters`, add a +companion `cloudDNS.zoneIDs []string` (and Route53 mirror) +that drives external-dns's `--google-zone-id-filter` / +`--zone-id-filter`. That layers a zone-level guardrail on top +of the record-level filter so a cluster can't accidentally +mutate another cluster's records. Defer until a concrete +multi-cluster-shared-zone ask comes in — record-level +filtering plus per-cluster `txtOwnerId` already covers the +common case. + +--- + +### ACME static-credentials Secret support (Route53 + CloudDNS) + +**Date added:** 2026-05-14. +**Trigger to file:** users without IRSA/Workload Identity (on-prem +or smaller clouds) ask for ACME-DNS01 support backed by long-lived +credentials. + +**Context:** + +v1alpha1 lands ACME-DNS01 with identity-based auth only — +`Route53Config.IAMRoleARN` (IRSA on EKS) and +`CloudDNSConfig.WorkloadIdentityServiceAccount` (Workload Identity +on GKE). The CRD already reserves `CredentialsSecretRef` on both +provider configs, but the operator validator rejects it as "not +yet supported in v1alpha1". + +cert-manager's underlying API does support static credentials — +`Route53.accessKeyIDSecretRef` + `Route53.secretAccessKeySecretRef` +on AWS, `CloudDNS.serviceAccountSecretRef` on GCP. The work is in +the operator: copy the user-supplied Secret from the operator +namespace into the cert-manager namespace (mirroring the +CustomCA-copy pattern), then reference the copied Secret from the +ClusterIssuer's ACME solver spec. + +**Scope:** + +1. Validator: accept `CredentialsSecretRef` on Route53 and + CloudDNS provider configs; enforce key presence + (`aws_access_key_id` + `aws_secret_access_key` for Route53, + `credentials.json` for CloudDNS) via the same + `checkCustomCASecret`-style helper. +2. Copy step: ensure helper analogous to + `ensureCustomCASecretCopy` that mirrors the credentials Secret + into the cert-manager namespace under a deterministic name. +3. `buildACMEIssuer`: when CredentialsSecretRef is set, populate + `Route53.SecretAccessKeyID/SecretAccessKey` or + `CloudDNS.ServiceAccount` instead of relying on identity-based + inference. +4. Mutual exclusivity: existing CEL/validator already enforces + one mechanism only — verify the rule still applies after + reactivating CredentialsSecretRef. + +**Acceptance criteria:** + +- `educates-installer` reaches Ready on a kind cluster (or any + cluster without IRSA/WI) using static AWS credentials. +- Validator returns clear messages on missing keys / both + mechanisms set. +- envtest covers: valid static creds (Route53 + CloudDNS), + missing key, and the "both set" rejection. + +--- + +### Expose ACME server URL choice (staging vs production) + +**Date added:** 2026-05-14. +**Trigger to file:** post-Phase-3 polish — testing real ACME on +fresh clusters quickly hits Let's Encrypt production rate limits. + +**Context:** + +`ACMEConfig.Server` is exposed in v1alpha1 and defaults to +`https://acme-v02.api.letsencrypt.org/directory` when unset. The +field works today; what's missing is good documentation and +example values for Let's Encrypt staging +(`https://acme-staging-v02.api.letsencrypt.org/directory`) and +guidance on when each is appropriate. CLI / docs should call out +the staging endpoint for first-time testing because the operator +exits the install pipeline on rate-limit errors and the user +sees a hard failure rather than a transient one. + +**Scope:** + +- Reference docs for the `acme.server` field with a worked + example for staging. +- Example CR snippets in `project-docs/` covering both Route53 + and CloudDNS for production + staging. +- Consider a `--acme-staging` shortcut on `educates install` + when the CLI rewrite (Phase 5) reaches the + `EducatesClusterConfig` builder. + +**Acceptance criteria:** + +- Reference docs clearly differentiate production and staging + use cases. +- Sample CRs in repository demonstrate both setups. + +--- + +### SessionManager: wire remaining spec fields into chart values + +**Date added:** 2026-05-14. +*(partially landed: 2026-06-10 — items 1 and 3 are done for their +supported scope. Secret-sourced themes map to +`websiteStyling.themeDataRefs` + `defaultTheme` (a `secretRef` field +was added to `ThemeSource`; ConfigMap/URL sources are rejected as "not +yet supported in v1alpha1"). `spec.imagePrePuller.enabled` passes +through to the chart, which now derives the default pre-pull list +(training-portal + base-environment) from its imageVersions helper — +see decisions.md. Items 2 (`defaultAccessCredentials`) and 4 +(`registryMirrors`) remain reserved and are now rejected explicitly by +`validateSessionManagerSpec` instead of silently discarded.)* +**Trigger to file:** any user reporting that themes, image cache, +registry mirrors, or default access credentials configured on the +SessionManager CR don't take effect. + +**Context:** + +`renderSessionManagerValues` (installer/operator/internal/controller/ +platform/sessionmanager_controller.go) maps the SessionManagerSpec +fields the v1alpha1 CRD exposes today onto the session-manager +subchart's values shape. Four spec blocks are reserved in the CRD +but not yet wired through; the reconciler explicitly discards them +via `_ = obj.Spec.` so the gap is visible in the source: + +1. **`spec.themes` + `spec.defaultTheme`** — the subchart accepts + `websiteStyling.themeDataRefs` (Secret refs only) plus an inline + blob. The CRD's `ThemeSource` supports `ConfigMap`, `Secret`, and + `URL`. Translating ConfigMap-sourced themes requires either + extending the subchart to accept ConfigMap refs or having the + operator copy/transform the ConfigMap into a Secret in the + release namespace at apply time. +2. **`spec.defaultAccessCredentials`** — the runtime carries an + admin/robot credentials pipeline (now stable via Helm `lookup` + in `resolvedTrainingPortal`), but the CRD's + `DefaultAccessCredentials` is a separate concept that pre-seeds + *workshop* (not portal-admin) credentials. The subchart has no + typed value for it yet; landing it requires a chart-side + addition plus an operator mapping. +3. **`spec.imagePrePuller`** — `imagePrePuller.enabled: true` should + toggle the chart's `imagePrePuller.enabled` plus pre-populate + `imagePrePuller.images` from the resolved image inventory. Neither + half is in place yet. +4. **`spec.registryMirrors`** — the v3 carvel runtime had a + workshop-side registry mirror story (rewriting workshop + container pulls to internal mirrors). No chart wiring in v4 yet; + needs a runtime-config field and a chart values shape. + +**Scope:** + +One follow-up PR per item, in order of demand. (1) likely first +because themes are user-facing; (3) and (4) tend to land together +because they share the air-gap/mirror story. + +**Acceptance criteria:** + +- Each item's spec block, when set on a SessionManager CR, takes + effect at runtime on a real cluster (verified manually). +- envtest specs assert the values map renders the expected + subchart-values shape for each. +- Reconciler removes the `_ = obj.Spec.` placeholder and + notes the mapping in `renderSessionManagerValues`'s comment. + +--- + +### Block EducatesClusterConfig finalize while platform CRs exist + +**Date added:** 2026-05-14. +*(landed: 2026-06-10 — Managed-mode deletion path checks the three +platform singletons before `cleanupManaged`; while any exist it +publishes `Ready=False reason=PlatformCRsPresent` / +`phase=Uninstalling` naming the offenders and requeues. Watches on the +three platform kinds re-enqueue the ECC on their deletion; a 15s +requeue backstops missed events. envtest covers both ordering paths.)* + +**Trigger to file:** observed on a real GKE cluster — deleting +`EducatesClusterConfig` first then the three platform CRs led to +SessionManager's finalizer drain failing in a tight loop with the +opaque helm error `failed to delete release: session-manager`. + +**Context:** + +The Phase 4 platform reconcilers (SecretsManager, LookupService, +SessionManager) install helm releases that track resources +created from cluster-services CRDs (kyverno ClusterPolicy in +particular). When the user deletes `EducatesClusterConfig` +first, ECC's finalizer drains the cluster services in reverse +install order — which removes Kyverno (and its CRDs). The +SessionManager helm release Secret still references kyverno +ClusterPolicy resources by name; when the SessionManager +finalizer subsequently runs `helm uninstall`, helm can't +enumerate those kinds anymore (CRD gone, NoMatchError under the +hood) and collapses the per-resource error into a generic +"failed to delete release" with no detail. + +User experience: SessionManager stuck `Uninstalling` forever; +`kubectl delete sessionmanager cluster` hangs; the only way out +is to manually patch the finalizer off and clean up the orphan +`educates` namespace by hand. + +The architectural fix is to make EducatesClusterConfig's +finalizer refuse to proceed while any of the three platform CRs +exist. The user then sees a clear "Stuck terminating: platform +CRs still present" status message and learns the order. + +**Scope:** + +- Extend `EducatesClusterConfigReconciler.cleanupManaged` (or + its caller) with a pre-flight check: list SecretsManager, + LookupService, SessionManager singletons. If any exist (even + in Terminating state), publish a `Ready=False` / + `Phase=Uninstalling` condition with reason + `PlatformCRsPresent` and message naming the offenders; + requeue without proceeding. +- Watch on the three platform CR kinds from the + EducatesClusterConfigReconciler so deletion events re-enqueue + ECC. +- envtest spec: delete ECC while a SecretsManager exists; + assert ECC stays terminating and surfaces the condition; + delete SecretsManager; assert ECC unblocks. + +**Why not "ignore missing kinds during uninstall"?** + +Tempting alternative is to make the helm wrapper tolerant of +NoMatchError during uninstall (treat as "already gone, drain +proceeds"). This works but masks a real ordering bug: the user +intended the platform CRs to drain first, and silently completing +the SessionManager uninstall with kyverno-related resources +half-orphaned in the `educates` namespace leaves the cluster in +an inconsistent state. Refusal + clear error is the better UX. + +**Related visibility fix already landed:** + +helm SDK's slog handler is now wired to the operator pod's +stderr at Debug level (commit TBD), so future runs surface the +per-resource error detail behind the collapsed +"failed to delete release" message. That helps diagnosis even +when the architectural fix isn't yet in place. + +**Acceptance criteria:** + +- Deleting ECC while any platform CR exists publishes the + `PlatformCRsPresent` condition and does not proceed with + cluster-service cleanup. +- Deleting platform CRs first lets ECC's finalizer run cleanly. +- envtest covers both ordering paths. + + +--- + +### Revisit `imageCache` naming (was `imagePuller` in v3) + +*(resolved: 2026-05-27 — standardised on `imagePrePuller` across CRD, +chart, and CLI; list field renamed to `images`. See decisions.md "Image +pre-pull feature named `imagePrePuller`". Original analysis kept below.)* + +**Date added:** 2026-05-20. +**Trigger to file:** raised during Phase 5 CLI config design when +deciding what name to expose in `EducatesLocalConfig`. The mismatch +between v3 muscle memory (`imagePuller`) and the CRD r3 name +(`imageCache`) is the kind of papercut that lingers if not chosen +deliberately. + +**Context:** + +- **v3 name:** `imagePuller` (under + `client-programs/pkg/config/installationconfig.go::ImagePullerConfig`, + with fields `enabled` and `prePullImages[]`). +- **v4 CRD r3 name:** `SessionManager.spec.imageCache` (single + `enabled` boolean; pre-pull list is intended to be derived + from the chart's resolved image inventory rather than user- + listed — see the existing follow-up "SessionManager: wire + remaining spec fields into chart values" item 3). +- **Chart-side name:** session-manager subchart still uses + `imagePuller.enabled` / `prePullImages` (matches v3 terminology). +- **EducatesLocalConfig (Phase 5):** currently planned to expose + `imageCache: false` to align with the CRD; will surface to users + as the new name on first contact. + +**What the feature actually does:** + +A DaemonSet runs on each node that pre-pulls (caches) workshop- +related images so workshop session startup is fast. "Cache" is +accurate as a noun (the cached images on each node); "puller" is +accurate as a verb (what populates the cache). Either name is +defensible. + +**Action item:** + +Decide which name to standardise on across all surfaces, then +align the three places: + +1. **Option A — keep `imageCache` everywhere.** Rename the chart + field `imagePuller` → `imageCache` (breaking for any standalone + chart users). v3 terminology is dropped. EducatesLocalConfig + stays as drafted. +2. **Option B — revert to `imagePuller` everywhere.** Rename the + CRD field `imageCache` → `imagePuller` (only impacts in-flight + v1alpha1 — no users yet). Chart stays as-is. EducatesLocalConfig + becomes `imagePuller: false`. Preserves v3 muscle memory. +3. **Option C — pick a third name.** Candidates: `prePuller`, + `imageWarmup`, `nodeImageCache`. Apply consistently. + +**Recommendation:** decide before Phase 4 lands the SessionManager +reconciler — renaming the CRD field is cheap pre-Phase-4 and +expensive after. + +**Acceptance criteria:** + +- One name chosen and applied consistently across CRD spec, + session-manager subchart values, and `EducatesLocalConfig` / + `EducatesConfig` translator. +- CRD draft r3 (or its successor) updated. +- decisions.md entry recording the choice and reasoning. + +--- + +### CLI: CI drift checks for embedded operator chart and generated `EducatesConfig` schema + +**Date added:** 2026-06-10 (accumulated during Phase 5 steps 2 + 5). +*(landed: 2026-06-10 — `make verify-installer-chart` / +`make verify-cli-schemas` regen-and-diff targets in the root Makefile, +run by the new `client-programs-ci.yaml` workflow alongside CLI +vet/build/test, triggered on client-programs and +installer/charts/educates-installer changes.)* + +**Trigger to file:** immediately — both artifacts can silently drift +today. + +**Context:** + +Two CLI-embedded artifacts are copies of generated/canonical sources: +`client-programs/pkg/deployer/chart/files/` is a copy of +`installer/charts/educates-installer/` (refreshed by `make +embed-installer-chart`; the Makefile comment explicitly notes the CI +check is a follow-up), and +`client-programs/pkg/config/v1alpha1/schemas/EducatesConfig.schema.json` +is generated from the CRD OpenAPI schemas by `make +generate-cli-schemas`. Neither is verified in CI; a CRD or chart +change without the corresponding regen ships a CLI that installs +stale manifests or validates against a stale schema. + +**Scope:** + +CI steps (CLI workflow or installer-operator-ci.yaml) that run both +make targets and fail on `git diff --exit-code` over the embedded +copies. + +**Acceptance criteria:** + +- CI fails when `installer/charts/educates-installer/` and the + embedded chart copy differ. +- CI fails when the committed `EducatesConfig.schema.json` differs + from freshly generated output. +- Failure message names the make target to run. + +--- + +### CLI: deploy/delete hardening follow-ups + +**Date added:** 2026-06-10 (accumulated during Phase 5 steps 5–6). +**Trigger to file:** post-Phase-5; none block daily use. + +Already landed from the same accumulation: deploy-side CRD lifecycle +(`14216722`, `a9109bf1`), structured progress reporting (`8909ff53`), +`--yes` + `--purge` on delete (`4b4a1741`), create-preflight existence +guard + port probe (`c4b59f15`). + +**Still open, in rough priority order:** + +1. **Mocked tests for cluster-touching deploy code.** + `client-programs/pkg/deployer/{apply,wait,prereq,helm}` have no + unit tests — confidence currently comes from kind smoke runs only. + fake.NewClientBuilder + the helm in-memory client wrapper would + unblock CI-time coverage. +2. **`--force-finalizers` on delete.** A wedged finalizer currently + requires a manual `kubectl patch`; flag automates it for users who + accept the loss. +3. **Apply-all-then-wait-all CR orchestration.** Sequential + apply-then-wait is fragile with bidirectional CR readiness deps + (the LookupService/SessionManager cycle, worked around in + `0d79afc6` by pairing them). Cleaner: apply every CR upfront, then + poll the set for Ready with a shared deadline. +4. **Operator image rebuild guidance.** Detect a dev-tag pod whose + image digest doesn't match the latest local build; warn or accept + `--rebuild-operator` (docker-build + kind load + rollout). +5. **Helm release labels/annotations.** Stamp releases with CLI + version + build SHA so `helm list` shows provenance. + +**Acceptance criteria:** each item lands as its own small PR with +tests; this entry gets per-item `*(landed: ...)*` marks. + +--- + +### CLI: `local config` UX papercuts + +**Date added:** 2026-06-10 (accumulated during Phase 5 step 7). +**Trigger to file:** on user demand; cheap wins for daily ergonomics. + +1. **Path suggestions on missing-field errors** — `get ingress.domian` + → "did you mean `ingress.domain`?" via a schema-walker producing + valid paths + fuzzy match. +2. **Tab completion on dotted paths** — Cobra `ValidArgsFunction` + walking the embedded JSON schema. +3. **`set` for list paths** — e.g. `set resolver.extraDomains[0] + foo.test`; today only map paths work. +4. **`unset PATH`** — remove a key without re-initing the file. + +**Acceptance criteria:** each papercut fixed with schema-driven tests; +no hand-maintained path lists. + +--- + +### CLI: scenario-kind regression tests (escape-hatch round-trip, sample-CR parity) + +**Date added:** 2026-06-10 (accumulated during Phase 5 step 11). +**Trigger to file:** before the next scenario kind or CRD field change. + +**Context:** + +The scenario kinds (Local/GKE/EKS/Inline) and the `EducatesConfig` +escape hatch both translate to the same four CRs, and each scenario +kind was admitted against a tested sample CR in `installer/samples/`. +Neither relationship is pinned by a test today. + +**Scope:** + +1. **Round-trip test:** `render --config inline.yaml` and `render + --config escape.yaml` declaring the same EducatesClusterConfig must + produce identical output. +2. **Sample-CR parity test:** render the minimal scenario config per + kind and diff against its `installer/samples/` CR — catches drift + in either direction. +3. Clearer error when `local cluster create` is given a non-Local + kind (today's message doesn't say which kinds are accepted). +4. **Cloud auth alternatives** (static credentials for GKE/EKS) stay + rejected until the operator-side follow-up "ACME static-credentials + Secret support" lands; CLI schema + translator follow it. + +**Acceptance criteria:** tests live with the translator package and +run in CI; the error message names accepted kinds. + +--- + +### CLI: `educates admin platform images copy` for air-gapped relocation + +**Date added:** 2026-06-11. +**Trigger to file:** when the first air-gapped consumer asks for a +single-command transport, or when writing the air-gap installation +docs makes the skopeo loop feel too raw. + +**Context:** + +The Phase 6 relocation decision (see decisions.md "Image relocation is +a published digest-pinned list") ships a per-release +`educates-images-.txt` and documents name-preserving +mirroring with skopeo/crane. That flow works everywhere but is a +loop of third-party commands. `helm dt`-style single-command UX +(one tarball out, one command in) was the only thing the rejected +tools offered that we kept wanting. + +**Scope:** + +Add `educates admin platform images copy` (final naming TBD) with two +modes: + +- `--to-tar `: read an image list (default: fetch the list for + the CLI's own version from the GitHub release; `--images-file` + override), pull every image and write a single tarball. +- `--from-tar --to-registry `: push the tarball's + images into the target registry **preserving repository paths** + under the prefix (NOT imgpkg's single-repo flattening), so the + charts' annotation ladder and the operator's + `imageRegistry.prefix` rewriting resolve them directly. + +Implement with the Carvel registry libraries already vendored in the +CLI (or go-containerregistry, whichever is less code); multi-arch +indexes must be copied whole. + +**Acceptance criteria:** + +- Round-trip (to-tar → from-tar) lands every image from the list in + the target registry under preserved paths, digests intact. +- Air-gap docs show the CLI flow as primary and skopeo as the + tool-agnostic alternative. + +--- + +### External load balancer support (restore `clusterIngress.protocol`, possibly as a full externalLoadBalancer capability) + +**Date added:** 2026-06-11 (expanded same day after design discussion; +deliberately deferred — see "Why deferred" below). +**Status:** partially landed 2026-06-11 — the URL-generation half +shipped as the minimal slice: `SessionManager.spec.ingressOverrides. +protocol` (http|https) threaded to the chart's `clusterIngress. +protocol`, exposed as `externalTLSTermination: true` on +`EducatesGKEConfig` / `EducatesEKSConfig` / `EducatesInlineConfig` +(and via `EducatesConfig` through the regenerated schema). STILL OPEN: +certificate-less installs (`ingress.certificates` / Inline wildcard +secret remain required, so GKE/EKS still provision the unused ACME +stack behind an external LB), LookupService URL coherence, envoy +NodePort exposure for ALB-fronted setups, and the full +externalLoadBalancer modelling below. +**Trigger to file:** first user report needing Cloudflare Tunnel / +ALB+ACM / plain-HTTP-behind-proxy with an operator-driven install. +This is a frequently used v3 capability, so likely soon after v4 ships. + +**Context:** + +v3 supported `clusterIngress.protocol: https` with no in-cluster +certificate, for deployments where an external proxy/CDN terminates +public TLS and forwards plain HTTP to the cluster (Cloudflare +Flexible/Tunnel, AWS ALB with ACM). The v4 `EducatesClusterConfig` +requires `ingress.certificates` in Managed mode and Inline mode +requires `wildcardCertificateSecret` — neither can express "no +in-cluster TLS, but generate https:// URLs". The session-manager +subchart still has the knob (`ingress.protocol`, auto-derived when +empty), so the standalone-chart install path supports the scenario; +only the operator surface is missing. Surfaced while rewriting +`project-docs/installation-guides/secure-http-connections.md`, which +currently documents the standalone chart as the workaround. + +**Design discussion outcome (2026-06-11):** + +- The protocol is NOT a certificates-provider concern — no new + `certificates.provider` value. It is a URL-generation concern owned + by the session-manager (and workshops): an assertion to the + operator that the public edge is https even though the cluster + terminates none. The natural home is a field on the + `SessionManager` CR (e.g. alongside `spec.ingressOverrides`), + threaded to the session-manager chart's existing `ingress.protocol` + value. +- Independently, "configured without certificates" must become + expressible in `EducatesClusterConfig` (relax `ingress.certificates` + required in Managed and/or `wildcardCertificateSecretRef` in + Inline) for the scenario to exist operator-side. +- Open coherence question: LookupService also publishes URLs from its + own ingress; without the same treatment a proxy-fronted install + gets https workshop links but an http lookup-service URL. + +**Why deferred / the bigger shape:** + +A point fix (protocol field + requiredness relaxation) may not give a +full end-to-end solution — properly supporting external load +balancers likely has wider implications, potentially requiring +rewrites in session-manager and other Educates runtime internals +(URL composition, ingress creation for workshop services, header +handling). Runtime components are explicitly out of scope for v4 +(installer-only change), so rather than landing a partial knob now, +tackle this as a designed **`externalLoadBalancer` capability**: +model the external edge (protocol, possibly ports/hostname mapping +and forwarded-header expectations) as a first-class concept consumed +end-to-end by the operator, the platform components and workshop +ingress creation. + +**Scope (when picked up):** + +Design first — decide between the minimal restoration (SessionManager +protocol field + certificates-optional relaxation, accepting the +LookupService gap or covering it) and the full externalLoadBalancer +capability; assess the runtime-internals impact before committing to +either. Then update the CRD draft, implement, and update +secure-http-connections.md to drop the standalone-chart workaround. + +**Acceptance criteria:** + +- An operator-driven install can serve proxy-terminated HTTPS with no + in-cluster certificate, generating https:// URLs consistently + across session-manager-created resources (and lookup-service, if in + scope). +- CEL/validation keeps the configuration coherent (no silent + insecure installs). +- secure-http-connections.md documents the supported shape. diff --git a/docs/architecture/session-manager-chart-values-schema.json b/docs/architecture/session-manager-chart-values-schema.json new file mode 100644 index 000000000..6173385d2 --- /dev/null +++ b/docs/architecture/session-manager-chart-values-schema.json @@ -0,0 +1,366 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "Educates session-manager subchart values", + "type": "object", + "additionalProperties": false, + "required": ["workshopSecurity"], + "description": "Cross-cutting blocks (clusterIngress, clusterSecurity, imageRegistry) may come from the umbrella's `.global` instead of being set here. Subchart-local values pass through when globals are unset; globals win when both are set. Helpers enforce non-empty resolved values at template time.", + + "definitions": { + + "imageRef": { + "description": "Image reference. Empty `repository` falls through to the imageRegistry-derived default; empty `tag` falls through to Chart.AppVersion.", + "type": "object", + "additionalProperties": false, + "properties": { + "repository": { "type": "string" }, + "tag": { "type": "string" }, + "pullPolicy": { + "type": "string", + "enum": ["", "Always", "IfNotPresent", "Never"] + } + } + }, + + "secretRef": { + "description": "Reference to a Kubernetes Secret. Empty `name` means the ref is unset.", + "type": "object", + "additionalProperties": false, + "properties": { + "name": { "type": "string" }, + "namespace": { "type": "string" } + } + }, + + "kyvernoClusterPolicy": { + "description": "A Kyverno ClusterPolicy resource. Open shape; only top-level identity is validated.", + "type": "object", + "required": ["apiVersion", "kind", "metadata"], + "properties": { + "apiVersion": { "const": "kyverno.io/v1" }, + "kind": { "const": "ClusterPolicy" }, + "metadata": { + "type": "object", + "required": ["name"], + "properties": { + "name": { "type": "string", "minLength": 1 } + } + } + } + }, + + "trackingIdBlock": { + "type": "object", + "additionalProperties": false, + "properties": { + "trackingId": { "type": "string" } + } + }, + + "stylingTriple": { + "type": "object", + "additionalProperties": false, + "properties": { + "html": { "type": "string" }, + "script": { "type": "string" }, + "style": { "type": "string" } + } + }, + + "stylingHtmlOnly": { + "type": "object", + "additionalProperties": false, + "properties": { + "html": { "type": "string" } + } + } + }, + + "properties": { + + "clusterIngress": { + "type": "object", + "additionalProperties": false, + "properties": { + "domain": { + "type": "string", + "description": "Wildcard subdomain. Required after merging with .global.clusterIngress; helper fails at template time if the resolved value is empty." + }, + "class": { "type": "string" }, + "protocol": { + "type": "string", + "enum": ["", "http", "https"], + "description": "Empty for auto-derive from tlsCertificateRef." + }, + "tlsCertificateRef": { "$ref": "#/definitions/secretRef" }, + "caCertificateRef": { "$ref": "#/definitions/secretRef" } + } + }, + + "clusterSecurity": { + "type": "object", + "additionalProperties": false, + "properties": { + "policyEngine": { + "type": "string", + "enum": ["Kyverno", "PodSecurityStandards", "OpenShiftSCC", "None"] + }, + "additionalKyvernoPolicies": { + "type": "array", + "items": { "$ref": "#/definitions/kyvernoClusterPolicy" } + } + } + }, + + "workshopSecurity": { + "type": "object", + "additionalProperties": false, + "required": ["rulesEngine"], + "properties": { + "rulesEngine": { + "type": "string", + "enum": ["Kyverno", "None"] + }, + "additionalKyvernoPolicies": { + "type": "array", + "items": { "$ref": "#/definitions/kyvernoClusterPolicy" } + } + } + }, + + "development": { + "description": "Local-development overrides. Leave empty in normal use — Chart.yaml annotations (`educates.dev/image-registry-{host,namespace}`) provide the publish-time defaults for chart-rendered image refs, and the runtime falls back to `registry.default.svc.cluster.local` for `$(image_repository)` workshop-content placeholder resolution.", + "type": "object", + "additionalProperties": false, + "properties": { + "imageRegistry": { + "type": "object", + "additionalProperties": false, + "properties": { + "host": { "type": "string" }, + "namespace": { "type": "string" } + } + } + } + }, + + "imageVersions": { + "type": "array", + "items": { + "type": "object", + "additionalProperties": false, + "required": ["name", "image"], + "properties": { + "name": { "type": "string", "minLength": 1 }, + "image": { "type": "string", "minLength": 1 } + } + } + }, + + "image": { "$ref": "#/definitions/imageRef" }, + + "imagePullSecrets": { + "description": "Pod-spec imagePullSecrets attached to the session-manager pod itself. Standard Kubernetes [{name: ...}] shape.", + "type": "array", + "items": { + "type": "object", + "additionalProperties": false, + "required": ["name"], + "properties": { + "name": { "type": "string", "minLength": 1 } + } + } + }, + + "resources": { + "type": "object" + }, + + "clusterAdmin": { "type": "boolean" }, + + "trainingPortal": { + "type": "object", + "additionalProperties": false, + "properties": { + "credentials": { + "type": "object", + "additionalProperties": false, + "properties": { + "admin": { + "type": "object", + "additionalProperties": false, + "properties": { + "username": { "type": "string" }, + "password": { "type": "string" } + } + }, + "robot": { + "type": "object", + "additionalProperties": false, + "properties": { + "username": { "type": "string" }, + "password": { "type": "string" } + } + } + } + }, + "clients": { + "type": "object", + "additionalProperties": false, + "properties": { + "robot": { + "type": "object", + "additionalProperties": false, + "properties": { + "id": { "type": "string" }, + "secret": { "type": "string" } + } + } + } + } + } + }, + + "sessionCookies": { + "type": "object", + "additionalProperties": false, + "properties": { + "domain": { "type": "string" } + } + }, + + "clusterStorage": { + "type": "object", + "additionalProperties": false, + "properties": { + "class": { "type": "string" }, + "user": { "type": ["integer", "null"] }, + "group": { "type": "integer" } + } + }, + + "clusterRuntime": { + "type": "object", + "additionalProperties": false, + "properties": { + "class": { "type": "string" } + } + }, + + "clusterNetwork": { + "type": "object", + "additionalProperties": false, + "properties": { + "blockCIDRs": { + "type": "array", + "items": { "type": "string" } + } + } + }, + + "dockerDaemon": { + "type": "object", + "additionalProperties": false, + "properties": { + "networkMTU": { "type": "integer", "minimum": 0 }, + "proxyCache": { + "type": "object", + "additionalProperties": false, + "properties": { + "remoteURL": { "type": "string" }, + "username": { "type": "string" }, + "password": { "type": "string" } + } + } + } + }, + + "workshopAnalytics": { + "type": "object", + "additionalProperties": false, + "properties": { + "google": { "$ref": "#/definitions/trackingIdBlock" }, + "clarity": { "$ref": "#/definitions/trackingIdBlock" }, + "amplitude": { "$ref": "#/definitions/trackingIdBlock" }, + "webhook": { + "type": "object", + "additionalProperties": false, + "properties": { + "url": { "type": "string" } + } + } + } + }, + + "websiteStyling": { + "type": "object", + "additionalProperties": false, + "properties": { + "inline": { + "type": "object", + "additionalProperties": false, + "description": "Inline HTML/JS/CSS for the fallback default theme. Each populated leaf becomes a stringData entry in the `default-website-theme` Secret.", + "properties": { + "workshopDashboard": { "$ref": "#/definitions/stylingTriple" }, + "workshopInstructions": { "$ref": "#/definitions/stylingTriple" }, + "workshopStarted": { "$ref": "#/definitions/stylingHtmlOnly" }, + "workshopFinished": { "$ref": "#/definitions/stylingHtmlOnly" }, + "trainingPortal": { "$ref": "#/definitions/stylingTriple" } + } + }, + "defaultTheme": { "type": "string" }, + "themeDataRefs": { + "type": "array", + "items": { "$ref": "#/definitions/secretRef" } + }, + "frameAncestors": { + "type": "array", + "items": { "type": "string" } + } + } + }, + + "imagePrePuller": { + "type": "object", + "additionalProperties": false, + "properties": { + "enabled": { "type": "boolean" }, + "pauseImage": { "$ref": "#/definitions/imageRef" }, + "images": { + "type": "array", + "items": { "type": "string", "minLength": 1 } + } + } + }, + + "secretPropagation": { + "type": "object", + "additionalProperties": false, + "properties": { + "imagePullSecretNames": { + "type": "array", + "items": { "type": "string", "minLength": 1 } + }, + "upstream": { + "type": "object", + "additionalProperties": false, + "properties": { + "imagePullSecrets": { + "type": "array", + "items": { "$ref": "#/definitions/secretRef" } + }, + "websiteThemes": { + "type": "array", + "items": { "$ref": "#/definitions/secretRef" } + } + } + } + } + }, + + "config": { + "type": "object", + "description": "Opaque escape hatch deep-merged on top of typed-derived runtime config." + } + } + } diff --git a/docs/architecture/session-manager-chart-values.yaml b/docs/architecture/session-manager-chart-values.yaml new file mode 100644 index 000000000..bf525fe9c --- /dev/null +++ b/docs/architecture/session-manager-chart-values.yaml @@ -0,0 +1,362 @@ +# Values for the session-manager subchart. +# +# In a v4 install, the operator derives these values from the SessionManager CR +# plus EducatesClusterConfig.status. They can also be set directly when +# installing the chart standalone. +# +# Cross-cutting blocks — `imageRegistry`, `clusterIngress`, `clusterSecurity` — +# can also be set at the umbrella level under `global:`. The chart deep-merges +# the umbrella's `global.` over the subchart-local block, with globals +# winning per-leaf where set. Subchart-local defaults below are the standalone- +# install default; under the umbrella they're typically left at defaults and +# the cross-cutting values come from `global:`. + +# ============================================================================= +# Cluster-wide ingress identity +# ============================================================================= + +# `domain` is required. Chart fails at template time if empty. +# `protocol` is auto-derived from tlsCertificateRef when empty: "http" if no +# ref is set, "https" otherwise. Override only for external TLS termination +# (router terminates TLS and proxies plain HTTP into the cluster). +clusterIngress: + domain: "" + class: "" + protocol: "" + + # Reference to a kubernetes.io/tls Secret holding the wildcard cert for + # *.. Required keys: tls.crt, tls.key. When `namespace` is empty + # the Secret is assumed to live in the release namespace. When set to a + # different namespace, the chart auto-creates a SecretCopier so the runtime + # finds the Secret locally. + tlsCertificateRef: + name: "" + namespace: "" + + # Reference to a Secret holding the CA certificate used to verify the + # wildcard. Required key: ca.crt. Same namespace semantics as the TLS ref. + caCertificateRef: + name: "" + namespace: "" + +# Note: cluster-node CA injection is its own subchart (`node-ca-injector`) +# at the umbrella, not a flag here. It consumes `global.clusterIngress. +# caCertificateRef` and is enabled via the umbrella's `node-ca-injector. +# enabled` toggle (default off). + +# ============================================================================= +# Security policy enforcement +# ============================================================================= + +# Cluster-level security policy enforcement. +# +# - Kyverno: installs the bundled cluster ClusterPolicies (PSS baseline + +# restricted profiles + operational best-practices) directly to the cluster. +# `additionalKyvernoPolicies` are installed alongside. +# - OpenShiftSCC: installs ClusterRoleBindings binding the session-manager and +# image-puller ServiceAccounts to the `educates-baseline-scc` ClusterRole. +# Implies you're on OpenShift; SCC enforcement comes from the platform. +# - PodSecurityStandards: chart installs nothing at this level; PSS is enforced +# by Kubernetes via namespace labels managed by the runtime. +# - None: no cluster-level policy enforcement. User accepts responsibility. +# +# `additionalKyvernoPolicies` is silently ignored when policyEngine is not +# Kyverno. +clusterSecurity: + policyEngine: Kyverno # Kyverno | PodSecurityStandards | OpenShiftSCC | None + additionalKyvernoPolicies: [] + # - apiVersion: kyverno.io/v1 + # kind: ClusterPolicy + # metadata: + # name: my-cluster-wide-extra + # spec: + # validationFailureAction: Audit + # rules: + # - name: ... + +# Per-workshop policy enforcement. The chart concatenates a curated bundle +# (operational best-practices + Educates-internal `require-ingress-session-name`) +# into the `kyverno-policies.yaml` key of the `educates-config` Secret; +# session-manager clones each rule per workshop environment with a namespace +# selector added. +# +# `additionalKyvernoPolicies` is appended to the same feed and is silently +# ignored when rulesEngine is not Kyverno. +workshopSecurity: + rulesEngine: Kyverno # Kyverno | None + additionalKyvernoPolicies: [] + # - apiVersion: kyverno.io/v1 + # kind: ClusterPolicy + # metadata: + # name: my-per-workshop-extra + # spec: + # rules: + # - name: ... + +# ============================================================================= +# Image registry +# ============================================================================= + +# Local-development overrides. Leave the `development:` block empty in +# normal use — Educates image refs resolve from the chart's publish-time +# defaults (Chart.yaml annotations `educates.dev/image-registry-host` / +# `-namespace`, set per-fork by the publish workflow) and the runtime's +# `IMAGE_REPOSITORY` env var falls back to the in-cluster service +# `registry.default.svc.cluster.local`. +# +# When `development.imageRegistry` IS set, ONE knob has two effects: +# 1. Replaces the Chart.yaml annotation defaults — chart pod, pause +# image, and the Educates-published entries in the `imageVersions` +# helper resolve against `{host}/{namespace}` instead. +# 2. Emits the same `{host}/{namespace}` into the runtime config blob, +# so workshop sessions get `IMAGE_REPOSITORY={host}/{namespace}` and +# `$(image_repository)` content placeholders resolve there (the +# typical local-dev flow where `educates publish-workshop` pushes +# to localhost:5001). +# +# Mirrors v3's `imageRegistry` schema knob, which the v3 schema comment +# explicitly described as "for development, experimentation and when +# working on workshop content in a local Educates environment, and should +# not be overridden through a values file in normal use." +development: + imageRegistry: + host: "" + namespace: "" + +# Per-image overrides, merged BY NAME on top of the chart-shipped default +# `imageVersions` list. The default list is built in the chart's helper +# (`session-manager.imageVersions`) and mirrors v3's carvel-installer +# `images.yaml`: +# - Educates-published images, tag = `Chart.AppVersion`. +# - Upstream pins (docker-in-docker, loftsh-*, debian-base), specific tags. +# An override matching a default by `name` replaces just that entry; other +# defaults pass through. Names not in the default list are appended. +# Use for airgap relocation, JDK/k8s variant pinning, or to mirror images +# under a different registry without forking the helper. +imageVersions: [] + # - name: base-environment + # image: my-registry.example.com/educates/base-environment@sha256:... + +# ============================================================================= +# Session-manager pod +# ============================================================================= + +image: + # Empty `repository` derives `{imageRegistry.host}/{imageRegistry.namespace}/educates-session-manager`. + # Empty `tag` falls through to `Chart.AppVersion`. Override either only + # when the chart-pod image diverges from the rest of the runtime (e.g., + # a development build). + repository: "" + tag: "" + pullPolicy: "" + +# Image-pull Secrets attached to the session-manager pod's own PodSpec. These +# are the Secrets needed to pull the session-manager image itself. For Secrets +# that should propagate into workshop namespaces, see `secretPropagation` below. +imagePullSecrets: [] + +resources: {} + +# Grant the session-manager ServiceAccount the built-in `cluster-admin` +# ClusterRole. Off by default; enable only when workshops need to manage +# cluster-scoped resources beyond what the aggregated `educates-session-manager` +# ClusterRole grants. Note: changed from v3 default of `true`. +clusterAdmin: false + +# ============================================================================= +# Training portal defaults +# ============================================================================= + +# Empty values cause the runtime to generate them on first reconciliation. +# The chart deliberately does NOT use `randAlphaNum` defaults here because that +# would rotate values on every `helm upgrade` and break in-flight workshops. +trainingPortal: + credentials: + admin: + username: "" + password: "" + robot: + username: "" + password: "" + clients: + robot: + id: "" + secret: "" + +# Optional override for the cookie domain used by training portal and +# workshop sessions. Empty means "use the ingress domain." +sessionCookies: + domain: "" + +# ============================================================================= +# Storage +# ============================================================================= + +# `class` empty uses the cluster default StorageClass. +# `user` is null by default (filesystem chown unset). Set to a numeric UID +# only when the storage class maps to NFS and the server requires a specific +# user. Cannot be combined with PodSecurityStandards/Policies enforcement. +# `group` defaults to 1, suitable for clusters with pod security policies. +clusterStorage: + class: "" + user: null + group: 1 + +# ============================================================================= +# Container runtime +# ============================================================================= + +# Optional runtimeClass applied to workshop containers (e.g., "kata" for +# VM-isolated workshops). Empty leaves the cluster default. +clusterRuntime: + class: "" + +# ============================================================================= +# Cluster network policy +# ============================================================================= + +# CIDRs that workshops are blocked from reaching. Default blocks the AWS EC2 +# instance metadata endpoint (IPv4 and IPv6). Set to [] to remove all blocks. +clusterNetwork: + blockCIDRs: + - "169.254.169.254/32" + - "fd00:ec2::254/128" + +# ============================================================================= +# Docker daemon (only used when workshops build images) +# ============================================================================= + +dockerDaemon: + networkMTU: 1400 + # Mirror cache to mitigate Docker Hub pull limits. Set remoteURL to e.g. + # "https://registry-1.docker.io" to enable. + proxyCache: + remoteURL: "" + username: "" + password: "" + +# ============================================================================= +# Analytics +# ============================================================================= + +workshopAnalytics: + google: + trackingId: "" + clarity: + trackingId: "" + amplitude: + trackingId: "" + webhook: + url: "" + +# ============================================================================= +# Website styling and theming +# ============================================================================= + +# Two ways to supply themes: +# +# `inline` — HTML/JS/CSS authored directly in values. Each populated leaf +# becomes a stringData entry in the `default-website-theme` Secret, +# which the runtime uses as the fallback theme. Convenient for small +# tweaks without managing a separate Secret. +# +# `themeDataRefs` — references to external theme Secrets that already +# hold the assets. The chart makes them available to the runtime and +# auto-creates a SecretCopier when a ref's namespace differs from the +# release namespace. +websiteStyling: + inline: + workshopDashboard: + html: "" + script: "" + style: "" + workshopInstructions: + html: "" + script: "" + style: "" + workshopStarted: + html: "" + workshopFinished: + html: "" + trainingPortal: + html: "" + script: "" + style: "" + + # Name of the theme to use as default. Must match a key in `themeDataRefs`. + # Empty means "use the inline default theme (above)." + defaultTheme: "" + + # External theme Secrets to make available. Each ref points at a Secret + # holding theme assets. When `namespace` differs from the release namespace + # the chart auto-creates a SecretCopier. + themeDataRefs: [] + # - name: my-theme + # namespace: themes-source + + # Allowed parent frames for embedding workshop sessions (CSP + # frame-ancestors directive). + frameAncestors: [] + +# ============================================================================= +# Image pre-puller DaemonSet +# ============================================================================= + +# When enabled, runs an init-container per image in `images` (each running +# `/bin/true`) so the kubelet pre-pulls and caches them on every node ahead of +# time, plus a long-lived pause container to keep the DS alive. Useful for +# clusters where workshop session start time is dominated by image pull. +imagePrePuller: + enabled: false + # Pause image used as the long-lived "keepalive" container in the DaemonSet. + # Empty `repository` derives `{imageRegistry.host}/{imageRegistry.namespace}/educates-pause-container`. + # Empty `tag` falls through to `Chart.AppVersion`. + pauseImage: + repository: "" + tag: "" + pullPolicy: "" + # Full image references to pre-pull. Empty defaults to the v3-equivalent + # set -- training-portal + base-environment -- resolved through the + # imageVersions inventory, so registry relocation and per-name overrides + # are honoured. A non-empty list replaces the default verbatim (fully + # qualified refs only; short names are not resolved here). + images: [] + # - ghcr.io/educates/training-portal:4.0.0-alpha.1 + +# ============================================================================= +# Secret propagation +# ============================================================================= +# +# The session-manager runtime distributes pull secrets and website themes +# across workshop namespaces using SecretCopier and SecretInjector resources +# from secrets.educates.dev. +# +# Note: ingress TLS and CA propagation is auto-derived from +# `clusterIngress.tlsCertificateRef` and `clusterIngress.caCertificateRef` +# when those refs target a namespace other than the release namespace. There +# is no longer an explicit knob for it. + +secretPropagation: + # Names of image-pull Secrets that already exist in the release namespace + # and should be (a) propagated into every workshop-portal and + # workshop-environment namespace, and (b) injected into ServiceAccounts + # in those namespaces. + imagePullSecretNames: [] + # - my-registry-pull-secret + + upstream: + # External Secrets to copy INTO the release namespace before propagation. + imagePullSecrets: [] + # - { name: my-pull-secret, namespace: source-ns } + websiteThemes: [] + # - { name: my-theme, namespace: source-ns } + +# ============================================================================= +# Escape hatch +# ============================================================================= +# +# Opaque map deep-merged on top of the typed-values-derived +# `educates-operator-config.yaml` Secret content. Use only for runtime fields +# not yet promoted to typed values. Newly added fields should land here first +# and be promoted in a subsequent chart release. +config: {} diff --git a/go.work b/go.work index 6c7d3437c..4935152f7 100644 --- a/go.work +++ b/go.work @@ -1,6 +1,7 @@ -go 1.25.0 +go 1.26.0 use ( ./client-programs/ + ./installer/operator/ ./node-ca-injector/ ) diff --git a/go.work.sum b/go.work.sum index 4890e3bc7..88425c4de 100644 --- a/go.work.sum +++ b/go.work.sum @@ -1,24 +1,125 @@ bitbucket.org/bertimus9/systemstat v0.5.0/go.mod h1:EkUWPp8lKFPMXP8vnbpT5JDI0W/sTiLZAvN8ONWErHY= +buf.build/gen/go/bufbuild/protovalidate/protocolbuffers/go v1.36.4-20250130201111-63bb56e20495.1/go.mod h1:novQBstnxcGpfKf8qGRATqn1anQKwMJIbH5Q581jibU= +buf.build/gen/go/bufbuild/protovalidate/protocolbuffers/go v1.36.6-20250425153114-8976f5be98c1.1/go.mod h1:avRlCjnFzl98VPaeCtJ24RrV/wwHFzB8sWXhj26+n/U= +buf.build/go/protovalidate v0.12.0/go.mod h1:q3PFfbzI05LeqxSwq+begW2syjy2Z6hLxZSkP1OH/D0= +cel.dev/expr v0.24.0/go.mod h1:hLPLo1W4QUmuYdA72RBX06QTs6MXw941piREPl3Yfiw= +cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.110.4 h1:1JYyxKMN9hd5dR2MYTPWkGUgcoxVVhg0LKNKEo0qvmk= cloud.google.com/go v0.110.4/go.mod h1:+EYjdK8e5RME/VY/qLCAtuyALQ9q67dvuum8i+H5xsI= +cloud.google.com/go v0.116.0 h1:B3fRrSDkLRt5qSHWe40ERJvhvnQwdZiHu0bJOpldweE= +cloud.google.com/go v0.116.0/go.mod h1:cEPSRWPzZEswwdr9BxE6ChEn01dWlTaF05LiC2Xs70U= +cloud.google.com/go/auth v0.18.2/go.mod h1:xD+oY7gcahcu7G2SG2DsBerfFxgPAJz17zz2joOFF3M= +cloud.google.com/go/auth/oauth2adapt v0.2.8/go.mod h1:XQ9y31RkqZCcwJWNSx2Xvric3RrU88hAYYbjDWYDL+c= +cloud.google.com/go/compute v1.19.1 h1:am86mquDUgjGNWxiGn+5PGLbmgiWXlE/yNWpIpNvuXY= +cloud.google.com/go/compute v1.19.1/go.mod h1:6ylj3a05WF8leseCdIf77NK0g1ey+nj5IKd5/kvShxE= +cloud.google.com/go/compute/metadata v0.3.0/go.mod h1:zFmK7XCadkQkj6TtorcaGlCW1hT1fIilQDwofLpJ20k= +cloud.google.com/go/iam v1.2.2/go.mod h1:0Ys8ccaZHdI1dEUilwzqng/6ps2YB6vRsjIe00/+6JY= +cloud.google.com/go/monitoring v1.21.2/go.mod h1:hS3pXvaG8KgWTSz+dAdyzPrGUYmi2Q+WFX8g2hqVEZU= +cloud.google.com/go/storage v1.50.0/go.mod h1:l7XeiD//vx5lfqE3RavfmU9yvk5Pp0Zhcv482poyafY= +codeberg.org/go-fonts/liberation v0.5.0/go.mod h1:zS/2e1354/mJ4pGzIIaEtm/59VFCFnYC7YV6YdGl5GU= +codeberg.org/go-latex/latex v0.1.0/go.mod h1:LA0q/AyWIYrqVd+A9Upkgsb+IqPcmSTKc9Dny04MHMw= +codeberg.org/go-pdf/fpdf v0.10.0/go.mod h1:Y0DGRAdZ0OmnZPvjbMp/1bYxmIPxm0ws4tfoPOc4LjU= +cyphar.com/go-pathrs v0.2.1/go.mod h1:y8f1EMG7r+hCuFf/rXsKqMJrJAUoADZGNh5/vZPKcGc= +git.sr.ht/~sbinet/gg v0.6.0/go.mod h1:uucygbfC9wVPQIfrmwM2et0imr8L7KQWywX0xpFMm94= +github.com/Azure/azure-sdk-for-go/sdk/azcore v1.21.0/go.mod h1:t76Ruy8AHvUAC8GfMWJMa0ElSbuIcO03NLpynfbgsPA= +github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.13.1/go.mod h1:IYus9qsFobWIc2YVwe/WPjcnyCkPKtnHAqUYeebc8z0= +github.com/Azure/azure-sdk-for-go/sdk/internal v1.11.2/go.mod h1:XtLgD3ZD34DAaVIIAyG3objl5DynM3CQ/vMcbBNJZGI= +github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/dns/armdns v1.2.0/go.mod h1:fSvRkb8d26z9dbL40Uf/OO6Vo9iExtZK3D0ulRV+8M0= +github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/privatedns/armprivatedns v1.3.0/go.mod h1:GE4m0rnnfwLGX0Y9A9A25Zx5N/90jneT5ABevqzhuFQ= +github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.6.0/go.mod h1:cTvi54pg19DoT07ekoeMgE/taAwNtCShVeZqA+Iv2xI= +github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E= +github.com/Azure/go-ntlmssp v0.0.0-20221128193559-754e69321358/go.mod h1:chxPXzSsl7ZWRAuOIE23GDNzjWuZquvFlgA8xmpunjU= +github.com/AzureAD/microsoft-authentication-library-for-go v1.6.0/go.mod h1:HKpQxkWaGLJ+D/5H8QRpyQXA1eKjxkFlOMwck5+33Jk= github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.30.0/go.mod h1:P4WPRUkOhJC13W//jWpyfJNDAIpvRbAUIYLX/4jtlE0= +github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.31.0/go.mod h1:P4WPRUkOhJC13W//jWpyfJNDAIpvRbAUIYLX/4jtlE0= +github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/metric v0.48.1/go.mod h1:jyqM3eLpJ3IbIFDTKVz2rF9T/xWGW0rIriGwnz8l9Tk= +github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/resourcemapping v0.48.1/go.mod h1:viRWSEhtMZqz1rhwmOVKkWl6SwmVowfL9O2YR5gI2PE= github.com/JeffAshton/win_pdh v0.0.0-20161109143554-76bb4ee9f0ab/go.mod h1:3VYc5hodBMJ5+l/7J4xAyMeuM2PNuepvHlGs8yilUCA= +github.com/Khan/genqlient v0.8.1/go.mod h1:R2G6DzjBvCbhjsEajfRjbWdVglSH/73kSivC9TLWVjU= +github.com/Masterminds/vcs v1.13.3/go.mod h1:TiE7xuEjl1N4j016moRd6vezp6e6Lz23gypeXfzXeW8= github.com/Microsoft/hnslib v0.1.1/go.mod h1:DRQR4IjLae6WHYVhW7uqe44hmFUiNhmaWA+jwMbz5tM= github.com/NYTimes/gziphandler v1.1.1/go.mod h1:n/CVRwUEOgIxrgPvAQhUUr9oeUtvrhMomdKFjzJNB0c= github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE= +github.com/Venafi/vcert/v5 v5.12.3/go.mod h1:9ahHk4P0YeWfuacnf0jxSPy9qujonwFlfh2aMtOfdwc= +github.com/ajstarks/svgo v0.0.0-20211024235047-1546f124cd8b/go.mod h1:1KcenG0jGWcpt8ov532z81sp/kMMUG485J2InIOyADM= +github.com/akamai/AkamaiOPEN-edgegrid-golang/v13 v13.0.0/go.mod h1:lnGMNS5JOiZWnZT5nv+dG8fC92X5U98DiIIPNpwlQQY= github.com/alecthomas/kingpin/v2 v2.4.0/go.mod h1:0gyi0zQnjuFk8xrkNKamJoyUo382HRL7ATRpFZCw6tE= +github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= +github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= +github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= +github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= +github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho= github.com/alecthomas/units v0.0.0-20240927000941-0f3dac36c52b/go.mod h1:fvzegU4vN3H1qMT+8wDmzjAcDONcgo2/SZ/TyfdUOFs= +github.com/alicebob/miniredis/v2 v2.35.0/go.mod h1:TcL7YfarKPGDAthEtl5NBeHZfeUQj6OXMm/+iu5cLMM= github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= github.com/antlr/antlr4/runtime/Go/antlr v1.4.10/go.mod h1:F7bn7fEU90QkQ3tnmaTx3LTKLEDqnwWODIYppRQ5hnY= +github.com/antlr/antlr4/runtime/Go/antlr/v4 v4.0.0-20230305170008-8188dc5388df/go.mod h1:pSwJ0fSY5KhvocuWSx4fz3BA8OrA1bQn+K1Eli3BRwM= +github.com/antlr4-go/antlr/v4 v4.13.0/go.mod h1:pfChB/xh/Unjila75QW7+VU4TSnWnnk9UTnmpPaOR2g= github.com/armon/circbuf v0.0.0-20190214190532-5111143e8da2/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o= +github.com/armon/go-radix v1.0.0/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= +github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs= github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY= github.com/aws/aws-lambda-go v1.41.0/go.mod h1:jwFe2KmMsHmffA1X2R09hH6lFzJQxzI8qK17ewzbQMM= +github.com/aws/aws-sdk-go v1.55.5/go.mod h1:eRwEWoyTWFMVYVQzKMNHWP5/RV4xIUGMQfXQHfHkpNU= +github.com/aws/aws-sdk-go-v2 v1.41.2 h1:LuT2rzqNQsauaGkPK/7813XxcZ3o3yePY0Iy891T2ls= +github.com/aws/aws-sdk-go-v2 v1.41.2/go.mod h1:IvvlAZQXvTXznUPfRVfryiG1fbzE2NGK6m9u39YQ+S4= +github.com/aws/aws-sdk-go-v2/config v1.32.10 h1:9DMthfO6XWZYLfzZglAgW5Fyou2nRI5CuV44sTedKBI= +github.com/aws/aws-sdk-go-v2/config v1.32.10/go.mod h1:2rUIOnA2JaiqYmSKYmRJlcMWy6qTj1vuRFscppSBMcw= +github.com/aws/aws-sdk-go-v2/credentials v1.19.10 h1:EEhmEUFCE1Yhl7vDhNOI5OCL/iKMdkkYFTRpZXNw7m8= +github.com/aws/aws-sdk-go-v2/credentials v1.19.10/go.mod h1:RnnlFCAlxQCkN2Q379B67USkBMu1PipEEiibzYN5UTE= +github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.18 h1:Ii4s+Sq3yDfaMLpjrJsqD6SmG/Wq/P5L/hw2qa78UAY= +github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.18/go.mod h1:6x81qnY++ovptLE6nWQeWrpXxbnlIex+4H4eYYGcqfc= +github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.18 h1:F43zk1vemYIqPAwhjTjYIz0irU2EY7sOb/F5eJ3HuyM= +github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.18/go.mod h1:w1jdlZXrGKaJcNoL+Nnrj+k5wlpGXqnNrKoP22HvAug= +github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.18 h1:xCeWVjj0ki0l3nruoyP2slHsGArMxeiiaoPN5QZH6YQ= +github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.18/go.mod h1:r/eLGuGCBw6l36ZRWiw6PaZwPXb6YOj+i/7MizNl5/k= +github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.5 h1:CeY9LUdur+Dxoeldqoun6y4WtJ3RQtzk0JMP2gfUay0= +github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.5/go.mod h1:AZLZf2fMaahW5s/wMRciu1sYbdsikT/UHwbUjOdEVTc= +github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.18 h1:LTRCYFlnnKFlKsyIQxKhJuDuA3ZkrDQMRYm6rXiHlLY= +github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.18/go.mod h1:XhwkgGG6bHSd00nO/mexWTcTjgd6PjuvWQMqSn2UaEk= +github.com/aws/aws-sdk-go-v2/service/route53 v1.62.2/go.mod h1:Ll1DCasPTBFtHK5t/U5WIwGIyRuY3xY+x8/LmqIlqpM= +github.com/aws/aws-sdk-go-v2/service/signin v1.0.6 h1:MzORe+J94I+hYu2a6XmV5yC9huoTv8NRcCrUNedDypQ= +github.com/aws/aws-sdk-go-v2/service/signin v1.0.6/go.mod h1:hXzcHLARD7GeWnifd8j9RWqtfIgxj4/cAtIVIK7hg8g= +github.com/aws/aws-sdk-go-v2/service/sso v1.30.11 h1:7oGD8KPfBOJGXiCoRKrrrQkbvCp8N++u36hrLMPey6o= +github.com/aws/aws-sdk-go-v2/service/sso v1.30.11/go.mod h1:0DO9B5EUJQlIDif+XJRWCljZRKsAFKh3gpFz7UnDtOo= +github.com/aws/aws-sdk-go-v2/service/ssooidc v1.35.15 h1:edCcNp9eGIUDUCrzoCu1jWAXLGFIizeqkdkKgRlJwWc= +github.com/aws/aws-sdk-go-v2/service/ssooidc v1.35.15/go.mod h1:lyRQKED9xWfgkYC/wmmYfv7iVIM68Z5OQ88ZdcV1QbU= +github.com/aws/aws-sdk-go-v2/service/sts v1.41.7 h1:NITQpgo9A5NrDZ57uOWj+abvXSb83BbyggcUBVksN7c= +github.com/aws/aws-sdk-go-v2/service/sts v1.41.7/go.mod h1:sks5UWBhEuWYDPdwlnRFn1w7xWdH29Jcpe+/PJQefEs= +github.com/aws/smithy-go v1.24.1 h1:VbyeNfmYkWoxMVpGUAbQumkODcYmfMRfZ8yQiH30SK0= +github.com/aws/smithy-go v1.24.1/go.mod h1:LEj2LM3rBRQJxPZTB4KuzZkaZYnZPnvgIhb4pu07mx0= +github.com/aymanbagabas/go-osc52/v2 v2.0.1/go.mod h1:uYgXzlJ7ZpABp8OJ+exZzJJhRNQ2ASbcXHWsFqH8hp8= +github.com/benbjohnson/clock v1.3.5/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= +github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= +github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= +github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= github.com/blang/semver v3.5.1+incompatible h1:cQNTCjp13qL8KC3Nbxr/y2Bqb63oX6wdnnjpJbkM4JQ= github.com/blang/semver v3.5.1+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk= -github.com/chai2010/gettext-go v1.0.2/go.mod h1:y+wnP2cHYaVj19NZhYKAwEMH2CI1gNHeQQ+5AjwawxA= +github.com/bsm/ginkgo/v2 v2.7.0/go.mod h1:AiKlXPm7ItEHNc/2+OkrNG4E0ITzojb9/xWzvQ9XZ9w= +github.com/bsm/ginkgo/v2 v2.12.0/go.mod h1:SwYbGRRDovPVboqFv0tPTcG1sN61LM1Z4ARdbAV9g4c= +github.com/bsm/gomega v1.26.0/go.mod h1:JyEr/xRbxbtgWNi8tIEVPUYZ5Dzef52k01W3YH0H+O0= +github.com/bsm/gomega v1.27.10/go.mod h1:JyEr/xRbxbtgWNi8tIEVPUYZ5Dzef52k01W3YH0H+O0= +github.com/bufbuild/protovalidate-go v0.9.1/go.mod h1:5jptBxfvlY51RhX32zR6875JfPBRXUsQjyZjm/NqkLQ= +github.com/bwesterb/go-ristretto v1.2.3/go.mod h1:fUIoIZaG73pV5biE2Blr2xEzDoMj7NFEuV9ekS419A0= +github.com/campoy/embedmd v1.0.0/go.mod h1:oxyr9RCiSXg0M3VJ3ks0UGfp98BpSSGr0kpiX3MzVl8= +github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= +github.com/census-instrumentation/opencensus-proto v0.4.1/go.mod h1:4T9NM4+4Vw91VeyqjLS6ao50K5bOcLKN6Q42XnYaRYw= +github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/charmbracelet/colorprofile v0.3.1/go.mod h1:/GkGusxNs8VB/RSOh3fu0TJmQ4ICMMPApIIVn0KszZ0= +github.com/charmbracelet/lipgloss v1.1.0/go.mod h1:/6Q8FR2o+kj8rz4Dq0zQc3vYf7X+B0binUUBwA0aL30= +github.com/charmbracelet/x/ansi v0.9.2/go.mod h1:3RQDQ6lDnROptfpWuUVIUG64bD2g2BgntdxH0Ya5TeE= +github.com/charmbracelet/x/cellbuf v0.0.13/go.mod h1:xe0nKWGd3eJgtqZRaN9RjMtK7xUYchjzPr7q6kcvCCs= +github.com/charmbracelet/x/term v0.2.1/go.mod h1:oQ4enTYFV7QN4m0i9mzHrViD7TQKvNEEkHUMCmsxdUg= +github.com/chzyer/logex v1.2.1/go.mod h1:JLbx6lG2kDbNRFnfkgvh4eRJRPX1QCoOIWomwysCBrQ= github.com/chzyer/readline v1.5.1/go.mod h1:Eh+b79XXUwfKfcPLepksvw2tcLE/Ct21YObkaSkeBlk= +github.com/chzyer/test v1.0.0/go.mod h1:2JlltgoNkt4TW/z9V/IzDdFaMTM2JPIi26O1pF38GC8= +github.com/clipperhouse/uax29/v2 v2.2.0/go.mod h1:EFJ2TJMRUaplDxHKj1qAEhCtQPW2tJSwu5BF98AuoVM= +github.com/cloudflare/circl v1.6.2/go.mod h1:2eXP6Qfat4O/Yhh8BznvKnJ+uzEoTQ6jVKJRn81BiS4= +github.com/cncf/udpa/go v0.0.0-20220112060539-c52dc94e7fbe/go.mod h1:6pvJx4me5XPnfI9Z40ddWsdw2W/uZgQLFXToKeRcDiI= github.com/cncf/xds/go v0.0.0-20251210132809-ee656c7534f5/go.mod h1:KdCmV+x/BuvyMxRnYBlmVaq4OLiKW6iRQfvC62cvdkI= +github.com/cockroachdb/datadriven v1.0.2/go.mod h1:a9RdTaap04u637JoCzcUoIcDmvwSUtcUFtT/C3kJlTU= github.com/container-storage-interface/spec v1.9.0/go.mod h1:ZfDu+3ZRyeVqxZM0Ds19MVLkN2d1XJ5MAfi1L3VjlT0= github.com/containerd/containerd/api v1.8.0/go.mod h1:dFv4lt6S20wTu/hMcP4350RL87qPWLVa/OHOwmmdnYc= github.com/containerd/ttrpc v1.2.6/go.mod h1:YCXHsb32f+Sq5/72xHubdiJRQY9inL4a4ZQrAbN1q9o= @@ -26,118 +127,577 @@ github.com/containerd/typeurl/v2 v2.2.2/go.mod h1:95ljDnPfD3bAbDJRugOiShd/DlAAsx github.com/coredns/caddy v1.1.1/go.mod h1:A6ntJQlAWuQfFlsd9hvigKbo2WS0VUs2l1e2F+BawD4= github.com/coredns/corefile-migration v1.0.26/go.mod h1:56DPqONc3njpVPsdilEnfijCwNGC3/kTJLl7i7SPavY= github.com/coreos/go-oidc v2.3.0+incompatible/go.mod h1:CgnwVTmzoESiwO9qyAFEMiHoZ1nMCKZlZ9V6mm3/LKc= +github.com/coreos/go-oidc v2.5.0+incompatible/go.mod h1:CgnwVTmzoESiwO9qyAFEMiHoZ1nMCKZlZ9V6mm3/LKc= +github.com/coreos/go-semver v0.3.1/go.mod h1:irMmmIw/7yzSRPWryHsK7EYSg09caPQL03VsM8rvUec= github.com/cpuguy83/go-md2man/v2 v2.0.7/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g= +github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/cyphar/filepath-securejoin v0.4.1/go.mod h1:Sdj7gXlvMcPZsbhwhQ33GguGLDGQL7h7bg04C/+u9jI= github.com/danieljoos/wincred v1.2.3/go.mod h1:6qqX0WNrS4RzPZ1tnroDzq9kY3fu1KwE7MRLQK4X0bs= +github.com/denisenkom/go-mssqldb v0.9.0/go.mod h1:xbL0rPBG9cCiLr28tMa8zpbdarY27NDyej4t/EjAShU= +github.com/digitalocean/godo v1.176.0/go.mod h1:xQsWpVCCbkDrWisHA72hPzPlnC+4W5w/McZY5ij9uvU= github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto= github.com/emicklei/go-restful v2.16.0+incompatible h1:rgqiKNjTnFQA6kkhFe16D8epTksy9HQ1MyrbDXSdYhM= github.com/emicklei/go-restful v2.16.0+incompatible/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs= +github.com/emicklei/go-restful/v3 v3.11.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= +github.com/emicklei/go-restful/v3 v3.12.2/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= github.com/envoyproxy/go-control-plane v0.14.0/go.mod h1:NcS5X47pLl/hfqxU70yPwL9ZMkUlwlKxtAohpi2wBEU= github.com/envoyproxy/go-control-plane/envoy v1.36.0/go.mod h1:ty89S1YCCVruQAm9OtKeEkQLTb+Lkz0k8v9W0Oxsv98= github.com/envoyproxy/go-control-plane/ratelimit v0.1.0/go.mod h1:Wk+tMFAFbCXaJPzVVHnPgRKdUdwW/KdbRt94AzgRee4= github.com/envoyproxy/protoc-gen-validate v1.3.0/go.mod h1:HvYl7zwPa5mffgyeTUHA9zHIH36nmrm7oCbo4YKoSWA= github.com/euank/go-kmsg-parser v2.0.0+incompatible/go.mod h1:MhmAMZ8V4CYH4ybgdRwPr2TU5ThnS43puaKEMpja1uw= -github.com/exponent-io/jsonpath v0.0.0-20210407135951-1de76d718b3f/go.mod h1:OSYXu++VVOHnXeitef/D8n/6y4QV8uLHSFXX4NeXMGc= +github.com/evanphx/json-patch v0.5.2/go.mod h1:ZWS5hhDbVDyob71nXKNL0+PWn6ToqBHMikGIFbs31qQ= github.com/fatih/camelcase v1.0.0/go.mod h1:yN2Sb0lFhZJUdVvtELVWefmrXpuZESvPmqwoZc+/fpc= github.com/form3tech-oss/jwt-go v3.2.3+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k= +github.com/go-asn1-ber/asn1-ber v1.5.8-0.20250403174932-29230038a667/go.mod h1:hEBeB/ic+5LoWskz+yKT7vGhhPYkProFKoKdwZRWMe0= github.com/go-errors/errors v1.4.2/go.mod h1:sIVyrIiJhuEF+Pj9Ebtd6P/rEYROXFi3BopGUQ5a5Og= +github.com/go-http-utils/headers v0.0.0-20181008091004-fed159eddc2a/go.mod h1:I79BieaU4fxrw4LMXby6q5OS9XnoR9UIKLOzDFjUmuw= github.com/go-jose/go-jose/v4 v4.1.3/go.mod h1:x4oUasVrzR7071A4TnHLGSPpNOm2a21K9Kf04k1rs08= +github.com/go-jose/go-jose/v4 v4.1.4/go.mod h1:x4oUasVrzR7071A4TnHLGSPpNOm2a21K9Kf04k1rs08= +github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= +github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= +github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY= +github.com/go-ldap/ldap/v3 v3.4.12/go.mod h1:+SPAGcTtOfmGsCb3h1RFiq4xpp4N636G75OEace8lNo= +github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= +github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= +github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= +github.com/go-logfmt/logfmt v0.6.0/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs= +github.com/go-logr/logr v0.1.0/go.mod h1:ixOQHD9gLJUVQQ2ZOR7zLEifBX6tGkNJF4QyIY7sIas= +github.com/go-logr/logr v0.2.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTgseGU= +github.com/go-logr/logr v1.2.0/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/logr v1.4.1/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= +github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= +github.com/go-openapi/jsonpointer v0.19.6/go.mod h1:osyAmYz/mB/C3I+WsTTSgw1ONzaLJoLCyoi6/zppojs= +github.com/go-openapi/jsonpointer v0.21.0/go.mod h1:IUyH9l/+uyhIYQ/PXVA41Rexl+kOkAPDdXEYns6fzUY= +github.com/go-openapi/jsonpointer v0.21.1/go.mod h1:50I1STOfbY1ycR8jGz8DaMeLCdXiI6aDteEdRNNzpdk= +github.com/go-openapi/jsonreference v0.20.1/go.mod h1:Bl1zwGIM8/wsvqjsOQLJ/SH+En5Ap4rVB5KVcIDZG2k= +github.com/go-openapi/jsonreference v0.20.2/go.mod h1:Bl1zwGIM8/wsvqjsOQLJ/SH+En5Ap4rVB5KVcIDZG2k= +github.com/go-openapi/jsonreference v0.21.0/go.mod h1:LmZmgsrTkVg9LG4EaHeY8cBDslNPMo06cago5JNLkm4= +github.com/go-openapi/swag v0.22.3/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14= +github.com/go-openapi/swag v0.23.0/go.mod h1:esZ8ITTYEsH1V2trKHjAN8Ai7xHb8RV+YSZ577vPjgQ= +github.com/go-ozzo/ozzo-validation/v4 v4.3.0/go.mod h1:2NKgrcHl3z6cJs+3Oo940FPRiTzuqKbvfrL2RxCj6Ew= +github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= github.com/gobuffalo/flect v0.2.3/go.mod h1:vmkQwuZYhN5Pc4ljYQZzP+1sq+NEkK+lh20jmEmX3jc= +github.com/goccmack/gocc v0.0.0-20230228185258-2292f9e40198/go.mod h1:DTh/Y2+NbnOVVoypCCQrovMPDKUGp4yZpSbWg5D0XIM= +github.com/goccmack/gocc v1.0.2/go.mod h1:LXX2tFVUggS/Zgx/ICPOr3MLyusuM7EcbfkPvNsjdO8= +github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/godbus/dbus/v5 v5.1.0/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= +github.com/godror/godror v0.40.4/go.mod h1:i8YtVTHUJKfFT3wTat4A9UoqScUtZXiYB9Rf3SVARgc= +github.com/godror/knownpb v0.1.1/go.mod h1:4nRFbQo1dDuwKnblRXDxrfCFYeT4hjg3GjMqef58eRE= +github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= github.com/golang-jwt/jwt/v5 v5.2.2/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk= +github.com/golang-jwt/jwt/v5 v5.3.0/go.mod h1:fxCRLWMO43lRc8nhHWY6LGqRcf+1gQWArsqaEUEa5bE= +github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0= +github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGwJL78qG/PmXZO1EjYhfJinVAhrmmHX6Z8B9k= github.com/golang/glog v1.2.5/go.mod h1:6AhwSGph0fcJtXVM/PEHPqZlFeoLxhs7/t5UDAwmO+w= github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= +github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= +github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= +github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= +github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= +github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= +github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= +github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= +github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/google/cadvisor v0.52.1/go.mod h1:OAhPcx1nOm5YwMh/JhpUOMKyv1YKLRtS9KgzWPndHmA= +github.com/google/certificate-transparency-go v1.3.1/go.mod h1:gg+UQlx6caKEDQ9EElFOujyxEQEfOiQzAt6782Bvi8k= github.com/google/gnostic v0.5.7-v3refs/go.mod h1:73MKFl6jIHelAJNaBGFzt3SPtZULs9dYrGFt8OiIsHQ= -github.com/gregjones/httpcache v0.0.0-20190611155906-901d90724c79/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA= +github.com/google/gnostic-models v0.6.9/go.mod h1:CiWsm0s6BSQd1hRn8/QmxqB6BesYcbSZxsz9b0KuDBw= +github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/pprof v0.0.0-20240727154555-813a5fbdbec8/go.mod h1:K1liHPHnj73Fdn/EKuT8nrFqBihUSKXoLYU0BuatOYo= +github.com/google/pprof v0.0.0-20250403155104-27863c87afa6/go.mod h1:boTsfXsheKC2y+lKOCMpSfarhxDeIzfZG1jqGcPl3cA= +github.com/google/s2a-go v0.1.9/go.mod h1:YA0Ei2ZQL3acow2O62kdp9UlnvMmU7kA6Eutn0dXayM= +github.com/googleapis/enterprise-certificate-proxy v0.3.12/go.mod h1:vqVt9yG9480NtzREnTlmGSBmFrA+bzb0yl0TxoBQXOg= +github.com/googleapis/gax-go/v2 v2.17.0/go.mod h1:mzaqghpQp4JDh3HvADwrat+6M3MOIDp5YKHhb9PAgDY= +github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= +github.com/grpc-ecosystem/go-grpc-middleware v1.3.0/go.mod h1:z0ButlSOZa5vEBq9m2m2hlwIgKw+rp3sdCBRoJY+30Y= github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus v1.0.1/go.mod h1:lXGCsh6c22WGtjr+qGHj1otzZpV/1kwTMAqkwZsnWRU= +github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus v1.1.0/go.mod h1:hM2alZsMUni80N33RBe6J0e423LB+odMj7d3EMP9l20= github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.3.0/go.mod h1:qOchhhIlmRcqk/O9uCo/puJlyo07YINaIqdZfZG3Jkc= +github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.3.3/go.mod h1:NbCUVmiS4foBGBHOYlCT25+YmGpJ32dZPi75pGEUpj4= +github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.3/go.mod h1:ndYquD05frm2vACXE1nsccT4oJzjhw2arTS2cpUD1PI= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.2/go.mod h1:pkJQ2tZHJ0aFOVEEot6oZmaVEZcRme73eIFmhiVuRWs= +github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= +github.com/hashicorp/go-cleanhttp v0.5.2/go.mod h1:kO/YDlP8L1346E6Sodw+PrpBSV4/SoxCXGY6BqNFT48= +github.com/hashicorp/go-hmac-drbg v0.0.0-20210916214228-a6e5a68489f6/go.mod h1:y+HSOcOGB48PkUxNyLAiCiY6rEENu+E+Ss4LG8QHwf4= +github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM= +github.com/hashicorp/go-retryablehttp v0.7.8/go.mod h1:rjiScheydd+CxvumBsIrFKlx3iS0jrZ7LvzFGFmuKbw= +github.com/hashicorp/go-rootcerts v1.0.2/go.mod h1:pqUvnprVnM5bf7AOirdbb01K4ccR319Vf4pU3K5EGc8= +github.com/hashicorp/go-secure-stdlib/cryptoutil v0.1.1/go.mod h1:hH8rgXHh9fPSDPerG6WzABHsHF+9ZpLhRI1LPk4JZ8c= +github.com/hashicorp/go-secure-stdlib/parseutil v0.2.0/go.mod h1:Ll013mhdmsVDuoIXVfBtvgGJsXDYkTw1kooNcoCXuE0= +github.com/hashicorp/go-secure-stdlib/strutil v0.1.2/go.mod h1:Gou2R9+il93BqX25LAKCLuM+y9U2T4hlwvT1yprcna4= +github.com/hashicorp/go-sockaddr v1.0.7/go.mod h1:FZQbEYa1pxkQ7WLpyXJ6cbjpT8q0YgQaK/JakXqGyWw= github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= +github.com/hashicorp/hcl v1.0.1-vault-7/go.mod h1:XYhtn6ijBSAj6n4YqAaf7RBPS4I06AItNorpy+MoQNM= +github.com/hashicorp/vault/api v1.22.0/go.mod h1:IUZA2cDvr4Ok3+NtK2Oq/r+lJeXkeCrHRmqdyWfpmGM= +github.com/hashicorp/vault/sdk v0.23.0/go.mod h1:BkJpVju7qe2cDe+T8gA84uFtRnNYQIPXkiJqqWGUYrc= +github.com/iancoleman/strcase v0.3.0/go.mod h1:iwCmte+B7n89clKwxIoIXy/HfoL7AsD47ZCWhYzw7ho= github.com/ianlancetaylor/demangle v0.0.0-20240312041847-bd984b5ce465/go.mod h1:gx7rwoVhcfuVKG5uya9Hs3Sxj7EIvldVofAWIUtGouw= github.com/ishidawataru/sctp v0.0.0-20250521072954-ae8eb7fa7995/go.mod h1:co9pwDoBCm1kGxawmb4sPq0cSIOOWNPT4KnHotMP1Zg= +github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= github.com/jessevdk/go-flags v1.6.1/go.mod h1:Mk8T1hIAWpOiJiHa9rJASDK2UGWji0EuPGBnNLMooyc= +github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo= github.com/jonboulle/clockwork v0.5.0/go.mod h1:3mZlmanh0g2NDKO5TWZVJAfofYk64M7XN3SzBPjZF60= -github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4= +github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= +github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= github.com/k14s/semver/v4 v4.0.1-0.20210701191048-266d47ac6115/go.mod h1:mGrnmO5qnhJIaSiwMo05cvRL6Ww9ccYbTgNFcm6RHZQ= github.com/karrick/godirwalk v1.17.0/go.mod h1:j4mkqPuvaLI8mp1DroR3P6ad7cyYd4c1qeJ3RV7ULlk= github.com/keybase/go-keychain v0.0.1/go.mod h1:PdEILRW3i9D8JcdM+FmY6RwkHGnhHxXwkPPMeUgOK1k= github.com/kisielk/errcheck v1.8.0/go.mod h1:1kLL+jV4e+CFfueBmI1dSK2ADDyQnlrnrY/FqKluHJQ= +github.com/kisielk/sqlstruct v0.0.0-20201105191214-5f3e10d3ab46/go.mod h1:yyMNCyc/Ib3bDTKd379tNMpB/7/H5TjM2Y9QJ5THLbE= +github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= +github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= +github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/libopenstorage/openstorage v1.0.0/go.mod h1:Sp1sIObHjat1BeXhfMqLZ14wnOzEhNx2YQedreMcUyc= github.com/lithammer/dedent v1.1.0/go.mod h1:jrXYCQtgg0nJiN+StA2KgR7w6CiQNv9Fd/Z9BP0jIOc= +github.com/lucasb-eyer/go-colorful v1.2.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0= +github.com/lyft/protoc-gen-star/v2 v2.0.4-0.20230330145011-496ad1ac90a4/go.mod h1:amey7yeodaJhXSbf/TlLvWiqQfLOSpEk//mLlc+axEk= github.com/magefile/mage v1.14.0/go.mod h1:z5UZb/iS3GoOSn0JgWuiw7dxlurVYTu+/jHXqQg881A= github.com/magiconair/properties v1.8.5/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60= github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= +github.com/mailru/easyjson v0.9.0/go.mod h1:1+xMtQp2MRNVL/V1bOzuP3aP8VNwRW55fQUto+XFtTU= +github.com/mattn/go-oci8 v0.1.1/go.mod h1:wjDx6Xm9q7dFtHJvIlrI99JytznLw5wQ4R+9mNXJwGI= +github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= github.com/matttproud/golang_protobuf_extensions v1.0.4/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= github.com/maxbrunsfeld/counterfeiter/v6 v6.11.2/go.mod h1:VzB2VoMh1Y32/QqDfg9ZJYHj99oM4LiGtqPZydTiQSQ= github.com/mistifyio/go-zfs v2.1.2-0.20190413222219-f784269be439+incompatible/go.mod h1:8AuVvqP/mXw1px98n46wfvcGfQ4ci2FwoAjKYxuo3Z4= +github.com/mitchellh/cli v1.1.5/go.mod h1:v8+iFts2sPIKUV1ltktPXMCC8fumSKFItNcD2cLtRR4= github.com/moby/ipvs v1.1.0/go.mod h1:4VJMWuf098bsUMmZEiD4Tjk/O7mOn3l1PTD3s4OoYAs= +github.com/moby/spdystream v0.5.0/go.mod h1:xBAYlnt/ay+11ShkdFKNAG7LsyK/tmNBVvVOwrfMgdI= +github.com/moby/spdystream v0.5.1/go.mod h1:xBAYlnt/ay+11ShkdFKNAG7LsyK/tmNBVvVOwrfMgdI= github.com/moby/sys/mountinfo v0.7.2/go.mod h1:1YOa8w8Ih7uW0wALDUgT1dTTSBrZ+HiBLGws92L2RU4= github.com/moby/sys/userns v0.1.0/go.mod h1:IHUYgu/kao6N8YZlp9Cf444ySSvCmDlmzUcYfDHOl28= +github.com/moby/term v0.5.0/go.mod h1:8FzsFHVUBGZdbDsJw/ot+X+d5HLUbvklYLJ9uGfcI3Y= +github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= +github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826/go.mod h1:TaXosZuwdSHYgviHp1DAtfrULt5eUgsSMsZf+YrPgl8= -github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00/go.mod h1:Pm3mSP3c5uWn86xMLZ5Sa7JB9GsEZySvHYXCTK4E9q4= github.com/mrunalp/fileutils v0.5.1/go.mod h1:M1WthSahJixYnrXQl/DFQuteStB1weuxD2QJNHXfbSQ= +github.com/muesli/termenv v0.16.0/go.mod h1:ZRfOIKPFDYQoDFF4Olj7/QJbW60Ol/kL1pU3VfY/Cnk= +github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= +github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw= +github.com/nelsam/hel/v2 v2.3.3/go.mod h1:1ZTGfU2PFTOd5mx22i5O0Lc2GY933lQ2wb/ggy+rL3w= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= +github.com/nrdcg/goacmedns v0.2.0/go.mod h1:T5o6+xvSLrQpugmwHvrSNkzWht0UGAwj2ACBMhh73Cg= +github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY= +github.com/onsi/ginkgo/v2 v2.19.0/go.mod h1:rlwLi9PilAFJ8jCg9UE1QP6VBpd6/xj3SRC0d6TU0To= +github.com/onsi/ginkgo/v2 v2.25.1/go.mod h1:ppTWQ1dh9KM/F1XgpeRqelR+zHVwV81DGRSDnFxK7Sk= +github.com/onsi/ginkgo/v2 v2.27.2/go.mod h1:ArE1D/XhNXBXCBkKOLkbsb2c81dQHCRcF5zwn/ykDRo= +github.com/onsi/ginkgo/v2 v2.27.4/go.mod h1:ArE1D/XhNXBXCBkKOLkbsb2c81dQHCRcF5zwn/ykDRo= +github.com/onsi/ginkgo/v2 v2.28.0/go.mod h1:ArE1D/XhNXBXCBkKOLkbsb2c81dQHCRcF5zwn/ykDRo= +github.com/onsi/gomega v1.33.1/go.mod h1:U4R44UsT+9eLIaYRB2a5qajjtQYn0hauxvRm16AVYg0= +github.com/onsi/gomega v1.38.2/go.mod h1:W2MJcYxRGV63b418Ai34Ud0hEdTVXq9NW9+Sx6uXf3k= +github.com/onsi/gomega v1.39.0/go.mod h1:ZCU1pkQcXDO5Sl9/VVEGlDyp+zm0m1cmeG5TOzLgdh4= github.com/opencontainers/cgroups v0.0.1/go.mod h1:s8lktyhlGUqM7OSRL5P7eAW6Wb+kWPNvt4qvVfzA5vs= github.com/opencontainers/runtime-spec v1.2.0/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= github.com/opencontainers/selinux v1.11.1/go.mod h1:E5dMC3VPuVvVHDYmi78qvhJp8+M586T4DlDRYpFkyec= +github.com/openshift/build-machinery-go v0.0.0-20230824093055-6a18da01283c/go.mod h1:b1BuldmJlbA/xYtdZvKi+7j5YGB44qJUJDZ9zwiNCfE= github.com/openshift/build-machinery-go v0.0.0-20240613134303-8359781da660/go.mod h1:8jcm8UPtg2mCAsxfqKil1xrmRMI3a+XU2TZ9fF8A7TE= +github.com/openshift/generic-admission-server v1.14.1-0.20231020105858-8dcc3c9b298f/go.mod h1:/CLsleDcQ6AFTGKJe9VL3Y4rB9DqX3fQwQv47q2/ZJc= github.com/openshift/generic-admission-server v1.14.1-0.20240926143655-a882ebf9df19/go.mod h1:eNpBvr/3zce6zLOeCtBw48xbCp8SLAmQqu/rb7vFE9Y= -github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU= +github.com/pavlo-v-chernykh/keystore-go/v4 v4.5.0/go.mod h1:lAVhWwbNaveeJmxrxuSTxMgKpF6DjnuVpn6T8WiBwYQ= +github.com/pierrec/lz4 v2.6.1+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY= +github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c/go.mod h1:7rwL4CYBLnjLxUqIJNnCWiEdr3bn6IUYi15bNlnbCCU= +github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= +github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/planetscale/vtprotobuf v0.6.1-0.20240319094008-0393e58bdf10/go.mod h1:t/avpk3KcrXxUnYOhZhMXJlSEyie6gQbtLq5NM3loB8= +github.com/posener/complete v1.2.3/go.mod h1:WZIdtGGp+qx0sLrYKtIRAruyNpv6hFCicSgv7Sy7s/s= github.com/pquerna/cachecontrol v0.1.0/go.mod h1:NrUG3Z7Rdu85UNR3vm7SOsl1nFIeSiQnrHV5K9mBcUI= +github.com/prashantv/gostub v1.1.0/go.mod h1:A5zLQHz7ieHGG7is6LLXLz7I8+3LZzsrV0P1IAHhP5U= +github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= +github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= +github.com/prometheus/client_golang v1.1.0/go.mod h1:I1FGZT9+L76gKKOs5djB6ezCbFQP1xR9D75/vuwEF3g= +github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M= +github.com/prometheus/client_golang v1.11.1/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0= +github.com/prometheus/client_golang v1.20.4/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE= +github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= +github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= +github.com/prometheus/common v0.6.0/go.mod h1:eBmuwkDJBwy6iBfxCBob6t6dR6ENT/y+J+Zk0j9GMYc= +github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo= +github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9VFqTh1DIvc= +github.com/prometheus/common v0.66.1/go.mod h1:gcaUsgf3KfRSwHY4dIMXLPV0K/Wg1oZ8+SbZk/HH/dA= +github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= +github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= +github.com/prometheus/procfs v0.0.3/go.mod h1:4A/X28fw3Fc593LaREMrKMqOKvUAntwMDaekg4FpcdQ= +github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= +github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= +github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk= +github.com/prometheus/procfs v0.16.1/go.mod h1:teAbpZRB1iIAJYREa1LsoWUXykVXA1KlTmWl8x/U+Is= +github.com/redis/go-redis/v9 v9.0.5/go.mod h1:WqMKv5vnQbRuZstUwxQI195wHy+t4PuXDOjzMvcuQHk= github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= github.com/robfig/cron/v3 v3.0.1/go.mod h1:eQICP3HwyT7UooqI/z+Ov+PtYAWygg1TEWWzGIFLtro= github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= +github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= +github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog= +github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4= +github.com/rogpeppe/go-internal v1.13.1/go.mod h1:uMEvuHeurkdAXX61udpOXGD/AzZDWNMNyH2VO9fmH0o= github.com/russross/blackfriday v1.6.0 h1:KqfZb0pUVN2lYqZUYRddxF4OR8ZMURnJIG5Y3VRLtww= github.com/russross/blackfriday v1.6.0/go.mod h1:ti0ldHuxg49ri4ksnFxlkCfN+hvslNlmVHqNRXXJNAY= +github.com/ryanuber/go-glob v1.0.0/go.mod h1:807d1WSdnB0XRJzKNil9Om6lcp/3a0v4qIHxIXzX/Yc= github.com/santhosh-tekuri/jsonschema/v5 v5.3.1/go.mod h1:uToXkOrWAZ6/Oc07xWQrPOhJotwFIyu2bBVN41fcDUY= +github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= +github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= +github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88= +github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= github.com/soheilhy/cmux v0.1.5/go.mod h1:T7TcVDs9LWfQgPlPsdngu6I6QIoyIFZDDC6sNE1GqG0= +github.com/sosodev/duration v1.3.1/go.mod h1:RQIBBX0+fMLc/D9+Jb/fwvVmo0eZvDDEERAikUR6SDg= github.com/spf13/afero v1.6.0/go.mod h1:Ai8FlHk4v/PARR026UzYexafAt9roJ7LcLMAmO6Z93I= +github.com/spf13/afero v1.10.0/go.mod h1:UBogFpq8E9Hx+xc5CNTTEpTnuHVmXDwZcZcE1eb/UhQ= github.com/spf13/cast v1.3.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= +github.com/spf13/cobra v1.9.1/go.mod h1:nDyEzZ8ogv936Cinf6g1RU9MRY64Ir93oCnqb9wxYW0= +github.com/spf13/cobra v1.10.0/go.mod h1:9dhySC7dnTtEiqzmqfkLj47BslqLCUPMXjG2lj/NgoE= github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo= +github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= +github.com/spf13/pflag v1.0.6/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= +github.com/spf13/pflag v1.0.8/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/spf13/viper v1.8.1/go.mod h1:o0Pch8wJ9BVSWGQMbra6iw0oQ5oktSIBaujf1rJH9Ns= github.com/spiffe/go-spiffe/v2 v2.6.0/go.mod h1:gm2SeUoMZEtpnzPNs2Csc0D/gX33k1xIx7lEzqblHEs= +github.com/spyzhov/ajson v0.9.6/go.mod h1:a6oSw0MMb7Z5aD2tPoPO+jq11ETKgXUr2XktHdT8Wt8= +github.com/stoewer/go-strcase v1.2.0/go.mod h1:IBiWB2sKIp3wVVQ3Y035++gc+knqhUQag1KpM8ahLw8= +github.com/stoewer/go-strcase v1.3.0/go.mod h1:fAH5hQ5pehh+j3nZfvwdk2RgEgQjAoM8wodgtPmh1xo= +github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= +github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= +github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw= +github.com/tidwall/gjson v1.14.2/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk= +github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU= github.com/tmc/grpc-websocket-proxy v0.0.0-20220101234140-673ab2c3ae75/go.mod h1:KO6IkyS8Y3j8OdNO85qEYBsRPuteD+YciPomcXdrMnk= github.com/urfave/cli v1.22.16/go.mod h1:EeJR6BKodywf4zciqrdw6hpCPk68JO9z5LazXZMn5Po= +github.com/vektah/gqlparser/v2 v2.5.30/go.mod h1:D1/VCZtV3LPnQrcPBeR/q5jkSQIPti0uYCP/RI0gIeo= github.com/vishvananda/netlink v1.3.1/go.mod h1:ARtKouGSTGchR8aMwmkzC0qiNPrrWO5JS/XMVl45+b4= github.com/vishvananda/netns v0.0.5/go.mod h1:SpkAiCQRtJ6TvvxPnOSyH3BMl6unz3xZlaprSwhNNJM= github.com/xhit/go-str2duration/v2 v2.1.0/go.mod h1:ohY8p+0f07DiV6Em5LKB0s2YpLtXVyJfNt1+BlmyAsU= github.com/xiang90/probing v0.0.0-20221125231312-a49e3df8f510/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= -github.com/xlab/treeprint v1.2.0/go.mod h1:gj5Gd3gPdKtR1ikdDK6fnFLdmIS0X30kTTuNd/WEJu0= +github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e/go.mod h1:RbqR21r5mrJuqunuUZ/Dhy/avygyECGrLceyNeo4LiM= +github.com/youmark/pkcs8 v0.0.0-20240726163527-a2c0da244d78/go.mod h1:aL8wCCfTfSfmXjznFBSZNN13rSJjlIOI1fUNAtF7rmI= +github.com/yuin/gopher-lua v1.1.1/go.mod h1:GBR0iDaNXjAgGg9zfCvksxSRnQx76gclCIb7kdAd1Pw= +github.com/zeebo/errs v1.4.0/go.mod h1:sgbWHsvVuTPHcqJJGQ1WhI5KbWlHYz+2+2C/LSEtCw4= go.etcd.io/bbolt v1.4.2/go.mod h1:Is8rSHO/b4f3XigBC0lL0+4FwAQv3HXEEIgFMuKHceM= +go.etcd.io/bbolt v1.4.3/go.mod h1:tKQlpPaYCVFctUIgFKFnAlvbmB3tpy1vkTnDWohtc0E= +go.etcd.io/etcd/api/v3 v3.6.5 h1:pMMc42276sgR1j1raO/Qv3QI9Af/AuyQUW6CBAWuntA= +go.etcd.io/etcd/api/v3 v3.6.5/go.mod h1:ob0/oWA/UQQlT1BmaEkWQzI0sJ1M0Et0mMpaABxguOQ= +go.etcd.io/etcd/api/v3 v3.6.8/go.mod h1:qyQj1HZPUV3B5cbAL8scG62+fyz5dSxxu0w8pn28N6Q= +go.etcd.io/etcd/client/pkg/v3 v3.6.5 h1:Duz9fAzIZFhYWgRjp/FgNq2gO1jId9Yae/rLn3RrBP8= +go.etcd.io/etcd/client/pkg/v3 v3.6.5/go.mod h1:8Wx3eGRPiy0qOFMZT/hfvdos+DjEaPxdIDiCDUv/FQk= +go.etcd.io/etcd/client/pkg/v3 v3.6.8/go.mod h1:GsiTRUZE2318PggZkAo6sWb6l8JLVrnckTNfbG8PWtw= +go.etcd.io/etcd/client/v3 v3.6.5 h1:yRwZNFBx/35VKHTcLDeO7XVLbCBFbPi+XV4OC3QJf2U= +go.etcd.io/etcd/client/v3 v3.6.5/go.mod h1:ZqwG/7TAFZ0BJ0jXRPoJjKQJtbFo/9NIY8uoFFKcCyo= +go.etcd.io/etcd/client/v3 v3.6.8/go.mod h1:MVG4BpSIuumPi+ELF7wYtySETmoTWBHVcDoHdVupwt8= go.etcd.io/etcd/pkg/v3 v3.6.4/go.mod h1:kKcYWP8gHuBRcteyv6MXWSN0+bVMnfgqiHueIZnKMtE= +go.etcd.io/etcd/pkg/v3 v3.6.5/go.mod h1:uqrXrzmMIJDEy5j00bCqhVLzR5jEJIwDp5wTlLwPGOU= +go.etcd.io/etcd/pkg/v3 v3.6.8/go.mod h1:TRibVNe+FqJIe1abOAA1PsuQ4wqO87ZaOoprg09Tn8c= go.etcd.io/etcd/server/v3 v3.6.4/go.mod h1:aYCL/h43yiONOv0QIR82kH/2xZ7m+IWYjzRmyQfnCAg= +go.etcd.io/etcd/server/v3 v3.6.5/go.mod h1:PLuhyVXz8WWRhzXDsl3A3zv/+aK9e4A9lpQkqawIaH0= +go.etcd.io/etcd/server/v3 v3.6.8/go.mod h1:88dCtwUnSirkUoJbflQxxWXqtBSZa6lSG0Kuej+dois= +go.etcd.io/gofail v0.2.0/go.mod h1:nL3ILMGfkXTekKI3clMBNazKnjUZjYLKmBHzsVAnC1o= go.etcd.io/raft/v3 v3.6.0/go.mod h1:nLvLevg6+xrVtHUmVaTcTz603gQPHfh7kUAwV6YpfGo= +go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo= +go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A= go.opentelemetry.io/contrib/detectors/gcp v1.39.0/go.mod h1:t/OGqzHBa5v6RHZwrDBJ2OirWc+4q/w2fTbLZwAKjTk= go.opentelemetry.io/contrib/instrumentation/github.com/emicklei/go-restful/otelrestful v0.44.0/go.mod h1:uq8DrRaen3suIWTpdR/JNHCGpurSvMv9D5Nr5CU5TXc= +go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.61.0 h1:q4XOmH/0opmeuJtPsbFNivyl7bCt7yRBbeEm2sC/XtQ= +go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.61.0/go.mod h1:snMWehoOh2wsEwnvvwtDyFCxVeDAODenXHtn5vzrKjo= +go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.65.0/go.mod h1:KDgtbWKTQs4bM+VPUr6WlL9m/WXcmkCcBlIzqxPGzmI= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.61.0/go.mod h1:UHB22Z8QsdRDrnAtX4PntOl36ajSxcdUMt1sF7Y6E7Q= +go.opentelemetry.io/otel v1.36.0/go.mod h1:/TcFMXYjyRNh8khOAO9ybYkqaDBb/70aVwkNML4pP8E= +go.opentelemetry.io/otel v1.38.0/go.mod h1:zcmtmQ1+YmQM9wrNsTGV/q/uyusom3P8RxwExxkZhjM= +go.opentelemetry.io/otel v1.39.0/go.mod h1:kLlFTywNWrFyEdH0oj2xK0bFYZtHRYUdv1NklR/tgc8= +go.opentelemetry.io/otel v1.40.0/go.mod h1:IMb+uXZUKkMXdPddhwAHm6UfOwJyh4ct1ybIlV14J0g= +go.opentelemetry.io/otel v1.41.0/go.mod h1:Yt4UwgEKeT05QbLwbyHXEwhnjxNO6D8L5PQP51/46dE= +go.opentelemetry.io/otel v1.42.0/go.mod h1:lJNsdRMxCUIWuMlVJWzecSMuNjE7dOYyWlqOXWkdqCc= go.opentelemetry.io/otel/exporters/otlp/internal/retry v1.10.0/go.mod h1:78XhIg8Ht9vR4tbLNUhXsiOnE2HOuSeKAiAcoVQEpOY= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.34.0/go.mod h1:7Bept48yIeqxP2OZ9/AqIpYS94h2or0aB4FypJTc8ZM= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.42.0/go.mod h1:J2pvYM5NGHofZ2/Ru6zw/TNWnEQp5crgyDeSrYpXkAw= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.34.0/go.mod h1:U7HYyW0zt/a9x5J1Kjs+r1f/d4ZHnYFclhYY2+YbeoE= +go.opentelemetry.io/otel/metric v1.36.0/go.mod h1:zC7Ks+yeyJt4xig9DEw9kuUFe5C3zLbVjV2PzT6qzbs= +go.opentelemetry.io/otel/metric v1.38.0/go.mod h1:kB5n/QoRM8YwmUahxvI3bO34eVtQf2i4utNVLr9gEmI= +go.opentelemetry.io/otel/metric v1.39.0/go.mod h1:jrZSWL33sD7bBxg1xjrqyDjnuzTUB0x1nBERXd7Ftcs= +go.opentelemetry.io/otel/metric v1.40.0/go.mod h1:ib/crwQH7N3r5kfiBZQbwrTge743UDc7DTFVZrrXnqc= +go.opentelemetry.io/otel/metric v1.41.0/go.mod h1:xPvCwd9pU0VN8tPZYzDZV/BMj9CM9vs00GuBjeKhJps= +go.opentelemetry.io/otel/metric v1.42.0/go.mod h1:RlUN/7vTU7Ao/diDkEpQpnz3/92J9ko05BIwxYa2SSI= +go.opentelemetry.io/otel/sdk v1.36.0/go.mod h1:+lC+mTgD+MUWfjJubi2vvXWcVxyr9rmlshZni72pXeY= +go.opentelemetry.io/otel/sdk v1.38.0/go.mod h1:ghmNdGlVemJI3+ZB5iDEuk4bWA3GkTpW+DOoZMYBVVg= +go.opentelemetry.io/otel/sdk v1.39.0/go.mod h1:vDojkC4/jsTJsE+kh+LXYQlbL8CgrEcwmt1ENZszdJE= +go.opentelemetry.io/otel/sdk v1.40.0/go.mod h1:Ph7EFdYvxq72Y8Li9q8KebuYUr2KoeyHx0DRMKrYBUE= +go.opentelemetry.io/otel/sdk v1.42.0/go.mod h1:rGHCAxd9DAph0joO4W6OPwxjNTYWghRWmkHuGbayMts= +go.opentelemetry.io/otel/sdk/log/logtest v0.19.0/go.mod h1:Lua81/3yM0wOmoHTokLj9y9ADeA02v1naRrVrkAZuKk= +go.opentelemetry.io/otel/sdk/metric v1.38.0/go.mod h1:dg9PBnW9XdQ1Hd6ZnRz689CbtrUp0wMMs9iPcgT9EZA= +go.opentelemetry.io/otel/sdk/metric v1.39.0/go.mod h1:xq9HEVH7qeX69/JnwEfp6fVq5wosJsY1mt4lLfYdVew= +go.opentelemetry.io/otel/sdk/metric v1.40.0/go.mod h1:4Z2bGMf0KSK3uRjlczMOeMhKU2rhUqdWNoKcYrtcBPg= +go.opentelemetry.io/otel/sdk/metric v1.42.0/go.mod h1:Ua6AAlDKdZ7tdvaQKfSmnFTdHx37+J4ba8MwVCYM5hc= +go.opentelemetry.io/otel/trace v1.36.0/go.mod h1:gQ+OnDZzrybY4k4seLzPAWNwVBBVlF2szhehOBB/tGA= +go.opentelemetry.io/otel/trace v1.38.0/go.mod h1:j1P9ivuFsTceSWe1oY+EeW3sc+Pp42sO++GHkg4wwhs= +go.opentelemetry.io/otel/trace v1.39.0/go.mod h1:88w4/PnZSazkGzz/w84VHpQafiU4EtqqlVdxWy+rNOA= +go.opentelemetry.io/otel/trace v1.40.0/go.mod h1:zeAhriXecNGP/s2SEG3+Y8X9ujcJOTqQ5RgdEJcawiA= +go.opentelemetry.io/otel/trace v1.41.0/go.mod h1:U1NU4ULCoxeDKc09yCWdWe+3QoyweJcISEVa1RBzOis= +go.opentelemetry.io/otel/trace v1.42.0/go.mod h1:f3K9S+IFqnumBkKhRJMeaZeNk9epyhnCmQh/EysQCdc= +go.opentelemetry.io/proto/otlp v1.5.0/go.mod h1:keN8WnHxOy8PG0rQZjJJ5A2ebUoafqWp0eVQ4yIXvJ4= +go.opentelemetry.io/proto/otlp v1.7.1/go.mod h1:b2rVh6rfI/s2pHWNlB7ILJcRALpcNDzKhACevjI+ZnE= go.starlark.net v0.0.0-20230525235612-a134d8f9ddca/go.mod h1:jxU+3+j+71eXOW14274+SmmuW82qJzl6iZSeqEtTGds= go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= +go.uber.org/atomic v1.10.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0= +go.uber.org/automaxprocs v1.6.0/go.mod h1:ifeIMSnPZuznNm6jmdzmU3/bfk01Fe2fotchwEFJ8r8= +go.uber.org/goleak v1.2.0/go.mod h1:XJYK+MuIchqpmGmUSAzotztawfKvYLUIgg7guXrwVUo= +go.uber.org/multierr v1.10.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= +go.uber.org/ratelimit v0.3.1/go.mod h1:6euWsTB6U/Nb3X++xEUXA8ciPJvr19Q/0h1+oDcJhRk= +go.yaml.in/yaml/v2 v2.4.2/go.mod h1:081UH+NErpNdqlCXm3TtEran0rJZGxAYx9hb/ELlsPU= +go.yaml.in/yaml/v3 v3.0.3/go.mod h1:tBHosrYAkRZjRAOREWbDnBXUf08JOwYq++0QNwQiWzI= +golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc= +golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4= +golang.org/x/crypto v0.15.0/go.mod h1:4ChreQoLWfG3xLDer1WdlH5NdlQ3+mwnQq1YTKY+72g= +golang.org/x/crypto v0.30.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk= +golang.org/x/crypto v0.41.0/go.mod h1:pO5AFd7FA68rFak7rOAGVuygIISepHftHnr8dr6+sUc= +golang.org/x/crypto v0.45.0/go.mod h1:XTGrrkGJve7CYK7J8PEww4aY7gM3qMCElcJQ8n8JdX4= +golang.org/x/crypto v0.47.0/go.mod h1:ff3Y9VzzKbwSSEzWqJsJVBnWmRwRSHt/6Op5n9bQc4A= +golang.org/x/exp v0.0.0-20230515195305-f3d0a9c9a5cc/go.mod h1:V1LtkGg67GoY2N1AnLN78QLrzxkLyJw7RJb1gzOOz9w= +golang.org/x/exp v0.0.0-20240506185415-9bf2ced13842/go.mod h1:XtvwrStGgqGPLc4cjQfWqZHG1YFdYs6swckp8vpsjnc= +golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56/go.mod h1:M4RDyNAINzryxdtnbRXRL/OHtkFuWGRjvuhBJpk2IlY= +golang.org/x/image v0.25.0/go.mod h1:tCAmOEGthTtkalusGp1g3xa2gke8J6c2N565dTyl9Rs= +golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= +golang.org/x/mod v0.14.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= +golang.org/x/mod v0.21.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY= +golang.org/x/mod v0.25.0/go.mod h1:IXM97Txy2VM4PJ3gI61r1YEk/gAj6zAHN3AdZt6S9Ww= +golang.org/x/mod v0.27.0/go.mod h1:rWI627Fq0DEoudcK+MBkNkCe0EetEaDSwJJkCcjpazc= +golang.org/x/mod v0.29.0/go.mod h1:NyhrlYXJ2H4eJiRy/WDBO6HMqZQ6q9nk4JzS3NuCK+w= +golang.org/x/mod v0.30.0 h1:fDEXFVZ/fmCKProc/yAXXUijritrDzahmwwefnjoPFk= golang.org/x/mod v0.30.0/go.mod h1:lAsf5O2EvJeSFMiBxXDki7sCgAxEUcZHXoXMKT4GJKc= +golang.org/x/mod v0.31.0/go.mod h1:43JraMp9cGx1Rx3AqioxrbrhNsLl2l/iNAvuBkrezpg= +golang.org/x/mod v0.32.0/go.mod h1:SgipZ/3h2Ci89DlEtEXWUk/HteuRin+HHhN+WbNhguU= +golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/net v0.0.0-20201202161906-c7110b5ffcbb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20211123203042-d83791d6bcd9/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk= +golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= +golang.org/x/net v0.18.0/go.mod h1:/czyP5RqHAH4odGYxBJ1qz0+CE5WZ+2j1YgoEo8F2jQ= +golang.org/x/net v0.38.0/go.mod h1:ivrbrMbzFq5J41QOQh0siUuly180yBYtLp+CKbEaFx8= +golang.org/x/net v0.40.0/go.mod h1:y0hY0exeL2Pku80/zKK7tpntoX23cqL3Oa6njdgRtds= +golang.org/x/net v0.41.0/go.mod h1:B/K4NNqkfmg07DQYrbwvSluqCJOOXwUjeb/5lOisjbA= +golang.org/x/net v0.43.0/go.mod h1:vhO1fvI4dGsIjh73sWfUVjj3N7CA9WkKJNQm2svM6Jg= +golang.org/x/net v0.46.0/go.mod h1:Q9BGdFy1y4nkUwiLvT5qtyhAnEHgnQ/zd8PfU6nc210= +golang.org/x/net v0.47.0/go.mod h1:/jNxtkgq5yWUGYkaZGqo27cfGZ1c5Nen03aYrrKpVRU= +golang.org/x/net v0.49.0/go.mod h1:/ysNB2EvaqvesRkuLAyjI1ycPZlQHM3q01F02UY/MV8= +golang.org/x/net v0.50.0/go.mod h1:UgoSli3F/pBgdJBHCTc+tp3gmrU4XswgGRgtnwWTfyM= +golang.org/x/net v0.51.0/go.mod h1:aamm+2QF5ogm02fjy5Bb7CQ0WMt1/WVM7FtyaTLlA9Y= +golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.30.0/go.mod h1:B++QgG3ZKulg6sRPGD/mqlHQs5rB3Ml9erfeDY7xKlU= +golang.org/x/oauth2 v0.32.0/go.mod h1:lzm5WQJQwKZ3nwavOZ3IS5Aulzxi68dUSgRHujetwEA= +golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= +golang.org/x/sync v0.4.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= +golang.org/x/sync v0.5.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sync v0.16.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA= +golang.org/x/sync v0.17.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI= +golang.org/x/sync v0.18.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI= +golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190801041406-cbf593c0f2f3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220310020820-b874c991c1a5/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.14.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.26.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.29.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.31.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= +golang.org/x/sys v0.32.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= +golang.org/x/sys v0.33.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= +golang.org/x/sys v0.35.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= +golang.org/x/sys v0.37.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= +golang.org/x/sys v0.38.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= +golang.org/x/sys v0.39.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= +golang.org/x/sys v0.41.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= +golang.org/x/telemetry v0.0.0-20251111182119-bc8e575c7b54/go.mod h1:hKdjCMrbv9skySur+Nek8Hd0uJ0GuxJIoIX2payrIdQ= +golang.org/x/telemetry v0.0.0-20260209163413-e7419c687ee4/go.mod h1:g5NllXBEermZrmR51cJDQxmJUHUOfRAaNyWBM+R+548= +golang.org/x/telemetry v0.0.0-20260311193753-579e4da9a98c/go.mod h1:TpUTTEp9frx7rTdLpC9gFG9kdI7zVLFTFFlqaH2Cncw= +golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU= +golang.org/x/term v0.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U= +golang.org/x/term v0.14.0/go.mod h1:TySc+nGkYR6qt8km8wUhuFRTVSMIX3XPR58y2lC8vww= +golang.org/x/term v0.37.0/go.mod h1:5pB4lxRNYYVZuTLmy8oR2BH8dflOR+IbTYFD8fi3254= +golang.org/x/term v0.39.0/go.mod h1:yxzUCTP/U+FzoxfdKmLaA0RV1WgE0VY7hXBwKtY/4ww= +golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= +golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= +golang.org/x/text v0.22.0/go.mod h1:YRoo4H8PVmsu+E3Ou7cqLVH8oXWIHVoX0jqUWALQhfY= +golang.org/x/text v0.23.0/go.mod h1:/BLNzu4aZCJ1+kcD0DNRotWKage4q2rGVAg4o22unh4= +golang.org/x/text v0.25.0/go.mod h1:WEdwpYrmk1qmdHvhkSTNPm3app7v4rsT8F2UD6+VHIA= +golang.org/x/text v0.28.0/go.mod h1:U8nCwOR8jO/marOQ0QbDiOngZVEBB7MAiitBuMjXiNU= +golang.org/x/text v0.29.0/go.mod h1:7MhJOA9CD2qZyOKYazxdYMF85OwPdEr9jTtBpO7ydH4= +golang.org/x/text v0.30.0/go.mod h1:yDdHFIX9t+tORqspjENWgzaCVXgk0yYnYuSZ8UzzBVM= +golang.org/x/text v0.31.0/go.mod h1:tKRAlv61yKIjGGHX/4tP1LTbc13YSec1pxVEWXzfoeM= +golang.org/x/text v0.33.0/go.mod h1:LuMebE6+rBincTi9+xWTY8TztLzKHc/9C1uBCG27+q8= +golang.org/x/text v0.34.0/go.mod h1:homfLqTYRFyVYemLBFl5GgL/DWEiH5wcsQ5gSh1yziA= +golang.org/x/time v0.9.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= +golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58= +golang.org/x/tools v0.15.0/go.mod h1:hpksKq4dtpQWS1uQ61JkdqWM3LscIS6Slf+VVkm+wQk= +golang.org/x/tools v0.16.1/go.mod h1:kYVVN6I1mBNoB1OX+noeBjbRk4IUEPa7JJ+TJMEooJ0= +golang.org/x/tools v0.26.0/go.mod h1:TPVVj70c7JJ3WCazhD8OdXcZg/og+b9+tH/KxylGwH0= +golang.org/x/tools v0.36.0/go.mod h1:WBDiHKJK8YgLHlcQPYQzNCkUxUypCaa5ZegCVutKm+s= +golang.org/x/tools v0.38.0/go.mod h1:yEsQ/d/YK8cjh0L6rZlY8tgtlKiBNTL14pGDJPJpYQs= +golang.org/x/tools v0.40.0/go.mod h1:Ik/tzLRlbscWpqqMRjyWYDisX8bG13FrdXp3o4Sr9lc= +golang.org/x/tools v0.41.0/go.mod h1:XSY6eDqxVNiYgezAVqqCeihT4j1U2CCsqvH3WhQpnlg= +golang.org/x/tools/go/expect v0.1.0-deprecated/go.mod h1:eihoPOH+FgIqa3FpoTwguz/bVUSGBlGQU67vpBeOrBY= golang.org/x/tools/go/expect v0.1.1-deprecated/go.mod h1:eihoPOH+FgIqa3FpoTwguz/bVUSGBlGQU67vpBeOrBY= golang.org/x/tools/go/packages/packagestest v0.1.1-deprecated/go.mod h1:RVAQXBGNv1ib0J382/DPCRS/BPnsGebyM1Gj5VSDpG8= +gonum.org/v1/gonum v0.17.0/go.mod h1:El3tOrEuMpv2UdMrbNlKEh9vd86bmQ6vqIcDwxEOc1E= +gonum.org/v1/plot v0.15.2/go.mod h1:DX+x+DWso3LTha+AdkJEv5Txvi+Tql3KAGkehP0/Ubg= +gonum.org/v1/tools v0.0.0-20200318103217-c168b003ce8c/go.mod h1:fy6Otjqbk477ELp8IXTpw1cObQtLbRCBVonY+bTTfcM= +google.golang.org/api v0.269.0/go.mod h1:N8Wpcu23Tlccl0zSHEkcAZQKDLdquxK+l9r2LkwAauE= +google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= -google.golang.org/genproto v0.0.0-20230711160842-782d3b101e98 h1:Z0hjGZePRE0ZBWotvtrwxFNrNE9CUAGtplaDK5NNI/g= google.golang.org/genproto v0.0.0-20230711160842-782d3b101e98/go.mod h1:S7mY02OqCJTD0E1OiQy1F72PWFB4bZJ87cAtLPYgDR0= +google.golang.org/genproto v0.0.0-20241118233622-e639e219e697 h1:ToEetK57OidYuqD4Q5w+vfEnPvPpuTwedCNVohYJfNk= +google.golang.org/genproto v0.0.0-20241118233622-e639e219e697/go.mod h1:JJrvXBWRZaFMxBufik1a4RpFw4HhgVtBBWQeQgUj2cc= +google.golang.org/genproto/googleapis/api v0.0.0-20240826202546-f6391c0de4c7/go.mod h1:OCdP9MfskevB/rbYvHTsXTtKC+3bHWajPdoKgjcYkfo= +google.golang.org/genproto/googleapis/api v0.0.0-20250303144028-a0af3efb3deb/go.mod h1:jbe3Bkdp+Dh2IrslsFCklNhweNTBgSYanP1UXhJDhKg= +google.golang.org/genproto/googleapis/api v0.0.0-20250825161204-c5933d9347a5/go.mod h1:j3QtIyytwqGr1JUDtYXwtMXWPKsEa5LtzIFN1Wn5WvE= +google.golang.org/genproto/googleapis/api v0.0.0-20250929231259-57b25ae835d4/go.mod h1:NnuHhy+bxcg30o7FnVAZbXsPHUDQ9qKWAQKCD7VxFtk= +google.golang.org/genproto/googleapis/api v0.0.0-20260120221211-b8f7ae30c516/go.mod h1:p3MLuOwURrGBRoEyFHBT3GjUwaCQVKeNqqWxlcISGdw= +google.golang.org/genproto/googleapis/api v0.0.0-20260209200024-4cfbd4190f57/go.mod h1:kSJwQxqmFXeo79zOmbrALdflXQeAYcUbgS7PbpMknCY= +google.golang.org/genproto/googleapis/rpc v0.0.0-20230525234030-28d5490b6b19/go.mod h1:66JfowdXAEgad5O9NnYcsNPLCPZJD++2L9X0PCMODrA= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240826202546-f6391c0de4c7/go.mod h1:UqMtugtsSgubUsoxbuAoiCXvqvErP7Gf0so0mK9tHxU= +google.golang.org/genproto/googleapis/rpc v0.0.0-20250519155744-55703ea1f237/go.mod h1:qQ0YXyHHx3XkvlzUtpXDkS29lDSafHMZBAZDc03LQ3A= +google.golang.org/genproto/googleapis/rpc v0.0.0-20250528174236-200df99c418a/go.mod h1:qQ0YXyHHx3XkvlzUtpXDkS29lDSafHMZBAZDc03LQ3A= +google.golang.org/genproto/googleapis/rpc v0.0.0-20250825161204-c5933d9347a5/go.mod h1:M4/wBTSeyLxupu3W3tJtOgB14jILAS/XWPSSa3TAlJc= +google.golang.org/genproto/googleapis/rpc v0.0.0-20250929231259-57b25ae835d4/go.mod h1:HSkG/KdJWusxU1F6CNrwNDjBMgisKxGnc5dAZfT0mjQ= +google.golang.org/genproto/googleapis/rpc v0.0.0-20251124214823-79d6a2a48846/go.mod h1:7i2o+ce6H/6BluujYR+kqX3GKH+dChPTQU19wjRPiGk= +google.golang.org/genproto/googleapis/rpc v0.0.0-20260120221211-b8f7ae30c516/go.mod h1:j9x/tPzZkyxcgEFkiKEEGxfvyumM01BEtsW8xzOahRQ= +google.golang.org/genproto/googleapis/rpc v0.0.0-20260122232226-8e98ce8d340d/go.mod h1:j9x/tPzZkyxcgEFkiKEEGxfvyumM01BEtsW8xzOahRQ= +google.golang.org/genproto/googleapis/rpc v0.0.0-20260128011058-8636f8732409/go.mod h1:j9x/tPzZkyxcgEFkiKEEGxfvyumM01BEtsW8xzOahRQ= +google.golang.org/genproto/googleapis/rpc v0.0.0-20260209200024-4cfbd4190f57/go.mod h1:j9x/tPzZkyxcgEFkiKEEGxfvyumM01BEtsW8xzOahRQ= +google.golang.org/genproto/googleapis/rpc v0.0.0-20260401001100-f93e5f3e9f0f/go.mod h1:4Hqkh8ycfw05ld/3BWL7rJOSfebL2Q+DVDeRgYgxUU8= +google.golang.org/grpc v1.56.3/go.mod h1:I9bI3vqKfayGqPUAwGdOSu7kt6oIJLixfffKrpXqQ9s= +google.golang.org/grpc v1.71.0/go.mod h1:H0GRtasmQOh9LkFoCPDu3ZrwUtD1YGE+b2vYBYd/8Ec= +google.golang.org/grpc v1.72.1/go.mod h1:wH5Aktxcg25y1I3w7H69nHfXdOG3UiadoBtjh3izSDM= +google.golang.org/grpc v1.72.2/go.mod h1:wH5Aktxcg25y1I3w7H69nHfXdOG3UiadoBtjh3izSDM= +google.golang.org/grpc v1.75.0/go.mod h1:JtPAzKiq4v1xcAB2hydNlWI2RnF85XXcV0mhKXr2ecQ= +google.golang.org/grpc v1.75.1/go.mod h1:JtPAzKiq4v1xcAB2hydNlWI2RnF85XXcV0mhKXr2ecQ= +google.golang.org/grpc v1.78.0/go.mod h1:I47qjTo4OKbMkjA/aOOwxDIiPSBofUtQUI5EfpWvW7U= +google.golang.org/grpc v1.79.1/go.mod h1:KmT0Kjez+0dde/v2j9vzwoAScgEPx/Bw1CYChhHLrHQ= +google.golang.org/grpc v1.79.2/go.mod h1:KmT0Kjez+0dde/v2j9vzwoAScgEPx/Bw1CYChhHLrHQ= +google.golang.org/grpc/examples v0.0.0-20250407062114-b368379ef8f6/go.mod h1:6ytKWczdvnpnO+m+JiG9NjEDzR1FJfsnmJdG7B8QVZ8= +google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= +google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= +google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= +google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= +google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= +google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= +google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= +google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw= +google.golang.org/protobuf v1.35.1/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= +google.golang.org/protobuf v1.36.5/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= +google.golang.org/protobuf v1.36.6/go.mod h1:jduwjTPXsFjZGTmRluh+L6NjiWu7pchiJ2/5YcXBHnY= +google.golang.org/protobuf v1.36.7/go.mod h1:jduwjTPXsFjZGTmRluh+L6NjiWu7pchiJ2/5YcXBHnY= +google.golang.org/protobuf v1.36.8/go.mod h1:fuxRtAxBytpl4zzqUh6/eyUujkJdNiuEkXntxiD/uRU= +gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= +gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/go-jose/go-jose.v2 v2.6.3/go.mod h1:zzZDPkNNw/c9IE7Z9jr11mBZQhKQTMzoEEIoEdZlFBI= gopkg.in/ini.v1 v1.62.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= +gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/natefinch/lumberjack.v2 v2.2.1/go.mod h1:YD8tP3GAjkrDg1eZH7EGmyESg/lsYskCTPBJVb9jqSc= +gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +k8s.io/api v0.35.0/go.mod h1:AQ0SNTzm4ZAczM03QH42c7l3bih1TbAXYo0DkF8ktnA= +k8s.io/api v0.35.1/go.mod h1:28uR9xlXWml9eT0uaGo6y71xK86JBELShLy4wR1XtxM= +k8s.io/apiextensions-apiserver v0.35.0/go.mod h1:E1Ahk9SADaLQ4qtzYFkwUqusXTcaV2uw3l14aqpL2LU= +k8s.io/apimachinery v0.35.0/go.mod h1:jQCgFZFR1F4Ik7hvr2g84RTJSZegBc8yHgFWKn//hns= +k8s.io/apimachinery v0.35.1/go.mod h1:jQCgFZFR1F4Ik7hvr2g84RTJSZegBc8yHgFWKn//hns= +k8s.io/apiserver v0.35.0/go.mod h1:QUy1U4+PrzbJaM3XGu2tQ7U9A4udRRo5cyxkFX0GEds= +k8s.io/client-go v0.35.0/go.mod h1:q2E5AAyqcbeLGPdoRB+Nxe3KYTfPce1Dnu1myQdqz9o= +k8s.io/client-go v0.35.1/go.mod h1:1p1KxDt3a0ruRfc/pG4qT/3oHmUj1AhSHEcxNSGg+OA= k8s.io/code-generator v0.34.1/go.mod h1:DeWjekbDnJWRwpw3s0Jat87c+e0TgkxoR4ar608yqvg= +k8s.io/code-generator v0.35.0/go.mod h1:iS1gvVf3c/T71N5DOGYO+Gt3PdJ6B9LYSvIyQ4FHzgc= +k8s.io/code-generator v0.35.2/go.mod h1:id4XLCm0yAQq5nlvyfAKibMOKnMjzlesAwGw6kM3Adc= +k8s.io/code-generator v0.36.0/go.mod h1:Tr2UhfBRdlyRoadfob9aPCmmGe8PUs5XPK9MEJ2nx+w= +k8s.io/component-base v0.35.0/go.mod h1:85SCX4UCa6SCFt6p3IKAPej7jSnF3L8EbfSyMZayJR0= +k8s.io/component-base v0.35.1/go.mod h1:HI/6jXlwkiOL5zL9bqA3en1Ygv60F03oEpnuU1G56Bs= +k8s.io/component-helpers v0.35.1 h1:vwQ/cAfnVwaPeSXTu4DdK3d3n11Lugc5vMb6EV809ZY= +k8s.io/component-helpers v0.35.1/go.mod h1:HQqMwUk68Yyxgj92dJ+J1w/qbx9M0QR0eZ680m/o+Rk= k8s.io/gengo v0.0.0-20220902162205-c0856e24416d/go.mod h1:FiNAH4ZV3gBg2Kwh89tzAEV2be7d5xI0vBa/VySYy3E= k8s.io/gengo/v2 v2.0.0-20250604051438-85fd79dbfd9f/go.mod h1:EJykeLsmFC60UQbYJezXkEsG2FLrt0GPNkU5iK5GWxU= +k8s.io/gengo/v2 v2.0.0-20250922181213-ec3ebc5fd46b/go.mod h1:CgujABENc3KuTrcsdpGmrrASjtQsWCT7R99mEV4U/fM= k8s.io/klog v1.0.0 h1:Pt+yjF5aB1xDSVbau4VsWe+dQNzA0qv1LlXdC2dF6Q8= k8s.io/klog v1.0.0/go.mod h1:4Bi6QPql/J/LkTDqv7R/cd3hPo4k2DG6Ptcz060Ez5I= +k8s.io/klog/v2 v2.0.0/go.mod h1:PBfzABfn139FHAV07az/IF9Wp1bkk3vpT2XSJ76fSDE= +k8s.io/klog/v2 v2.2.0/go.mod h1:Od+F08eJP+W3HUb4pSrPpgp9DGU4GzlpG/TmITuYh/Y= +k8s.io/klog/v2 v2.80.1/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0= k8s.io/kms v0.34.1/go.mod h1:s1CFkLG7w9eaTYvctOxosx88fl4spqmixnNpys0JAtM= +k8s.io/kms v0.35.0/go.mod h1:VT+4ekZAdrZDMgShK37vvlyHUVhwI9t/9tvh0AyCWmQ= +k8s.io/kms v0.35.2/go.mod h1:VT+4ekZAdrZDMgShK37vvlyHUVhwI9t/9tvh0AyCWmQ= +k8s.io/kms v0.36.0/go.mod h1:g91diTD9h0oJCCHkTb00krlF+Qm5HTnkWLi9Q/TpRoc= k8s.io/kube-aggregator v0.22.17/go.mod h1:J557nueFVurHA1JiDrxT1HlgygNQ+2exsTVUXiz2T7k= +k8s.io/kube-aggregator v0.35.2/go.mod h1:7Xl9zFJFsFIrPnwBfu7hve+G5QgLsDZRIedc8gA1mq4= +k8s.io/kube-openapi v0.0.0-20241212222426-2c72e554b1e7/go.mod h1:GewRfANuJ70iYzvn+i4lezLDAFzvjxZYK1gn1lWcfas= k8s.io/metrics v0.34.2/go.mod h1:Ydulln+8uZZctUM8yrUQX4rfq/Ay6UzsuXf24QJ37Vc= +k8s.io/metrics v0.35.1/go.mod h1:9x7xWOAOiWzHA0vaqLgSE4PXF3vyT5ts5XIbx8OSjiI= +k8s.io/metrics v0.36.0/go.mod h1:FY1dgPJZqnSfnOYbVdBEdRNUdy0n1nUCU6yxSMUrVG4= +k8s.io/streaming v0.36.0 h1:agnTxU+NFulUrtYzXUGKO3ndEa8jKwht1Kwn9nu9x+4= +k8s.io/streaming v0.36.0/go.mod h1:z6fV3D+NVkoeqRMtWwlUZK6U17SY/LqNzOxWL6GyR/s= k8s.io/system-validators v1.10.2/go.mod h1:awfSS706v9R12VC7u7K89FKfqVy44G+E0L1A0FX9Wmw= +k8s.io/utils v0.0.0-20240711033017-18e509b52bc8/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= +rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4= +sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.31.2/go.mod h1:Ve9uj1L+deCXFrPOk1LpFXqTg7LCFzFso6PA48q/XZw= +sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.34.0 h1:hSfpvjjTQXQY2Fol2CS0QHMNs/WI1MOSGzCm1KhM5ec= +sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.34.0/go.mod h1:Ve9uj1L+deCXFrPOk1LpFXqTg7LCFzFso6PA48q/XZw= sigs.k8s.io/controller-tools v0.7.0/go.mod h1:bpBAo0VcSDDLuWt47evLhMLPxRPxMDInTEH/YbdeMK0= +sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd/go.mod h1:B8JuhiUyNFVKdsE8h686QcCxMaH6HrOAZj4vswFpcB0= sigs.k8s.io/knftables v0.0.17/go.mod h1:f/5ZLKYEUPUhVjUCg6l80ACdL7CIIyeL0DxfgojGRTk= sigs.k8s.io/kustomize/api v0.20.1/go.mod h1:t6hUFxO+Ph0VxIk1sKp1WS0dOjbPCtLJ4p8aADLwqjM= +sigs.k8s.io/kustomize/cmd/config v0.20.1/go.mod h1:R7rQ8kxknVlXWVUIbxWtMgu8DCCNVtl8V0KrmeVd/KE= +sigs.k8s.io/kustomize/cmd/config v0.21.1/go.mod h1:7yEFYBJyBJlpZQ50VaRGQRtFMn3Vzn9Fb2wts4TCok4= sigs.k8s.io/kustomize/kustomize/v5 v5.7.1/go.mod h1:+5/SrBcJ4agx1SJknGuR/c9thwRSKLxnKoI5BzXFaLU= +sigs.k8s.io/kustomize/kustomize/v5 v5.8.1/go.mod h1:0vFa5pQ/elNEQMyiAJuGku9rhAMzz7u9+61hRqFKiwY= sigs.k8s.io/kustomize/kyaml v0.20.1/go.mod h1:0EmkQHRUsJxY8Ug9Niig1pUMSCGHxQ5RklbpV/Ri6po= +sigs.k8s.io/randfill v0.0.0-20250304075658-069ef1bbf016/go.mod h1:XeLlZ/jmk4i1HRopwe7/aU3H5n1zNUcX6TM94b3QxOY= sigs.k8s.io/structured-merge-diff/v4 v4.6.0/go.mod h1:dDy58f92j70zLsuZVuUX5Wp9vtxXpaZnkPGWeqDfCps= +sigs.k8s.io/structured-merge-diff/v6 v6.2.0/go.mod h1:M3W8sfWvn2HhQDIbGWj3S099YozAsymCo/wrT5ohRUE= +sigs.k8s.io/structured-merge-diff/v6 v6.3.2-0.20260122202528-d9cc6641c482/go.mod h1:M3W8sfWvn2HhQDIbGWj3S099YozAsymCo/wrT5ohRUE= +sigs.k8s.io/yaml v1.4.0/go.mod h1:Ejl7/uTz7PSA4eKMyQCUTnhZYNmLIl+5c2lQPGR2BPY= +sigs.k8s.io/yaml v1.5.0/go.mod h1:wZs27Rbxoai4C0f8/9urLZtZtF3avA3gKvGyPdDqTO4= +software.sslmate.com/src/go-pkcs12 v0.7.0/go.mod h1:Qiz0EyvDRJjjxGyUQa2cCNZn/wMyzrRJ/qcDXOQazLI= diff --git a/hack/generate-image-list.sh b/hack/generate-image-list.sh new file mode 100755 index 000000000..aec3c7642 --- /dev/null +++ b/hack/generate-image-list.sh @@ -0,0 +1,124 @@ +#!/usr/bin/env bash +# Generate the digest-pinned platform image list for a release. +# +# hack/generate-image-list.sh [--no-digests] +# +# Writes one fully qualified image reference per line to stdout +# (`:@sha256:`), covering everything an air-gapped +# install of the platform needs (see decisions.md "Image relocation is +# a published digest-pinned list"): +# +# - the Educates platform images at the released version (operator, +# runtime components, pause-container, docker-registry, ...) plus +# the workshop base-environment image, composed from the given +# registry host/namespace; +# - the upstream cluster-service images (cert-manager, Contour, +# external-dns, Kyverno), extracted by rendering the vendored +# chart tarballs with default values. Defaults are a superset of +# what the operator enables, so this over-collects slightly rather +# than ever missing an image. +# +# Workshop environment images beyond base-environment (jdk*, conda) +# are deliberately excluded — they add many GB per release. Air-gap +# users append them to the list as needed. +# +# Digest resolution uses skopeo (preinstalled on GitHub runners) and +# requires the images to already be published — the release workflow +# runs this after the image-publish jobs. Use --no-digests for a local +# dry run without registry access. +set -euo pipefail + +usage() { + echo "usage: $0 [--no-digests]" >&2 + exit 1 +} + +VERSION="${1:-}" +REGISTRY_HOST="${2:-}" +REGISTRY_NAMESPACE="${3:-}" +[ -n "$VERSION" ] && [ -n "$REGISTRY_HOST" ] && [ -n "$REGISTRY_NAMESPACE" ] || usage +RESOLVE_DIGESTS=true +if [ "${4:-}" = "--no-digests" ]; then + RESOLVE_DIGESTS=false +elif [ -n "${4:-}" ]; then + usage +fi + +cd "$(dirname "$0")/.." + +VENDORED_CHARTS_DIR=installer/operator/vendored-charts + +# Educates-built platform images: the publish-generic-images matrix +# (with the operator's published name) plus the workshop +# base-environment. educates-cli and the docker extension are client +# tools, not platform images, and stay out. +PLATFORM_IMAGES=" +docker-registry +pause-container +session-manager +training-portal +secrets-manager +tunnel-manager +image-cache +assets-server +lookup-service +node-ca-injector +operator +base-environment +" + +# Upstream cluster-service charts the operator installs in Managed +# mode. Globs resolve the single vendored tarball per chart so version +# bumps don't touch this script. +UPSTREAM_CHART_GLOBS=" +cert-manager-*.tgz +contour-*.tgz +external-dns-*.tgz +kyverno-*.tgz +" + +emit() { + local ref="$1" + if $RESOLVE_DIGESTS; then + local digest + # --override-os keeps darwin hosts working; .Digest is the + # multi-arch index digest (verified equal to the raw manifest + # sha256), which is what a relocation copy should pin. + digest=$(skopeo inspect --override-os linux --format '{{.Digest}}' "docker://$ref") || { + echo "failed to resolve digest for $ref" >&2 + exit 1 + } + echo "$ref@$digest" + else + echo "$ref" + fi +} + +for name in $PLATFORM_IMAGES; do + emit "$REGISTRY_HOST/$REGISTRY_NAMESPACE/educates-$name:$VERSION" +done + +# Image references appear in rendered manifests as `image:` fields and, +# for cert-manager's acmesolver, as a `--*-image=` controller argument. +extract_chart_images() { + local tarball="$1" + helm template image-list-probe "$tarball" 2>/dev/null | + grep -ohE '(image: *"?[^"[:space:]]+"?|--[a-z0-9-]*image=[^"[:space:]]+)' | + sed -E 's/^image: *"?//; s/"$//; s/^--[a-z0-9-]*image=//' +} + +upstream_refs="" +for glob in $UPSTREAM_CHART_GLOBS; do + # shellcheck disable=SC2086 -- glob expansion is the point + set -- $VENDORED_CHARTS_DIR/$glob + [ -f "$1" ] || { + echo "no vendored chart matching $glob in $VENDORED_CHARTS_DIR" >&2 + exit 1 + } + upstream_refs+="$(extract_chart_images "$1")"$'\n' +done + +while read -r ref; do + [ -n "$ref" ] || continue + emit "$ref" +done < <(echo "$upstream_refs" | sort -u) diff --git a/hack/lint-chart-versions.sh b/hack/lint-chart-versions.sh new file mode 100755 index 000000000..873cd957a --- /dev/null +++ b/hack/lint-chart-versions.sh @@ -0,0 +1,106 @@ +#!/usr/bin/env bash +# Lint: the v4 charts stay version- and annotation-synchronized. +# +# The release pipeline (hack/stamp-release-version.sh) rewrites versions +# and registry annotations across all charts with blanket substitutions, +# which is only safe while the committed tree is uniform. This lint +# fails CI when any chart drifts: +# +# - educates-installer, the educates-training-platform umbrella and +# its five subcharts must share one `version`, and the umbrella's +# dependencies[].version pins must match it. +# - The image-rendering charts (educates-installer + the four +# annotated subcharts) must carry identical +# educates.dev/image-registry-{host,namespace} annotations. +# - The runtime charts (umbrella + five subcharts) must share one +# appVersion; educates-installer's appVersion must equal its +# version. +# - vendored-charts/embed.go must reference each local subchart +# tarball at the committed version, with a matching ChartVersion +# constant and the tarball present on disk. +# +# Requires yq (https://github.com/mikefarah/yq). +set -euo pipefail +cd "$(dirname "$0")/.." + +INSTALLER_CHART=installer/charts/educates-installer +UMBRELLA_CHART=installer/charts/educates-training-platform +LOCAL_SUBCHARTS="secrets-manager lookup-service session-manager node-ca-injector remote-access" +ANNOTATED_SUBCHARTS="secrets-manager lookup-service session-manager node-ca-injector" +VENDORED_CHARTS_DIR=installer/operator/vendored-charts +EMBED_GO=$VENDORED_CHARTS_DIR/embed.go + +fail=0 +err() { + echo "ERROR: $*" >&2 + fail=1 +} + +chart_version_const() { + case "$1" in + secrets-manager) echo SecretsManagerChartVersion ;; + lookup-service) echo LookupServiceChartVersion ;; + session-manager) echo SessionManagerChartVersion ;; + node-ca-injector) echo NodeCAInjectorChartVersion ;; + remote-access) echo RemoteAccessChartVersion ;; + esac +} + +ref_version=$(yq '.version' "$INSTALLER_CHART/Chart.yaml") +ref_host=$(yq '.annotations["educates.dev/image-registry-host"]' "$INSTALLER_CHART/Chart.yaml") +ref_namespace=$(yq '.annotations["educates.dev/image-registry-namespace"]' "$INSTALLER_CHART/Chart.yaml") + +[ "$ref_host" != "null" ] || err "$INSTALLER_CHART/Chart.yaml is missing the educates.dev/image-registry-host annotation" +[ "$ref_namespace" != "null" ] || err "$INSTALLER_CHART/Chart.yaml is missing the educates.dev/image-registry-namespace annotation" + +installer_app_version=$(yq '.appVersion' "$INSTALLER_CHART/Chart.yaml") +[ "$installer_app_version" = "$ref_version" ] || + err "$INSTALLER_CHART/Chart.yaml appVersion ($installer_app_version) != version ($ref_version)" + +umbrella_version=$(yq '.version' "$UMBRELLA_CHART/Chart.yaml") +[ "$umbrella_version" = "$ref_version" ] || + err "$UMBRELLA_CHART/Chart.yaml version ($umbrella_version) != $INSTALLER_CHART version ($ref_version)" + +while IFS=$'\t' read -r dep_name dep_version; do + [ "$dep_version" = "$ref_version" ] || + err "$UMBRELLA_CHART/Chart.yaml dependency $dep_name pins version $dep_version, expected $ref_version" +done < <(yq '.dependencies[] | [.name, .version] | @tsv' "$UMBRELLA_CHART/Chart.yaml") + +ref_app_version=$(yq '.appVersion' "$UMBRELLA_CHART/Chart.yaml") + +for name in $LOCAL_SUBCHARTS; do + chart_yaml=$UMBRELLA_CHART/charts/$name/Chart.yaml + + version=$(yq '.version' "$chart_yaml") + [ "$version" = "$ref_version" ] || + err "$chart_yaml version ($version) != $ref_version" + + app_version=$(yq '.appVersion' "$chart_yaml") + [ "$app_version" = "$ref_app_version" ] || + err "$chart_yaml appVersion ($app_version) != umbrella appVersion ($ref_app_version)" + + # embed.go must track the committed subchart version exactly. + grep -q "^//go:embed $name-$version.tgz\$" "$EMBED_GO" || + err "$EMBED_GO does not //go:embed $name-$version.tgz (run 'make package-local-charts' in installer/operator and update embed.go)" + const=$(chart_version_const "$name") + grep -q "^const $const = \"$version\"\$" "$EMBED_GO" || + err "$EMBED_GO constant $const != \"$version\"" + [ -f "$VENDORED_CHARTS_DIR/$name-$version.tgz" ] || + err "$VENDORED_CHARTS_DIR/$name-$version.tgz is missing (run 'make package-local-charts' in installer/operator)" +done + +for name in $ANNOTATED_SUBCHARTS; do + chart_yaml=$UMBRELLA_CHART/charts/$name/Chart.yaml + host=$(yq '.annotations["educates.dev/image-registry-host"]' "$chart_yaml") + namespace=$(yq '.annotations["educates.dev/image-registry-namespace"]' "$chart_yaml") + [ "$host" = "$ref_host" ] || + err "$chart_yaml educates.dev/image-registry-host ($host) != $INSTALLER_CHART's ($ref_host)" + [ "$namespace" = "$ref_namespace" ] || + err "$chart_yaml educates.dev/image-registry-namespace ($namespace) != $INSTALLER_CHART's ($ref_namespace)" +done + +if [ "$fail" -ne 0 ]; then + echo "chart version/annotation sync lint failed" >&2 + exit 1 +fi +echo "charts in sync: version $ref_version, runtime appVersion $ref_app_version, registry $ref_host/$ref_namespace" diff --git a/hack/stamp-release-version.sh b/hack/stamp-release-version.sh new file mode 100755 index 000000000..7d1e168d7 --- /dev/null +++ b/hack/stamp-release-version.sh @@ -0,0 +1,143 @@ +#!/usr/bin/env bash +# Stamp a release version across the v4 install charts and the copies +# embedded in the operator image and the CLI. +# +# hack/stamp-release-version.sh [--charts-only] +# +# The committed tree carries a development version (and upstream-default +# registry annotations); real versions are stamped at publish time from +# the git tag by the release workflow — nothing is committed back. See +# decisions.md "Release versions are stamped in CI at publish time". +# +# What gets stamped: +# - educates-installer + educates-training-platform (umbrella) + +# the five runtime subcharts: Chart.yaml version, appVersion, and +# the educates.dev/image-registry-{host,namespace} annotations +# (only where a chart already carries them). +# - The umbrella's dependencies[].version pins. +# - The CLI's embedded operator chart (regenerated from the stamped +# educates-installer chart, same as `make embed-installer-chart`). +# +# Full mode (default) additionally rebuilds what the operator image +# embeds — requires `helm` on PATH: +# - Repackages the five runtime subcharts into +# installer/operator/vendored-charts/ at the stamped version. +# - Rewrites the //go:embed filenames and ChartVersion constants +# in vendored-charts/embed.go (local subcharts only; upstream +# charts stay pinned). +# - Refreshes the local-subchart entries in SHA256SUMS. +# +# --charts-only skips the operator-image pieces; it needs only perl, so +# the macOS CLI build runners can use it. +set -euo pipefail + +usage() { + echo "usage: $0 [--charts-only]" >&2 + exit 1 +} + +VERSION="${1:-}" +REGISTRY_HOST="${2:-}" +REGISTRY_NAMESPACE="${3:-}" +[ -n "$VERSION" ] && [ -n "$REGISTRY_HOST" ] && [ -n "$REGISTRY_NAMESPACE" ] || usage +CHARTS_ONLY=false +if [ "${4:-}" = "--charts-only" ]; then + CHARTS_ONLY=true +elif [ -n "${4:-}" ]; then + usage +fi + +cd "$(dirname "$0")/.." + +INSTALLER_CHART=installer/charts/educates-installer +UMBRELLA_CHART=installer/charts/educates-training-platform +VENDORED_CHARTS_DIR=installer/operator/vendored-charts +EMBED_GO=$VENDORED_CHARTS_DIR/embed.go +EMBEDDED_CLI_CHART=client-programs/pkg/deployer/chart/files +LOCAL_SUBCHARTS="secrets-manager lookup-service session-manager node-ca-injector remote-access" + +# Maps a subchart name to its version constant in embed.go. +chart_version_const() { + case "$1" in + secrets-manager) echo SecretsManagerChartVersion ;; + lookup-service) echo LookupServiceChartVersion ;; + session-manager) echo SessionManagerChartVersion ;; + node-ca-injector) echo NodeCAInjectorChartVersion ;; + remote-access) echo RemoteAccessChartVersion ;; + *) echo "unknown subchart $1" >&2; exit 1 ;; + esac +} + +# Stamps version, appVersion and (where present) the image-registry +# annotations of one Chart.yaml. Line-level perl keeps this portable +# (no yq on the macOS runners) and preserves comments. +stamp_chart_yaml() { + local file="$1" + perl -pi -e "s|^version: .*|version: ${VERSION}|" "$file" + perl -pi -e "s|^appVersion: .*|appVersion: \"${VERSION}\"|" "$file" + perl -pi -e "s|^(\s+)educates\.dev/image-registry-host: .*|\${1}educates.dev/image-registry-host: \"${REGISTRY_HOST}\"|" "$file" + perl -pi -e "s|^(\s+)educates\.dev/image-registry-namespace: .*|\${1}educates.dev/image-registry-namespace: \"${REGISTRY_NAMESPACE}\"|" "$file" +} + +echo ">> stamping charts to version ${VERSION} (registry ${REGISTRY_HOST}/${REGISTRY_NAMESPACE})" + +stamp_chart_yaml "$INSTALLER_CHART/Chart.yaml" +stamp_chart_yaml "$UMBRELLA_CHART/Chart.yaml" +# The umbrella's only indented `version:` lines are its dependency pins. +perl -pi -e "s|^(\s+)version: .*|\${1}version: ${VERSION}|" "$UMBRELLA_CHART/Chart.yaml" +for name in $LOCAL_SUBCHARTS; do + stamp_chart_yaml "$UMBRELLA_CHART/charts/$name/Chart.yaml" +done + +echo ">> refreshing embedded CLI chart from $INSTALLER_CHART" +rm -rf "$EMBEDDED_CLI_CHART" +mkdir -p "$EMBEDDED_CLI_CHART" +cp -r "$INSTALLER_CHART/." "$EMBEDDED_CLI_CHART/" + +if $CHARTS_ONLY; then + echo ">> --charts-only: skipping operator vendored-charts rebuild" + exit 0 +fi + +echo ">> repackaging runtime subcharts into $VENDORED_CHARTS_DIR" +for name in $LOCAL_SUBCHARTS; do + rm -f "$VENDORED_CHARTS_DIR/$name-"*.tgz + helm package "$UMBRELLA_CHART/charts/$name" --destination "$VENDORED_CHARTS_DIR" >/dev/null + [ -f "$VENDORED_CHARTS_DIR/$name-$VERSION.tgz" ] || { + echo "helm package did not produce $name-$VERSION.tgz" >&2 + exit 1 + } +done + +echo ">> rewriting embed.go filenames and version constants" +for name in $LOCAL_SUBCHARTS; do + const=$(chart_version_const "$name") + perl -pi -e "s|^//go:embed ${name}-.*\.tgz$|//go:embed ${name}-${VERSION}.tgz|" "$EMBED_GO" + perl -pi -e "s|^const ${const} = \".*\"|const ${const} = \"${VERSION}\"|" "$EMBED_GO" +done +# Every //go:embed target must exist on disk or the operator image +# build fails later with a far less obvious error. +while read -r tarball; do + [ -f "$VENDORED_CHARTS_DIR/$tarball" ] || { + echo "embed.go references $tarball but it is missing from $VENDORED_CHARTS_DIR" >&2 + exit 1 + } +done < <(perl -ne 'print "$1\n" if m|^//go:embed (.*\.tgz)$|' "$EMBED_GO") + +echo ">> refreshing local-subchart entries in SHA256SUMS" +sums="$VENDORED_CHARTS_DIR/SHA256SUMS" +tmp=$(mktemp) +cp "$sums" "$tmp" +for name in $LOCAL_SUBCHARTS; do + grep -v " ${name}-" "$tmp" > "$tmp.next" || true + mv "$tmp.next" "$tmp" +done +( + cd "$VENDORED_CHARTS_DIR" + for name in $LOCAL_SUBCHARTS; do + shasum -a 256 "$name-$VERSION.tgz" >> "$tmp" + done +) +mv "$tmp" "$sums" + +echo ">> done" diff --git a/installer/charts/educates-installer/Chart.yaml b/installer/charts/educates-installer/Chart.yaml new file mode 100644 index 000000000..46dc29133 --- /dev/null +++ b/installer/charts/educates-installer/Chart.yaml @@ -0,0 +1,27 @@ +apiVersion: v2 +name: educates-installer +description: | + Educates v4 installer. Installs the four CRDs that drive the v4 + control plane (EducatesClusterConfig, SecretsManager, LookupService, + SessionManager) plus the operator that reconciles them: the operator + installs the cluster services (cert-manager, Contour, Kyverno, + external-dns) in Managed mode and the Educates runtime components. +type: application +# Publish-time default registry for the operator image. The release +# workflow rewrites these per fork (one yq -i call); local overrides go +# through values (image.repository or development.imageRegistry). Keep +# in sync with the educates-training-platform subcharts — see +# decisions.md "imageRegistry is a development override; publish-time +# defaults live in Chart.yaml annotations". +annotations: + educates.dev/image-registry-host: "ghcr.io" + educates.dev/image-registry-namespace: "educates" +version: 4.0.0-alpha.1 +appVersion: 4.0.0-alpha.1 +kubeVersion: ">=1.31.0-0" +home: https://educates.dev +sources: + - https://github.com/jorgemoralespou/educates-training-platform +maintainers: + - name: Educates Maintainers + url: https://github.com/jorgemoralespou/educates-training-platform/blob/develop/MAINTAINERS.md diff --git a/installer/charts/educates-installer/crds/config.educates.dev_educatesclusterconfigs.yaml b/installer/charts/educates-installer/crds/config.educates.dev_educatesclusterconfigs.yaml new file mode 100644 index 000000000..d9ed7185b --- /dev/null +++ b/installer/charts/educates-installer/crds/config.educates.dev_educatesclusterconfigs.yaml @@ -0,0 +1,1158 @@ +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.20.1 + name: educatesclusterconfigs.config.educates.dev +spec: + group: config.educates.dev + names: + kind: EducatesClusterConfig + listKind: EducatesClusterConfigList + plural: educatesclusterconfigs + shortNames: + - ecc + singular: educatesclusterconfig + scope: Cluster + versions: + - additionalPrinterColumns: + - jsonPath: .spec.mode + name: Mode + type: string + - jsonPath: .status.phase + name: Phase + type: string + - jsonPath: .metadata.creationTimestamp + name: Age + type: date + name: v1alpha1 + schema: + openAPIV3Schema: + description: |- + EducatesClusterConfig is the singleton resource describing the + cluster-wide configuration of an Educates installation. + properties: + apiVersion: + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + type: string + kind: + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + metadata: + type: object + spec: + description: |- + EducatesClusterConfigSpec defines the desired state of + EducatesClusterConfig. + + CEL invariants (structural): + - spec.mode is immutable; switching modes requires delete + recreate. + - When mode is Inline, the Managed-mode top-level fields + (infrastructure, ingress, dns, policyEnforcement, imageRegistry) + are forbidden. + - When mode is Managed, spec.inline is forbidden. + properties: + dns: + description: |- + dns configures DNS management in Managed mode; ignored in Inline + mode. + properties: + bundledExternalDNS: + description: |- + BundledExternalDNSConfig configures the operator-installed + external-dns chart. v1alpha1 supports Route53 and CloudDNS; other + providers (Cloudflare, AzureDNS, etc.) surface "not yet supported" + validation errors. + + CEL invariants: + - provider==Route53 requires route53 to be set and forbids cloudDNS. + - provider==CloudDNS requires cloudDNS to be set and forbids route53. + properties: + cloudDNS: + description: |- + ExternalDNSCloudDNSConfig configures the GCP CloudDNS provider for + the operator-installed external-dns. + + Credentials are supplied via *exactly one* of: + - CredentialsSecretRef: a Secret in the operator namespace with + key `credentials.json` containing the GCP service-account + JSON key. + - WorkloadIdentityServiceAccount: a GCP service-account email + bound to the external-dns ServiceAccount via the + `iam.gke.io/gcp-service-account` annotation. Preferred on GKE. + properties: + credentialsSecretRef: + description: |- + LocalObjectReference is a reference to a Kubernetes object by name in + the operator namespace. Cluster-scoped references (e.g., ClusterIssuer, + IngressClass) also use this shape. + properties: + name: + description: name of the referent. + type: string + required: + - name + type: object + project: + type: string + workloadIdentityServiceAccount: + type: string + required: + - project + type: object + provider: + allOf: + - enum: + - Route53 + - CloudDNS + - Cloudflare + - AzureDNS + - enum: + - Route53 + - CloudDNS + description: |- + provider selects which DNS provider external-dns publishes + records to. Reuses the DNS01Provider enum for vocabulary + consistency with cert-manager's solver config; validation + rejects Cloudflare/AzureDNS for now. + type: string + route53: + description: |- + ExternalDNSRoute53Config configures the AWS Route53 provider for + the operator-installed external-dns. HostedZoneID is required to + scope external-dns to a specific zone — running unscoped is a + production footgun (a broad IAM role plus no zone filter can + silently rewrite records across the entire account). + + Credentials are supplied via *exactly one* of: + - CredentialsSecretRef: a Secret in the operator namespace with + keys `aws_access_key_id` and `aws_secret_access_key`. + - IAMRoleARN: an IRSA / Pod Identity role assumed via the + external-dns ServiceAccount's `eks.amazonaws.com/role-arn` + annotation. Preferred on EKS. + + CEL elsewhere enforces the exactly-one rule; the operator + validator backs it up with a friendlier error message. + properties: + credentialsSecretRef: + description: |- + LocalObjectReference is a reference to a Kubernetes object by name in + the operator namespace. Cluster-scoped references (e.g., ClusterIssuer, + IngressClass) also use this shape. + properties: + name: + description: name of the referent. + type: string + required: + - name + type: object + hostedZoneID: + type: string + iamRoleARN: + type: string + region: + description: |- + region defaults to the AWS SDK's default detection (pod IMDS + / env vars). Set explicitly when running outside AWS or in + air-gapped environments. + type: string + required: + - hostedZoneID + type: object + sources: + default: + - service + description: |- + sources controls which Kubernetes kinds external-dns watches + for hostname records. Defaults to ["service"] because Educates + publishes the wildcard via an annotation on the Envoy Service. + Users can broaden to ["service","ingress"] (or any + chart-accepted source) when they want per-workshop Ingress + records published as well. + items: + type: string + type: array + required: + - provider + type: object + x-kubernetes-validations: + - message: provider Route53 requires spec.dns.bundledExternalDNS.route53 + and forbids cloudDNS + rule: self.provider != 'Route53' || (has(self.route53) && !has(self.cloudDNS)) + - message: provider CloudDNS requires spec.dns.bundledExternalDNS.cloudDNS + and forbids route53 + rule: self.provider != 'CloudDNS' || (has(self.cloudDNS) && + !has(self.route53)) + provider: + default: None + description: |- + provider defaults to None — appropriate for local clusters using + nip.io or hosts-file resolution. Cloud installs must set this + explicitly. + enum: + - BundledExternalDNS + - Manual + - None + type: string + type: object + imageRegistry: + description: |- + imageRegistry rewrites bundled chart image refs and supplies pull + credentials. Applies in Managed mode (Inline mode has its own + equivalent under spec.inline.imageRegistry). + properties: + prefix: + description: |- + prefix rewrites every bundled image reference to live under this + prefix, e.g., "internal-registry.corp.local/educates". Pre-relocated + bundles (via helm dt wrap/unwrap) do not need this set. + type: string + pullSecrets: + description: |- + pullSecrets references kubernetes.io/dockerconfigjson Secrets in + the operator namespace. + items: + description: |- + LocalObjectReference is a reference to a Kubernetes object by name in + the operator namespace. Cluster-scoped references (e.g., ClusterIssuer, + IngressClass) also use this shape. + properties: + name: + description: name of the referent. + type: string + required: + - name + type: object + type: array + type: object + infrastructure: + description: |- + infrastructure describes the cluster substrate. Used in Managed + mode; ignored in Inline mode. + properties: + cloud: + description: |- + cloud carries provider-specific configuration. Required for cloud + providers (EKS, GKE) when bundled cert-manager or external-dns is + enabled. + properties: + project: + description: |- + project / account identifier, e.g., GCP project ID or AWS account + alias. + type: string + region: + type: string + serviceAccounts: + description: |- + CloudServiceAccounts maps Educates' bundled cluster services to + provider-native workload identities. + properties: + certManager: + description: |- + certManager identity used by cert-manager when requesting + DNS01-validated certificates. + type: string + externalDNS: + description: |- + externalDNS identity used by external-dns when managing DNS + records. + type: string + type: object + type: object + provider: + description: |- + InfrastructureProvider identifies the underlying cluster substrate. + Used by the operator to compute provider-specific defaults and to + validate cloud-related fields. + enum: + - Kind + - Minikube + - EKS + - GKE + - OpenShift + - VCluster + - Generic + type: string + required: + - provider + type: object + ingress: + description: |- + ingress configures the Educates ingress in Managed mode; ignored + in Inline mode. + properties: + certificates: + description: Certificates groups certificate-provider configuration. + properties: + bundledCertManager: + description: |- + BundledCertManagerConfig configures the operator-installed cert-manager + chart and the ClusterIssuer it provides. + properties: + acme: + description: ACMEConfig configures the cert-manager ACME + ClusterIssuer. + properties: + email: + type: string + server: + description: |- + server is the ACME directory URL. Defaults to Let's Encrypt + production. Override for Let's Encrypt staging or another CA. + type: string + solvers: + description: |- + ACMESolvers groups the cert-manager solvers used to satisfy the ACME + challenge. + properties: + dns01: + description: dns01 is required for wildcard issuance. + properties: + azureDNS: + description: AzureDNSConfig configures the + Azure DNS DNS01 solver. + properties: + resourceGroup: + type: string + subscriptionID: + type: string + required: + - resourceGroup + - subscriptionID + type: object + cloudDNS: + description: |- + CloudDNSConfig configures the cert-manager GCP CloudDNS DNS01 + solver and the GCP-side credentials. + + Credentials must be supplied via *exactly one* mechanism: + - WorkloadIdentityServiceAccount: a GCP service-account email + bound to cert-manager's K8s ServiceAccount via the + `iam.gke.io/gcp-service-account` annotation. Recommended on + GKE. + - CredentialsSecretRef: a Secret in the operator namespace + with key `credentials.json` containing a GCP service-account + JSON key. v1alpha1 reserves the field but rejects it as + "not yet supported"; static-creds support is a follow-up. + properties: + credentialsSecretRef: + description: |- + LocalObjectReference is a reference to a Kubernetes object by name in + the operator namespace. Cluster-scoped references (e.g., ClusterIssuer, + IngressClass) also use this shape. + properties: + name: + description: name of the referent. + type: string + required: + - name + type: object + project: + type: string + workloadIdentityServiceAccount: + type: string + zone: + type: string + required: + - project + type: object + cloudflare: + description: CloudflareConfig configures the + Cloudflare DNS01 solver. + properties: + apiTokenSecretRef: + description: |- + apiTokenSecretRef references a Secret holding the Cloudflare API + token. The default key is "api-token". + properties: + key: + description: key within the Secret. + Defaults vary by use site. + type: string + name: + description: name of the Secret. + type: string + required: + - name + type: object + required: + - apiTokenSecretRef + type: object + provider: + description: |- + DNS01Provider names a cert-manager DNS01 solver. Required for wildcard + certificate issuance via ACME. + enum: + - Route53 + - CloudDNS + - Cloudflare + - AzureDNS + type: string + route53: + description: |- + Route53Config configures the cert-manager Route53 DNS01 solver + and the AWS-side credentials it needs to write TXT records during + ACME challenges. + + Credentials must be supplied via *exactly one* mechanism: + - IAMRoleARN: marks cert-manager's ServiceAccount with an + `eks.amazonaws.com/role-arn` annotation; cert-manager assumes + the role via IRSA / Pod Identity. Recommended on EKS. + - CredentialsSecretRef: a Secret in the operator namespace + with keys `aws_access_key_id` + `aws_secret_access_key`. + v1alpha1 reserves the field but rejects it as "not yet + supported"; static-creds support is a follow-up. + + CEL elsewhere enforces the mutual-exclusivity rule; the + operator validator backs it up with a friendlier message. + properties: + credentialsSecretRef: + description: |- + LocalObjectReference is a reference to a Kubernetes object by name in + the operator namespace. Cluster-scoped references (e.g., ClusterIssuer, + IngressClass) also use this shape. + properties: + name: + description: name of the referent. + type: string + required: + - name + type: object + hostedZoneID: + type: string + iamRoleARN: + type: string + region: + type: string + required: + - hostedZoneID + type: object + required: + - provider + type: object + http01: + description: |- + ACMEHTTP01Solver configures the optional HTTP01 solver. Rarely needed + because DNS01 is required for wildcards. + properties: + ingressClassName: + description: |- + ingressClassName defaults to spec.ingress.ingressClassName when + unset. + type: string + type: object + required: + - dns01 + type: object + required: + - email + - solvers + type: object + customCA: + description: CustomCAConfig configures a self-signed/custom + CA-backed ClusterIssuer. + properties: + caCertificateRef: + description: |- + caCertificateRef references a Secret holding the CA's own cert and + key (keys: tls.crt, tls.key). Namespace defaults to the operator + namespace when empty. + properties: + name: + description: name of the referent. + type: string + namespace: + description: namespace of the referent. Empty + means the operator namespace. + type: string + required: + - name + type: object + required: + - caCertificateRef + type: object + issuerType: + description: |- + IssuerType selects the cert-manager ClusterIssuer flavour for the + BundledCertManager provider. + enum: + - ACME + - CustomCA + type: string + required: + - issuerType + type: object + externalCertManager: + description: |- + ExternalCertManagerConfig assumes cert-manager is already installed + and references an existing ClusterIssuer; the operator only creates + the wildcard Certificate. + properties: + clusterIssuerRef: + description: |- + LocalObjectReference is a reference to a Kubernetes object by name in + the operator namespace. Cluster-scoped references (e.g., ClusterIssuer, + IngressClass) also use this shape. + properties: + name: + description: name of the referent. + type: string + required: + - name + type: object + required: + - clusterIssuerRef + type: object + provider: + description: |- + CertificatesProvider selects how the wildcard TLS certificate is + provisioned. + enum: + - BundledCertManager + - ExternalCertManager + - StaticCertificate + type: string + staticCertificate: + description: |- + StaticCertificateConfig declares a pre-provisioned wildcard TLS + certificate; no cert-manager is involved. + properties: + caCertificateRef: + description: |- + caCertificateRef optionally references a Secret with the ca.crt + key for the issuing CA chain. + properties: + name: + description: name of the referent. + type: string + required: + - name + type: object + tlsSecretRef: + description: |- + tlsSecretRef references a kubernetes.io/tls Secret with keys + tls.crt and tls.key. + properties: + name: + description: name of the referent. + type: string + required: + - name + type: object + required: + - tlsSecretRef + type: object + required: + - provider + type: object + controller: + description: IngressController groups ingress-controller configuration. + properties: + bundledContour: + description: |- + BundledContourConfig configures the operator-installed Contour ingress + controller. + properties: + envoyServiceType: + default: LoadBalancer + description: |- + envoyServiceType selects the Kubernetes Service type for the + Envoy DaemonSet. Defaults to LoadBalancer so cloud-provider + installs (EKS, GKE, AKS, OpenShift) work out of the box; + set explicitly to NodePort on kind / minikube / vCluster + installs where no in-cluster LoadBalancer controller exists. + enum: + - LoadBalancer + - NodePort + - ClusterIP + type: string + operational: + description: |- + OperationalBlock collects the per-Deployment operational knobs of a + Bundled cluster service. In v1alpha1 only BundledContour carries it: + the cert-manager / external-dns / kyverno blocks were dropped + (2026-06-11) because their semantics didn't hold against the + upstream charts — external-dns 1.21.1 hardcodes replicas to 1 and + exposes no replica value, Kyverno fanning one count across its four + controllers conflicts with upstream HA guidance (3+ for the + admission controller only), and cert-manager never consumed it. + They return when per-service shapes are validated against each + chart's real values surface. Of the knobs below, the reconciler + currently applies replicas; the rest are accepted but not yet + wired into chart values. + properties: + nodeSelector: + additionalProperties: + type: string + type: object + podAnnotations: + additionalProperties: + type: string + type: object + podLabels: + additionalProperties: + type: string + type: object + priorityClassName: + type: string + replicas: + description: |- + replicas overrides the operator-computed default. The default + varies by infrastructure provider (typically 1 for Kind/Minikube, + 2+ otherwise). + format: int32 + minimum: 0 + type: integer + resources: + description: ResourceRequirements describes the compute + resource requirements. + properties: + claims: + description: |- + Claims lists the names of resources, defined in spec.resourceClaims, + that are used by this container. + + This field depends on the + DynamicResourceAllocation feature gate. + + This field is immutable. It can only be set for containers. + items: + description: ResourceClaim references one entry + in PodSpec.ResourceClaims. + properties: + name: + description: |- + Name must match the name of one entry in pod.spec.resourceClaims of + the Pod where this field is used. It makes that resource available + inside a container. + type: string + request: + description: |- + Request is the name chosen for a request in the referenced claim. + If empty, everything from the claim is made available, otherwise + only the result of this request. + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: |- + Limits describes the maximum amount of compute resources allowed. + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: |- + Requests describes the minimum amount of compute resources required. + If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, + otherwise to an implementation-defined value. Requests cannot exceed Limits. + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ + type: object + type: object + tolerations: + items: + description: |- + The pod this Toleration is attached to tolerates any taint that matches + the triple using the matching operator . + properties: + effect: + description: |- + Effect indicates the taint effect to match. Empty means match all taint effects. + When specified, allowed values are NoSchedule, PreferNoSchedule and NoExecute. + type: string + key: + description: |- + Key is the taint key that the toleration applies to. Empty means match all taint keys. + If the key is empty, operator must be Exists; this combination means to match all values and all keys. + type: string + operator: + description: |- + Operator represents a key's relationship to the value. + Valid operators are Exists, Equal, Lt, and Gt. Defaults to Equal. + Exists is equivalent to wildcard for value, so that a pod can + tolerate all taints of a particular category. + Lt and Gt perform numeric comparisons (requires feature gate TaintTolerationComparisonOperators). + type: string + tolerationSeconds: + description: |- + TolerationSeconds represents the period of time the toleration (which must be + of effect NoExecute, otherwise this field is ignored) tolerates the taint. By default, + it is not set, which means tolerate the taint forever (do not evict). Zero and + negative values will be treated as 0 (evict immediately) by the system. + format: int64 + type: integer + value: + description: |- + Value is the taint value the toleration matches to. + If the operator is Exists, the value should be empty, otherwise just a regular string. + type: string + type: object + type: array + type: object + type: object + provider: + description: |- + IngressControllerProvider selects how the cluster's ingress controller + is provided. + enum: + - BundledContour + - ExternalIngressController + type: string + required: + - provider + type: object + domain: + description: |- + domain is the wildcard subdomain under which Educates serves + workshops, e.g., "educates.example.com". + type: string + ingressClassName: + description: |- + ingressClassName names the IngressClass used by Educates. In + BundledContour mode the operator creates an IngressClass with + this name; in External mode it must already exist. + type: string + required: + - certificates + - controller + - domain + - ingressClassName + type: object + inline: + description: |- + inline declares pre-existing cluster resources. Used in Inline + mode; ignored in Managed mode. + properties: + imageRegistry: + description: |- + ImageRegistry configures registry rewriting and pull credentials. + Applies to all bundled charts in Managed mode and to the runtime in + both modes. + properties: + prefix: + description: |- + prefix rewrites every bundled image reference to live under this + prefix, e.g., "internal-registry.corp.local/educates". Pre-relocated + bundles (via helm dt wrap/unwrap) do not need this set. + type: string + pullSecrets: + description: |- + pullSecrets references kubernetes.io/dockerconfigjson Secrets in + the operator namespace. + items: + description: |- + LocalObjectReference is a reference to a Kubernetes object by name in + the operator namespace. Cluster-scoped references (e.g., ClusterIssuer, + IngressClass) also use this shape. + properties: + name: + description: name of the referent. + type: string + required: + - name + type: object + type: array + type: object + ingress: + description: |- + InlineIngress declares pre-existing ingress resources for Inline + mode. The operator validates these and republishes them in status. + properties: + caCertificateSecretRef: + description: |- + caCertificateSecretRef references a Secret with the ca.crt key + for the issuing CA chain. Optional. + properties: + name: + description: name of the referent. + type: string + namespace: + description: namespace of the referent. Empty means the + operator namespace. + type: string + required: + - name + type: object + clusterIssuerRef: + description: |- + clusterIssuerRef references an existing ClusterIssuer that must be + Ready. Optional; informational for components. + properties: + name: + description: name of the referent. + type: string + required: + - name + type: object + domain: + type: string + ingressClassName: + type: string + wildcardCertificateSecretRef: + description: |- + wildcardCertificateSecretRef references a kubernetes.io/tls Secret + with keys tls.crt and tls.key, valid for *.. + properties: + name: + description: name of the referent. + type: string + required: + - name + type: object + required: + - domain + - ingressClassName + - wildcardCertificateSecretRef + type: object + policyEnforcement: + description: |- + InlinePolicyEnforcement declares the policy engines already in place + for Inline mode. Enforced engines are identified, not installed. + properties: + clusterPolicyEngine: + description: ClusterPolicyEngine names the cluster-wide policy + enforcement engine. + enum: + - Kyverno + - PodSecurityStandards + - OpenShiftSCC + - None + type: string + workshopPolicyEngine: + description: |- + WorkshopPolicyEngine names the engine enforcing per-workshop isolation + rules. Setting to None disables workshop isolation. + enum: + - Kyverno + - None + type: string + required: + - clusterPolicyEngine + - workshopPolicyEngine + type: object + required: + - ingress + - policyEnforcement + type: object + mode: + description: |- + ClusterConfigMode selects between operator-managed and user-declared + cluster infrastructure. Immutable once set; switching modes requires + deleting and recreating the resource. + enum: + - Managed + - Inline + type: string + policyEnforcement: + description: |- + policyEnforcement configures the cluster and workshop policy + engines in Managed mode; ignored in Inline mode. + properties: + clusterPolicy: + description: ClusterPolicyConfig configures the cluster-wide policy + engine. + properties: + engine: + default: Kyverno + description: engine defaults to Kyverno. + enum: + - Kyverno + - PodSecurityStandards + - OpenShiftSCC + - None + type: string + type: object + kyverno: + description: kyverno is required when either engine above resolves + to Kyverno. + properties: + provider: + default: Bundled + description: provider defaults to Bundled. + enum: + - Bundled + - External + type: string + type: object + workshopPolicy: + description: WorkshopPolicyConfig configures the per-workshop + isolation engine. + properties: + engine: + default: Kyverno + description: |- + engine defaults to Kyverno. Setting to None disables workshop + isolation; the cluster operator takes responsibility for + containment. + enum: + - Kyverno + - None + type: string + type: object + required: + - clusterPolicy + - workshopPolicy + type: object + required: + - mode + type: object + x-kubernetes-validations: + - message: spec.mode is immutable; delete and recreate the resource to + switch modes + rule: self.mode == oldSelf.mode + - message: spec.{infrastructure,ingress,dns,policyEnforcement,imageRegistry} + are forbidden when mode is Inline + rule: self.mode != 'Inline' || (!has(self.infrastructure) && !has(self.ingress) + && !has(self.dns) && !has(self.policyEnforcement) && !has(self.imageRegistry)) + - message: spec.inline is forbidden when mode is Managed + rule: self.mode != 'Managed' || !has(self.inline) + status: + description: |- + EducatesClusterConfigStatus is the public interface that component CRs + (SecretsManager, LookupService, SessionManager) consume. Phase 1 adds + the inter-CR contract fields (mode, ingress, policyEnforcement, + imageRegistry); the bundledChartVersions field lands in Phase 2/3 + alongside Managed-mode chart installs. + properties: + bundledChartVersions: + additionalProperties: + type: string + description: |- + bundledChartVersions records the version of each upstream Helm + chart the operator has installed in Managed mode. Keys are the + upstream chart names (e.g., "cert-manager", "contour"); values are + the chart's appVersion. Populated as charts are installed; absent + in Inline mode. + type: object + conditions: + description: |- + conditions report the resource's state. Phase 1 publishes: + - Ready (aggregate) + - ValidationSucceeded (Inline mode: refs validated) + Managed-mode conditions (IngressReady, CertificatesReady, + DNSReady, PolicyEnforcementReady, InfrastructureConfigured) land + in later phases alongside their producing reconcilers. + items: + description: Condition contains details for one aspect of the current + state of this API Resource. + properties: + lastTransitionTime: + description: |- + lastTransitionTime is the last time the condition transitioned from one status to another. + This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable. + format: date-time + type: string + message: + description: |- + message is a human readable message indicating details about the transition. + This may be an empty string. + maxLength: 32768 + type: string + observedGeneration: + description: |- + observedGeneration represents the .metadata.generation that the condition was set based upon. + For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date + with respect to the current state of the instance. + format: int64 + minimum: 0 + type: integer + reason: + description: |- + reason contains a programmatic identifier indicating the reason for the condition's last transition. + Producers of specific condition types may define expected values and meanings for this field, + and whether the values are considered a guaranteed API. + The value should be a CamelCase string. + This field may not be empty. + maxLength: 1024 + minLength: 1 + pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ + type: string + status: + description: status of the condition, one of True, False, Unknown. + enum: + - "True" + - "False" + - Unknown + type: string + type: + description: type of condition in CamelCase or in foo.example.com/CamelCase. + maxLength: 316 + pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ + type: string + required: + - lastTransitionTime + - message + - reason + - status + - type + type: object + type: array + x-kubernetes-list-map-keys: + - type + x-kubernetes-list-type: map + imageRegistry: + description: |- + imageRegistry publishes the rewriting prefix and pull secrets, if + configured. Always populated when reconciliation succeeds; an + empty prefix and empty pullSecrets means no rewriting is in effect. + properties: + prefix: + description: |- + prefix rewrites every bundled image reference to live under this + prefix, e.g., "internal-registry.corp.local/educates". Pre-relocated + bundles (via helm dt wrap/unwrap) do not need this set. + type: string + pullSecrets: + description: |- + pullSecrets references kubernetes.io/dockerconfigjson Secrets in + the operator namespace. + items: + description: |- + LocalObjectReference is a reference to a Kubernetes object by name in + the operator namespace. Cluster-scoped references (e.g., ClusterIssuer, + IngressClass) also use this shape. + properties: + name: + description: name of the referent. + type: string + required: + - name + type: object + type: array + type: object + ingress: + description: |- + ingress publishes the validated ingress contract for components to + consume. Populated once validation succeeds. + properties: + caCertificateSecretRef: + description: caCertificateSecretRef is set when a CA Secret is + configured. + properties: + name: + type: string + namespace: + type: string + required: + - name + - namespace + type: object + clusterIssuerRef: + description: |- + clusterIssuerRef names a cluster-wide ClusterIssuer when one was + configured. Components use this informationally; nothing in the + status pipeline depends on it. + properties: + name: + description: name of the referent. + type: string + required: + - name + type: object + domain: + type: string + ingressClassName: + type: string + wildcardCertificateSecretRef: + description: |- + wildcardCertificateSecretRef points at the operator-namespace + Secret holding the wildcard cert+key. + properties: + name: + type: string + namespace: + type: string + required: + - name + - namespace + type: object + required: + - domain + - ingressClassName + - wildcardCertificateSecretRef + type: object + mode: + description: |- + mode echoes spec.mode at the time of last successful reconcile. + Components can branch on this without reading spec. + enum: + - Managed + - Inline + type: string + observedGeneration: + description: observedGeneration tracks the spec generation last reconciled. + format: int64 + type: integer + phase: + description: |- + phase is an advisory summary of the operator's current activity on + this resource; conditions carry the authoritative state. + enum: + - Pending + - Installing + - Validating + - Ready + - Degraded + - Uninstalling + type: string + policyEnforcement: + description: policyEnforcement publishes the resolved policy engines. + properties: + clusterPolicyEngine: + description: ClusterPolicyEngine names the cluster-wide policy + enforcement engine. + enum: + - Kyverno + - PodSecurityStandards + - OpenShiftSCC + - None + type: string + workshopPolicyEngine: + description: |- + WorkshopPolicyEngine names the engine enforcing per-workshop isolation + rules. Setting to None disables workshop isolation. + enum: + - Kyverno + - None + type: string + required: + - clusterPolicyEngine + - workshopPolicyEngine + type: object + type: object + required: + - spec + type: object + x-kubernetes-validations: + - message: EducatesClusterConfig must be named 'cluster' (singleton per cluster) + rule: self.metadata.name == 'cluster' + served: true + storage: true + subresources: + status: {} diff --git a/installer/charts/educates-installer/crds/platform.educates.dev_lookupservices.yaml b/installer/charts/educates-installer/crds/platform.educates.dev_lookupservices.yaml new file mode 100644 index 000000000..092e09e13 --- /dev/null +++ b/installer/charts/educates-installer/crds/platform.educates.dev_lookupservices.yaml @@ -0,0 +1,283 @@ +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.20.1 + name: lookupservices.platform.educates.dev +spec: + group: platform.educates.dev + names: + kind: LookupService + listKind: LookupServiceList + plural: lookupservices + singular: lookupservice + scope: Cluster + versions: + - additionalPrinterColumns: + - jsonPath: .status.phase + name: Phase + type: string + - jsonPath: .metadata.creationTimestamp + name: Age + type: date + name: v1alpha1 + schema: + openAPIV3Schema: + description: |- + LookupService is the singleton resource that drives installation of + the lookup-service component. + properties: + apiVersion: + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + type: string + kind: + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + metadata: + type: object + spec: + description: |- + LookupServiceSpec defines the desired state of LookupService. + + Component-specific settings (auth, rate-limiting, storage) will be + added when the lookup-service owner specifies them; intentionally + out-of-scope for the v1alpha1 surface. + properties: + image: + description: |- + ImageRef declares a chart-render-time image override as a separable + repository + tag pair. The split shape matches what helm dt + wrap/unwrap (and similar relocation tools) expect. + properties: + repository: + type: string + tag: + type: string + type: object + ingress: + description: LookupServiceIngress configures the lookup-service Ingress. + properties: + prefix: + description: |- + prefix combines with EducatesClusterConfig.status.ingress.domain + to form the full hostname (e.g., "educates-api" with domain + "educates.example.com" yields "educates-api.educates.example.com"). + type: string + tlsSecretRef: + description: |- + tlsSecretRef optionally overrides the cluster wildcard + certificate. When unset, the ingress uses + EducatesClusterConfig.status.ingress.wildcardCertificateSecretRef. + properties: + name: + description: name of the referent. + type: string + required: + - name + type: object + required: + - prefix + type: object + logLevel: + default: info + description: logLevel defaults to info. + enum: + - debug + - info + - warn + - error + type: string + resources: + description: ResourceRequirements describes the compute resource requirements. + properties: + claims: + description: |- + Claims lists the names of resources, defined in spec.resourceClaims, + that are used by this container. + + This field depends on the + DynamicResourceAllocation feature gate. + + This field is immutable. It can only be set for containers. + items: + description: ResourceClaim references one entry in PodSpec.ResourceClaims. + properties: + name: + description: |- + Name must match the name of one entry in pod.spec.resourceClaims of + the Pod where this field is used. It makes that resource available + inside a container. + type: string + request: + description: |- + Request is the name chosen for a request in the referenced claim. + If empty, everything from the claim is made available, otherwise + only the result of this request. + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: |- + Limits describes the maximum amount of compute resources allowed. + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: |- + Requests describes the minimum amount of compute resources required. + If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, + otherwise to an implementation-defined value. Requests cannot exceed Limits. + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ + type: object + type: object + required: + - ingress + type: object + status: + description: |- + LookupServiceStatus defines the observed state of LookupService. + Phase 4 publishes the full CRD draft r3 §3 contract: phase + + conditions + url + installedVersion + deploymentRef. + properties: + conditions: + description: |- + conditions report the resource's state. Phase 4 publishes: + - Ready (aggregate) + - ClusterConfigAvailable (EducatesClusterConfig.Ready gate) + - Deployed (helm release + Deployment Available) + items: + description: Condition contains details for one aspect of the current + state of this API Resource. + properties: + lastTransitionTime: + description: |- + lastTransitionTime is the last time the condition transitioned from one status to another. + This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable. + format: date-time + type: string + message: + description: |- + message is a human readable message indicating details about the transition. + This may be an empty string. + maxLength: 32768 + type: string + observedGeneration: + description: |- + observedGeneration represents the .metadata.generation that the condition was set based upon. + For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date + with respect to the current state of the instance. + format: int64 + minimum: 0 + type: integer + reason: + description: |- + reason contains a programmatic identifier indicating the reason for the condition's last transition. + Producers of specific condition types may define expected values and meanings for this field, + and whether the values are considered a guaranteed API. + The value should be a CamelCase string. + This field may not be empty. + maxLength: 1024 + minLength: 1 + pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ + type: string + status: + description: status of the condition, one of True, False, Unknown. + enum: + - "True" + - "False" + - Unknown + type: string + type: + description: type of condition in CamelCase or in foo.example.com/CamelCase. + maxLength: 316 + pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ + type: string + required: + - lastTransitionTime + - message + - reason + - status + - type + type: object + type: array + x-kubernetes-list-map-keys: + - type + x-kubernetes-list-type: map + deploymentRef: + description: |- + deploymentRef names the upstream Deployment the operator is + gating Ready on. Stable across reconciles. + properties: + name: + type: string + namespace: + type: string + required: + - name + - namespace + type: object + installedVersion: + description: |- + installedVersion records the lookup-service chart version most + recently applied. + type: string + observedGeneration: + format: int64 + type: integer + phase: + description: |- + ComponentPhase summarises the operator's current activity on a + platform component. Phases are advisory; conditions carry the + authoritative state. + enum: + - Pending + - Installing + - Ready + - Degraded + - Uninstalling + type: string + url: + description: |- + url is the fully-qualified URL the lookup-service Ingress is + reachable at. Composed from spec.ingress.prefix and + EducatesClusterConfig.status.ingress.domain. Always https in + v1alpha1 (the operator always requires a wildcard TLS Secret + on the cluster config). + type: string + type: object + required: + - spec + type: object + x-kubernetes-validations: + - message: LookupService must be named 'cluster' (singleton per cluster) + rule: self.metadata.name == 'cluster' + served: true + storage: true + subresources: + status: {} diff --git a/installer/charts/educates-installer/crds/platform.educates.dev_secretsmanagers.yaml b/installer/charts/educates-installer/crds/platform.educates.dev_secretsmanagers.yaml new file mode 100644 index 000000000..5ee9f4c0e --- /dev/null +++ b/installer/charts/educates-installer/crds/platform.educates.dev_secretsmanagers.yaml @@ -0,0 +1,255 @@ +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.20.1 + name: secretsmanagers.platform.educates.dev +spec: + group: platform.educates.dev + names: + kind: SecretsManager + listKind: SecretsManagerList + plural: secretsmanagers + singular: secretsmanager + scope: Cluster + versions: + - additionalPrinterColumns: + - jsonPath: .status.phase + name: Phase + type: string + - jsonPath: .metadata.creationTimestamp + name: Age + type: date + name: v1alpha1 + schema: + openAPIV3Schema: + description: |- + SecretsManager is the singleton resource that drives installation of + the secrets-manager component. + properties: + apiVersion: + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + type: string + kind: + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + metadata: + type: object + spec: + description: |- + SecretsManagerSpec defines the desired state of SecretsManager. + + secrets-manager is a singleton at the pod level (the upstream + implementation can't scale beyond one replica) so no replicas knob is + exposed. Image-pull credentials are inherited from + EducatesClusterConfig.status.imageRegistry.pullSecrets and are not + duplicated here. + properties: + image: + description: |- + image overrides the default image reference. Both fields are + optional; defaults come from the chart's appVersion-derived + image inventory. + properties: + repository: + type: string + tag: + type: string + type: object + logLevel: + default: info + description: logLevel defaults to info. + enum: + - debug + - info + - warn + - error + type: string + resources: + description: ResourceRequirements describes the compute resource requirements. + properties: + claims: + description: |- + Claims lists the names of resources, defined in spec.resourceClaims, + that are used by this container. + + This field depends on the + DynamicResourceAllocation feature gate. + + This field is immutable. It can only be set for containers. + items: + description: ResourceClaim references one entry in PodSpec.ResourceClaims. + properties: + name: + description: |- + Name must match the name of one entry in pod.spec.resourceClaims of + the Pod where this field is used. It makes that resource available + inside a container. + type: string + request: + description: |- + Request is the name chosen for a request in the referenced claim. + If empty, everything from the claim is made available, otherwise + only the result of this request. + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: |- + Limits describes the maximum amount of compute resources allowed. + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: |- + Requests describes the minimum amount of compute resources required. + If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, + otherwise to an implementation-defined value. Requests cannot exceed Limits. + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ + type: object + type: object + type: object + status: + description: |- + SecretsManagerStatus defines the observed state of SecretsManager. + Mirrors the CRD draft r3 §2 status contract: phase + conditions + (aggregate Ready plus ClusterConfigAvailable + Deployed), plus the + installedVersion / deploymentRef pair that downstream tooling can + observe to discover the runtime install. + properties: + conditions: + description: |- + conditions report the resource's state. Phase 4 publishes: + - Ready (aggregate) + - ClusterConfigAvailable (EducatesClusterConfig.Ready gate) + - Deployed (helm release present + Deployment Available) + items: + description: Condition contains details for one aspect of the current + state of this API Resource. + properties: + lastTransitionTime: + description: |- + lastTransitionTime is the last time the condition transitioned from one status to another. + This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable. + format: date-time + type: string + message: + description: |- + message is a human readable message indicating details about the transition. + This may be an empty string. + maxLength: 32768 + type: string + observedGeneration: + description: |- + observedGeneration represents the .metadata.generation that the condition was set based upon. + For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date + with respect to the current state of the instance. + format: int64 + minimum: 0 + type: integer + reason: + description: |- + reason contains a programmatic identifier indicating the reason for the condition's last transition. + Producers of specific condition types may define expected values and meanings for this field, + and whether the values are considered a guaranteed API. + The value should be a CamelCase string. + This field may not be empty. + maxLength: 1024 + minLength: 1 + pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ + type: string + status: + description: status of the condition, one of True, False, Unknown. + enum: + - "True" + - "False" + - Unknown + type: string + type: + description: type of condition in CamelCase or in foo.example.com/CamelCase. + maxLength: 316 + pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ + type: string + required: + - lastTransitionTime + - message + - reason + - status + - type + type: object + type: array + x-kubernetes-list-map-keys: + - type + x-kubernetes-list-type: map + deploymentRef: + description: |- + deploymentRef names the upstream Deployment the operator is + gating Ready on. Stable across reconciles; populated once the + helm install lands. + properties: + name: + type: string + namespace: + type: string + required: + - name + - namespace + type: object + installedVersion: + description: |- + installedVersion records the secrets-manager chart version the + operator most recently applied. Reads back from the embedded + chart's metadata; mirrors what `helm get values` would show. + type: string + observedGeneration: + format: int64 + type: integer + phase: + description: |- + ComponentPhase summarises the operator's current activity on a + platform component. Phases are advisory; conditions carry the + authoritative state. + enum: + - Pending + - Installing + - Ready + - Degraded + - Uninstalling + type: string + type: object + required: + - spec + type: object + x-kubernetes-validations: + - message: SecretsManager must be named 'cluster' (singleton per cluster) + rule: self.metadata.name == 'cluster' + served: true + storage: true + subresources: + status: {} diff --git a/installer/charts/educates-installer/crds/platform.educates.dev_sessionmanagers.yaml b/installer/charts/educates-installer/crds/platform.educates.dev_sessionmanagers.yaml new file mode 100644 index 000000000..06862d08f --- /dev/null +++ b/installer/charts/educates-installer/crds/platform.educates.dev_sessionmanagers.yaml @@ -0,0 +1,523 @@ +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.20.1 + name: sessionmanagers.platform.educates.dev +spec: + group: platform.educates.dev + names: + kind: SessionManager + listKind: SessionManagerList + plural: sessionmanagers + singular: sessionmanager + scope: Cluster + versions: + - additionalPrinterColumns: + - jsonPath: .status.phase + name: Phase + type: string + - jsonPath: .metadata.creationTimestamp + name: Age + type: date + name: v1alpha1 + schema: + openAPIV3Schema: + description: |- + SessionManager is the singleton resource that drives installation of + the session-manager component (with training-portal, + assets-server, image-cache, and supporting services). + properties: + apiVersion: + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + type: string + kind: + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + metadata: + type: object + spec: + description: |- + SessionManagerSpec defines the desired state of SessionManager. + + Requires SecretsManager.Ready and EducatesClusterConfig.Ready; both + dependencies are singletons so no explicit refs are carried. + + Image registry prefix and pull secrets are inherited from + EducatesClusterConfig.status.imageRegistry; only per-image overrides + land in spec.images.overrides. + properties: + allowedEmbeddingHosts: + description: |- + allowedEmbeddingHosts lists hosts allowed to embed Educates + workshop frames (CSP frame-ancestors). + items: + type: string + type: array + defaultAccessCredentials: + description: |- + DefaultAccessCredentials configures the default + username/password used for workshop access when a TrainingPortal + doesn't override them. + properties: + passwordSecretRef: + description: passwordSecretRef references a Secret holding the + password value. + properties: + name: + description: name of the referent. + type: string + required: + - name + type: object + username: + type: string + type: object + defaultTheme: + description: |- + defaultTheme names the entry from themes used as the install-wide + default. Must match a Theme.name. + type: string + imagePrePuller: + description: |- + ImagePrePuller configures the optional DaemonSet that pre-pulls workshop + images onto every node ahead of time, so session startup isn't blocked on + image pulls. + properties: + enabled: + default: false + type: boolean + type: object + images: + description: |- + Images groups image-related overrides. Registry prefix and pull + secrets are inherited from + EducatesClusterConfig.status.imageRegistry; only per-image overrides + belong here. + properties: + overrides: + items: + description: |- + ImageOverride entries replace one chart-default image by short name. + Mirrors the v3 imageVersions shape: any image the chart's default + inventory exposes by name can be overridden here (e.g., + "training-portal", "base-environment", "jdk17-environment"). Three + names are special-cased by the reconciler because they live outside + that inventory: "session-manager" (the chart-pod image), + "pause-container" (the pre-puller pause image) and + "node-ca-injector" (its own subchart) — they route to the dedicated + chart values that control those images. + properties: + image: + description: |- + image is the full reference including tag. Digest-pinned + references are not supported for the special-cased names + ("session-manager", "pause-container", "node-ca-injector"), + whose chart values are repository+tag shaped. + type: string + name: + description: |- + name is the image's short name, e.g. "session-manager", + "training-portal", "jdk17-environment". + type: string + required: + - image + - name + type: object + type: array + type: object + ingressOverrides: + description: |- + IngressOverrides allows SessionManager to override the cluster-wide + ingress secrets for the bare-domain hostnames it serves directly + (TrainingPortal CRs prefix the domain for individual portals). + properties: + caCertificateSecretRef: + description: |- + LocalObjectReference is a name-only reference to an object in the + operator namespace (or, for cluster-scoped kinds, to the cluster- + scoped object). Mirrors the shape used in the config API group; + duplicated here to avoid cross-group Go coupling. + properties: + name: + description: name of the referent. + type: string + required: + - name + type: object + protocol: + description: |- + protocol asserts the scheme of the public-facing URLs the + session manager and workshops generate. Set to https when TLS + is terminated outside the cluster (external load balancer or + proxy forwarding plain HTTP inward) so links are generated + correctly despite no in-cluster certificate being presented. + Empty derives from the TLS configuration: https when a + wildcard certificate is configured, http otherwise. + enum: + - http + - https + type: string + tlsSecretRef: + description: |- + LocalObjectReference is a name-only reference to an object in the + operator namespace (or, for cluster-scoped kinds, to the cluster- + scoped object). Mirrors the shape used in the config API group; + duplicated here to avoid cross-group Go coupling. + properties: + name: + description: name of the referent. + type: string + required: + - name + type: object + type: object + logLevel: + default: info + description: logLevel defaults to info. + enum: + - debug + - info + - warn + - error + type: string + network: + description: |- + SessionNetwork configures network characteristics applied to workshop + sessions. + properties: + blockedCidrs: + description: |- + blockedCidrs lists CIDR ranges workshop sessions are denied + network access to (e.g., cloud metadata endpoints). + items: + type: string + type: array + packetSize: + description: |- + packetSize sets the MTU for workshop session networking. Useful + on overlay networks where the default MTU is too large. + format: int32 + minimum: 576 + type: integer + type: object + nodeCATrust: + description: nodeCATrust controls the optional node-ca-injector install. + properties: + mode: + default: Auto + description: |- + mode defaults to Auto. Auto installs the subchart only when + the cluster config publishes a CA Secret reference; with no CA + configured, Auto skips the install silently. Enabled forces + the install (refuses if no CA is configured). Disabled keeps + it uninstalled. + enum: + - Auto + - Enabled + - Disabled + type: string + type: object + registryMirrors: + description: |- + registryMirrors configures per-registry mirrors for workshop + container pulls. + items: + description: RegistryMirror declares a registry mirror used by workshop + containers. + properties: + mirror: + description: |- + mirror is the upstream registry being mirrored + (e.g., "docker.io"). + type: string + url: + description: url is the mirror endpoint. + type: string + required: + - mirror + - url + type: object + type: array + remoteAccess: + description: remoteAccess controls the optional remote-access install. + properties: + mode: + default: Auto + description: |- + mode defaults to Auto. Auto installs the subchart only when a + `LookupService` CR exists in the cluster (the signal that + cross-cluster federation is being used). Enabled forces the + install regardless of LookupService presence. Disabled keeps + it uninstalled. + enum: + - Auto + - Enabled + - Disabled + type: string + type: object + sessionCookieDomain: + description: |- + sessionCookieDomain sets the cookie domain used by workshop + sessions for cross-subdomain authentication. + type: string + storage: + description: |- + SessionStorage configures persistent storage characteristics for + workshop sessions. + properties: + storageClass: + type: string + storageGroup: + description: storageGroup sets the supplemental GID for mounted + volumes. + format: int64 + type: integer + storageUser: + description: storageUser sets the UID for mounted volumes. + format: int64 + type: integer + type: object + themes: + description: themes is a list of named themes available to TrainingPortals. + items: + description: Theme is one named entry in the spec.themes list. + properties: + name: + type: string + source: + description: |- + ThemeSource sources theme content. Exactly one of the per-type fields + (secretRef, configMapRef) should be populated for the selected type. + Secret is the only source the reconciler supports in v1alpha1; + ConfigMap and URL are reserved and rejected as "not yet supported". + properties: + configMapRef: + description: configMapRef applies when type is ConfigMap. + properties: + name: + type: string + namespace: + type: string + required: + - name + - namespace + type: object + secretRef: + description: |- + secretRef applies when type is Secret. It names a Secret holding + the theme assets; when its namespace differs from the release + namespace the runtime chart auto-creates a SecretCopier for it. + properties: + name: + type: string + namespace: + type: string + required: + - name + - namespace + type: object + type: + description: |- + ThemeSourceType selects how a theme's content is sourced. + Additional types may be added by the session-manager owner. + enum: + - ConfigMap + - Secret + - URL + type: string + required: + - type + type: object + required: + - name + - source + type: object + type: array + tracking: + description: Tracking groups analytics provider configuration. + properties: + amplitude: + description: TrackingProvider holds a single analytics provider's + tracking ID. + properties: + trackingId: + type: string + required: + - trackingId + type: object + clarity: + description: TrackingProvider holds a single analytics provider's + tracking ID. + properties: + trackingId: + type: string + required: + - trackingId + type: object + googleAnalytics: + description: TrackingProvider holds a single analytics provider's + tracking ID. + properties: + trackingId: + type: string + required: + - trackingId + type: object + webhook: + description: |- + TrackingWebhook configures an HTTP webhook receiver for analytics + events. + properties: + url: + type: string + required: + - url + type: object + type: object + workshopPolicyOverride: + description: |- + WorkshopPolicyOverride locally overrides + EducatesClusterConfig.status.policyEnforcement.workshopPolicyEngine + for this SessionManager. + properties: + engine: + description: |- + WorkshopPolicyEngine names the engine enforcing per-workshop isolation + rules. Mirrors the same-named enum in the config API group; + duplicated to avoid cross-group Go coupling. + enum: + - Kyverno + - None + type: string + required: + - engine + type: object + type: object + status: + description: |- + SessionManagerStatus defines the observed state of SessionManager. + Phase 4 publishes the full CRD draft r3 §4 contract: phase + + conditions + installedVersion + deploymentRef. + properties: + conditions: + description: |- + conditions report the resource's state. Phase 4 publishes: + - Ready (aggregate) + - ClusterConfigAvailable (EducatesClusterConfig.Ready gate) + - SecretsManagerAvailable (SecretsManager.Ready gate) + - Deployed (session-manager helm release + Deployment Available) + - NodeCATrustDeployed (optional extra; reflects mode evaluation outcome) + - RemoteAccessDeployed (optional extra; reflects mode evaluation outcome) + items: + description: Condition contains details for one aspect of the current + state of this API Resource. + properties: + lastTransitionTime: + description: |- + lastTransitionTime is the last time the condition transitioned from one status to another. + This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable. + format: date-time + type: string + message: + description: |- + message is a human readable message indicating details about the transition. + This may be an empty string. + maxLength: 32768 + type: string + observedGeneration: + description: |- + observedGeneration represents the .metadata.generation that the condition was set based upon. + For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date + with respect to the current state of the instance. + format: int64 + minimum: 0 + type: integer + reason: + description: |- + reason contains a programmatic identifier indicating the reason for the condition's last transition. + Producers of specific condition types may define expected values and meanings for this field, + and whether the values are considered a guaranteed API. + The value should be a CamelCase string. + This field may not be empty. + maxLength: 1024 + minLength: 1 + pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ + type: string + status: + description: status of the condition, one of True, False, Unknown. + enum: + - "True" + - "False" + - Unknown + type: string + type: + description: type of condition in CamelCase or in foo.example.com/CamelCase. + maxLength: 316 + pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ + type: string + required: + - lastTransitionTime + - message + - reason + - status + - type + type: object + type: array + x-kubernetes-list-map-keys: + - type + x-kubernetes-list-type: map + deploymentRef: + description: |- + deploymentRef names the upstream session-manager Deployment the + operator is gating Ready on. + properties: + name: + type: string + namespace: + type: string + required: + - name + - namespace + type: object + installedVersion: + description: |- + installedVersion records the session-manager chart version most + recently applied. + type: string + observedGeneration: + format: int64 + type: integer + phase: + description: |- + ComponentPhase summarises the operator's current activity on a + platform component. Phases are advisory; conditions carry the + authoritative state. + enum: + - Pending + - Installing + - Ready + - Degraded + - Uninstalling + type: string + type: object + required: + - spec + type: object + x-kubernetes-validations: + - message: SessionManager must be named 'cluster' (singleton per cluster) + rule: self.metadata.name == 'cluster' + served: true + storage: true + subresources: + status: {} diff --git a/installer/charts/educates-installer/templates/NOTES.txt b/installer/charts/educates-installer/templates/NOTES.txt new file mode 100644 index 000000000..3173c1350 --- /dev/null +++ b/installer/charts/educates-installer/templates/NOTES.txt @@ -0,0 +1,28 @@ +Educates v4 installer is now deployed in namespace {{ .Release.Namespace }}. + +The four CRDs are installed cluster-wide: + - educatesclusterconfigs.config.educates.dev (singleton, named "cluster") + - secretsmanagers.platform.educates.dev (singleton, named "cluster") + - lookupservices.platform.educates.dev (singleton, named "cluster") + - sessionmanagers.platform.educates.dev (singleton, named "cluster") + +Next, apply the platform custom resources for your scenario — the +operator installs everything else once EducatesClusterConfig is +applied. Worked examples live in installer/samples/ in the project +repository; documentation at https://docs.educates.dev. + + kubectl apply -f educates-cluster-config.yaml + kubectl wait --for=condition=Ready educatesclusterconfig/cluster --timeout=600s + kubectl apply -f educates-secrets-manager.yaml + kubectl apply -f educates-lookup-service.yaml # optional + kubectl apply -f educates-session-manager.yaml + +Useful commands: + + kubectl get pods -n {{ .Release.Namespace }} \ + -l app.kubernetes.io/name=educates-installer + kubectl logs -n {{ .Release.Namespace }} \ + -l app.kubernetes.io/name=educates-installer -f + + kubectl explain educatesclusterconfig.spec + kubectl get crd | grep educates.dev diff --git a/installer/charts/educates-installer/templates/_helpers.tpl b/installer/charts/educates-installer/templates/_helpers.tpl new file mode 100644 index 000000000..a68a83b05 --- /dev/null +++ b/installer/charts/educates-installer/templates/_helpers.tpl @@ -0,0 +1,86 @@ +{{/* +Common labels applied to all resources rendered by this chart. +*/}} +{{- define "educates-installer.labels" -}} +app.kubernetes.io/name: educates-installer +app.kubernetes.io/instance: {{ .Release.Name }} +app.kubernetes.io/component: operator +app.kubernetes.io/part-of: educates +app.kubernetes.io/managed-by: {{ .Release.Service }} +app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} +helm.sh/chart: {{ printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} +{{- end -}} + +{{/* +Selector labels — stable across upgrades; must not include the chart +version. +*/}} +{{- define "educates-installer.selectorLabels" -}} +app.kubernetes.io/name: educates-installer +app.kubernetes.io/instance: {{ .Release.Name }} +{{- end -}} + +{{/* +Resolve the effective image registry: development.imageRegistry (user +override) → global.development.imageRegistry (uniformity with the +runtime subcharts; this chart is standalone so it's normally unset) → +Chart.yaml `educates.dev/image-registry-*` annotations (publish-time +defaults). Returned as a YAML string — consume via `fromYaml`. +*/}} +{{- define "educates-installer.resolvedImageRegistry" -}} +{{- $local := default dict (default dict .Values.development).imageRegistry -}} +{{- $global := default dict (default dict (default dict .Values.global).development).imageRegistry -}} +{{- $merged := mergeOverwrite (deepCopy $local) $global -}} +{{- if not $merged.host -}} + {{- $_ := set $merged "host" (index .Chart.Annotations "educates.dev/image-registry-host" | default "") -}} +{{- end -}} +{{- if not $merged.namespace -}} + {{- $_ := set $merged "namespace" (index .Chart.Annotations "educates.dev/image-registry-namespace" | default "") -}} +{{- end -}} +{{- toYaml $merged -}} +{{- end -}} + +{{- define "educates-installer.imageRegistryPrefix" -}} +{{- $ir := include "educates-installer.resolvedImageRegistry" . | fromYaml -}} +{{- $host := default "" $ir.host -}} +{{- $ns := default "" $ir.namespace -}} +{{- if and $host $ns -}} +{{ $host }}/{{ $ns }} +{{- else if $host -}} +{{ $host }} +{{- else -}} +{{- fail "imageRegistry.host could not be resolved. Either set Chart.yaml annotation `educates.dev/image-registry-host` (publish-time default) or override locally via .development.imageRegistry / .global.development.imageRegistry." -}} +{{- end -}} +{{- end -}} + +{{- define "educates-installer.image.repository" -}} +{{- if .Values.image.repository -}} +{{ .Values.image.repository }} +{{- else -}} +{{ include "educates-installer.imageRegistryPrefix" . }}/educates-operator +{{- end -}} +{{- end -}} + +{{/* +Resolve the container image tag, defaulting to .Chart.AppVersion when unset. +*/}} +{{- define "educates-installer.image.tag" -}} +{{- default .Chart.AppVersion .Values.image.tag -}} +{{- end -}} + +{{/* +Auto-derive imagePullPolicy: Always for floating tags, IfNotPresent +otherwise. An explicit pullPolicy in values wins. +*/}} +{{- define "educates-installer.image.pullPolicy" -}} +{{- if .Values.image.pullPolicy -}} +{{ .Values.image.pullPolicy }} +{{- else -}} +{{- $tag := include "educates-installer.image.tag" . -}} +{{- if or (eq $tag "latest") (eq $tag "main") (eq $tag "master") (eq $tag "develop") -}} +Always +{{- else -}} +IfNotPresent +{{- end -}} +{{- end -}} +{{- end -}} diff --git a/installer/charts/educates-installer/templates/deployment.yaml b/installer/charts/educates-installer/templates/deployment.yaml new file mode 100644 index 000000000..22527e657 --- /dev/null +++ b/installer/charts/educates-installer/templates/deployment.yaml @@ -0,0 +1,78 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: educates-installer + namespace: {{ .Release.Namespace }} + labels: + {{- include "educates-installer.labels" . | nindent 4 }} +spec: + replicas: 1 + strategy: + type: Recreate + selector: + matchLabels: + {{- include "educates-installer.selectorLabels" . | nindent 6 }} + template: + metadata: + labels: + {{- include "educates-installer.labels" . | nindent 8 }} + {{- include "educates-installer.selectorLabels" . | nindent 8 }} + spec: + serviceAccountName: educates-installer + {{- with .Values.imagePullSecrets }} + imagePullSecrets: + {{- toYaml . | nindent 8 }} + {{- end }} + securityContext: + runAsNonRoot: true + containers: + - name: manager + image: "{{ include "educates-installer.image.repository" . }}:{{ include "educates-installer.image.tag" . }}" + imagePullPolicy: {{ include "educates-installer.image.pullPolicy" . }} + args: + - --health-probe-bind-address=:8081 + - --metrics-bind-address=0 + {{- if .Values.leaderElection.enabled }} + - --leader-elect + {{- end }} + env: + - name: OPERATOR_NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + securityContext: + allowPrivilegeEscalation: false + capabilities: + drop: ["ALL"] + ports: + - name: probes + containerPort: 8081 + protocol: TCP + livenessProbe: + httpGet: + path: /healthz + port: probes + initialDelaySeconds: 15 + periodSeconds: 20 + readinessProbe: + httpGet: + path: /readyz + port: probes + initialDelaySeconds: 5 + periodSeconds: 10 + {{- with .Values.resources }} + resources: + {{- toYaml . | nindent 12 }} + {{- end }} + {{- with .Values.nodeSelector }} + nodeSelector: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.tolerations }} + tolerations: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.affinity }} + affinity: + {{- toYaml . | nindent 8 }} + {{- end }} diff --git a/installer/charts/educates-installer/templates/rbac/cluster-admin-binding.yaml b/installer/charts/educates-installer/templates/rbac/cluster-admin-binding.yaml new file mode 100644 index 000000000..f4646b5ae --- /dev/null +++ b/installer/charts/educates-installer/templates/rbac/cluster-admin-binding.yaml @@ -0,0 +1,36 @@ +{{/* + Phase 2/3 development shortcut: bind the operator ServiceAccount to + the built-in cluster-admin ClusterRole. + + Why this is needed: the operator drives Helm SDK installs of upstream + charts (cert-manager today; Contour, Kyverno, external-dns in Phase + 3). Those installs apply every resource the chart contains — + ServiceAccounts, ClusterRoles, RoleBindings, Services, ConfigMaps, + ValidatingWebhookConfigurations, Deployments, CRDs — under the + operator's own ServiceAccount. Kubernetes RBAC requires the actor to + hold at least the permissions of the resources it creates, so any + scoping narrower than cluster-admin breaks on the first new chart + resource type we don't pre-enumerate. + + Why this is acceptable today: the operator is the only consumer of + cluster services in v4 (see decisions.md → no umbrella chart), and + Phase 6 will replace this binding with a fine-grained ClusterRole + derived from the manifests every vendored chart actually produces. + Until then, this is the "cluster-admin shortcut" referenced from + internal/controller/config/educatesclusterconfig_controller.go's + RBAC comment block. +*/}} +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: educates-installer-cluster-admin + labels: + {{- include "educates-installer.labels" . | nindent 4 }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: cluster-admin +subjects: + - kind: ServiceAccount + name: educates-installer + namespace: {{ .Release.Namespace }} diff --git a/installer/charts/educates-installer/templates/rbac/role-binding.yaml b/installer/charts/educates-installer/templates/rbac/role-binding.yaml new file mode 100644 index 000000000..a64469ff9 --- /dev/null +++ b/installer/charts/educates-installer/templates/rbac/role-binding.yaml @@ -0,0 +1,14 @@ +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: educates-installer-manager + labels: + {{- include "educates-installer.labels" . | nindent 4 }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: educates-installer-manager +subjects: + - kind: ServiceAccount + name: educates-installer + namespace: {{ .Release.Namespace }} diff --git a/installer/charts/educates-installer/templates/rbac/role.yaml b/installer/charts/educates-installer/templates/rbac/role.yaml new file mode 100644 index 000000000..b02fb4206 --- /dev/null +++ b/installer/charts/educates-installer/templates/rbac/role.yaml @@ -0,0 +1,116 @@ +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: educates-installer-manager +rules: +- apiGroups: + - "" + resources: + - namespaces + verbs: + - create + - delete + - get + - list + - patch + - watch +- apiGroups: + - "" + resources: + - secrets + verbs: + - create + - delete + - get + - list + - patch + - update + - watch +- apiGroups: + - apps + resources: + - deployments + verbs: + - get + - list + - watch +- apiGroups: + - cert-manager.io + resources: + - certificates + - clusterissuers + verbs: + - create + - delete + - get + - list + - patch + - update + - watch +- apiGroups: + - config.educates.dev + resources: + - educatesclusterconfigs + verbs: + - create + - delete + - get + - list + - patch + - update + - watch +- apiGroups: + - config.educates.dev + resources: + - educatesclusterconfigs/finalizers + verbs: + - update +- apiGroups: + - config.educates.dev + resources: + - educatesclusterconfigs/status + verbs: + - get + - patch + - update +- apiGroups: + - networking.k8s.io + resources: + - ingressclasses + verbs: + - get + - list + - watch +- apiGroups: + - platform.educates.dev + resources: + - lookupservices + - secretsmanagers + - sessionmanagers + verbs: + - create + - delete + - get + - list + - patch + - update + - watch +- apiGroups: + - platform.educates.dev + resources: + - lookupservices/finalizers + - secretsmanagers/finalizers + - sessionmanagers/finalizers + verbs: + - update +- apiGroups: + - platform.educates.dev + resources: + - lookupservices/status + - secretsmanagers/status + - sessionmanagers/status + verbs: + - get + - patch + - update diff --git a/installer/charts/educates-installer/templates/serviceaccount.yaml b/installer/charts/educates-installer/templates/serviceaccount.yaml new file mode 100644 index 000000000..19a4fcec4 --- /dev/null +++ b/installer/charts/educates-installer/templates/serviceaccount.yaml @@ -0,0 +1,7 @@ +apiVersion: v1 +kind: ServiceAccount +metadata: + name: educates-installer + namespace: {{ .Release.Namespace }} + labels: + {{- include "educates-installer.labels" . | nindent 4 }} diff --git a/installer/charts/educates-installer/values.yaml b/installer/charts/educates-installer/values.yaml new file mode 100644 index 000000000..21043f80e --- /dev/null +++ b/installer/charts/educates-installer/values.yaml @@ -0,0 +1,51 @@ +# Operator container image. All fields are overrides; in normal use +# leave them empty and the chart resolves the image as +# `{host}/{namespace}/educates-operator:{appVersion}` from the +# Chart.yaml `educates.dev/image-registry-*` annotations (publish-time +# defaults, rewritten per fork by the release workflow). +# +# - repository: full image repository (registry + path, no tag). +# Wins over both the annotations and development.imageRegistry. +# - tag: defaults to Chart.appVersion. +# - pullPolicy: empty auto-derives — Always for floating tags +# (latest/main/master/develop), IfNotPresent otherwise. +# +# Local development workflow: +# cd installer/operator +# make docker-build IMG=ghcr.io/educates/educates-operator:dev +# kind load docker-image ghcr.io/educates/educates-operator:dev +# helm install educates-installer installer/charts/educates-installer \ +# --namespace educates-installer --create-namespace \ +# --set image.repository=ghcr.io/educates/educates-operator \ +# --set image.tag=dev +image: + repository: "" + tag: "" + pullPolicy: "" + +# Development override for the registry prefix only (image name and tag +# still resolve normally): {host: ghcr.io, namespace: myfork}. Same +# knob as the runtime subcharts' development.imageRegistry. Leave empty +# in normal use. +development: + imageRegistry: {} + +# Pull secrets for the operator pod itself. Distinct from +# EducatesClusterConfig.spec.imageRegistry.pullSecrets, which apply to +# bundled charts the operator installs. +imagePullSecrets: [] + +# Operator pod resources. Empty means no requests or limits set; tune +# per cluster. +resources: {} + +# Pod placement. +nodeSelector: {} +tolerations: [] +affinity: {} + +# When false, leader election is disabled — appropriate for the Phase 0 +# single-replica deployment. When the operator scales beyond one replica +# (not in v4 plan), set to true. +leaderElection: + enabled: false diff --git a/installer/charts/educates-training-platform/.helmignore b/installer/charts/educates-training-platform/.helmignore new file mode 100644 index 000000000..138c64273 --- /dev/null +++ b/installer/charts/educates-training-platform/.helmignore @@ -0,0 +1,11 @@ +.DS_Store +.git/ +.gitignore +.idea/ +.vscode/ +*.tmproj +*.swp +*.bak +*.tgz +.project +tests diff --git a/installer/charts/educates-training-platform/Chart.yaml b/installer/charts/educates-training-platform/Chart.yaml new file mode 100644 index 000000000..6992fbc4f --- /dev/null +++ b/installer/charts/educates-training-platform/Chart.yaml @@ -0,0 +1,39 @@ +apiVersion: v2 +name: educates-training-platform +description: | + Educates training platform runtime. Umbrella chart that deploys the three + Educates components (secrets-manager, lookup-service, session-manager) as + subcharts. Each subchart can be enabled or disabled independently via its + `enabled` value. +type: application +version: 4.0.0-alpha.1 +# appVersion is the bundled Educates *runtime* version (the images session-manager +# spawns and the chart-pod images themselves). The committed value is a +# development placeholder pointing at the last released runtime; at release +# time CI stamps both `version` and `appVersion` to the git tag +# (hack/stamp-release-version.sh) — every release publishes the runtime +# images at that same tag, so released charts are self-consistent. +appVersion: "3.7.1" +kubeVersion: ">=1.31.0-0" +home: https://educates.dev +sources: + - https://github.com/jorgemoralespou/educates-training-platform +maintainers: + - name: Educates Maintainers + url: https://github.com/jorgemoralespou/educates-training-platform/blob/develop/MAINTAINERS.md +dependencies: + - name: secrets-manager + version: 4.0.0-alpha.1 + condition: secrets-manager.enabled + - name: lookup-service + version: 4.0.0-alpha.1 + condition: lookup-service.enabled + - name: remote-access + version: 4.0.0-alpha.1 + condition: remote-access.enabled + - name: session-manager + version: 4.0.0-alpha.1 + condition: session-manager.enabled + - name: node-ca-injector + version: 4.0.0-alpha.1 + condition: node-ca-injector.enabled diff --git a/installer/charts/educates-training-platform/charts/lookup-service/Chart.yaml b/installer/charts/educates-training-platform/charts/lookup-service/Chart.yaml new file mode 100644 index 000000000..790c031ad --- /dev/null +++ b/installer/charts/educates-training-platform/charts/lookup-service/Chart.yaml @@ -0,0 +1,12 @@ +apiVersion: v2 +name: lookup-service +description: | + Educates lookup-service component. Provides cross-cluster service discovery + for federated training portals. +type: application +version: 4.0.0-alpha.1 +appVersion: "3.7.1" +annotations: + educates.dev/image-registry-host: "ghcr.io" + educates.dev/image-registry-namespace: "educates" +kubeVersion: ">=1.31.0-0" diff --git a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/educates/_ytt_lib/lookup-service/upstream/crd-clientconfig.yaml b/installer/charts/educates-training-platform/charts/lookup-service/crds/clientconfig.yaml similarity index 100% rename from carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/educates/_ytt_lib/lookup-service/upstream/crd-clientconfig.yaml rename to installer/charts/educates-training-platform/charts/lookup-service/crds/clientconfig.yaml diff --git a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/educates/_ytt_lib/lookup-service/upstream/crd-clusterconfig.yaml b/installer/charts/educates-training-platform/charts/lookup-service/crds/clusterconfig.yaml similarity index 100% rename from carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/educates/_ytt_lib/lookup-service/upstream/crd-clusterconfig.yaml rename to installer/charts/educates-training-platform/charts/lookup-service/crds/clusterconfig.yaml diff --git a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/educates/_ytt_lib/lookup-service/upstream/crd-tenantconfig.yaml b/installer/charts/educates-training-platform/charts/lookup-service/crds/tenantconfig.yaml similarity index 100% rename from carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/educates/_ytt_lib/lookup-service/upstream/crd-tenantconfig.yaml rename to installer/charts/educates-training-platform/charts/lookup-service/crds/tenantconfig.yaml diff --git a/installer/charts/educates-training-platform/charts/lookup-service/templates/_helpers.tpl b/installer/charts/educates-training-platform/charts/lookup-service/templates/_helpers.tpl new file mode 100644 index 000000000..7a7ae52ea --- /dev/null +++ b/installer/charts/educates-training-platform/charts/lookup-service/templates/_helpers.tpl @@ -0,0 +1,101 @@ +{{- define "lookup-service.labels" -}} +app.kubernetes.io/name: lookup-service +app.kubernetes.io/instance: {{ .Release.Name }} +app.kubernetes.io/component: lookup-service +app.kubernetes.io/part-of: educates +app.kubernetes.io/managed-by: {{ .Release.Service }} +app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} +helm.sh/chart: {{ printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} +{{- end -}} + +{{- define "lookup-service.selectorLabels" -}} +app: lookup-service +{{- end -}} + +{{/* +Resolve the effective imageRegistry for chart-rendered refs. Reads the +development override (subchart-local + umbrella global, deep-merged) and +falls back per-leaf to Chart.yaml annotations +(`educates.dev/image-registry-host` / `-namespace`) when empty. The +annotations are publish-time defaults updated by the release workflow. +*/}} +{{- define "lookup-service.resolvedImageRegistry" -}} +{{- $local := default dict (default dict .Values.development).imageRegistry -}} +{{- $global := default dict (default dict (default dict .Values.global).development).imageRegistry -}} +{{- $merged := mergeOverwrite (deepCopy $local) $global -}} +{{- if not $merged.host -}} + {{- $_ := set $merged "host" (index .Chart.Annotations "educates.dev/image-registry-host" | default "") -}} +{{- end -}} +{{- if not $merged.namespace -}} + {{- $_ := set $merged "namespace" (index .Chart.Annotations "educates.dev/image-registry-namespace" | default "") -}} +{{- end -}} +{{- toYaml $merged -}} +{{- end -}} + +{{- define "lookup-service.imageRegistryPrefix" -}} +{{- $ir := include "lookup-service.resolvedImageRegistry" . | fromYaml -}} +{{- $host := default "" $ir.host -}} +{{- $ns := default "" $ir.namespace -}} +{{- if and $host $ns -}} +{{ $host }}/{{ $ns }} +{{- else if $host -}} +{{ $host }} +{{- else -}} +{{- fail "imageRegistry.host could not be resolved. Either set Chart.yaml annotation `educates.dev/image-registry-host` (publish-time default) or override locally via .development.imageRegistry / .global.development.imageRegistry." -}} +{{- end -}} +{{- end -}} + +{{- define "lookup-service.image.repository" -}} +{{- if .Values.image.repository -}} +{{ .Values.image.repository }} +{{- else -}} +{{ include "lookup-service.imageRegistryPrefix" . }}/educates-lookup-service +{{- end -}} +{{- end -}} + +{{- define "lookup-service.image.tag" -}} +{{- default .Chart.AppVersion .Values.image.tag -}} +{{- end -}} + +{{- define "lookup-service.image.pullPolicy" -}} +{{- if .Values.image.pullPolicy -}} +{{ .Values.image.pullPolicy }} +{{- else -}} +{{- $tag := include "lookup-service.image.tag" . -}} +{{- if or (eq $tag "latest") (eq $tag "main") (eq $tag "master") (eq $tag "develop") -}} +Always +{{- else -}} +IfNotPresent +{{- end -}} +{{- end -}} +{{- end -}} + +{{/* +Resolve the clusterIngress block by deep-merging the umbrella's +`global.clusterIngress` over the subchart's local `clusterIngress`. Globals +win where set; subchart-local defaults pass through otherwise. +*/}} +{{- define "lookup-service.resolvedClusterIngress" -}} +{{- $local := default dict .Values.clusterIngress -}} +{{- $global := default dict (default dict .Values.global).clusterIngress -}} +{{- toYaml (mergeOverwrite (deepCopy $local) $global) -}} +{{- end -}} + +{{/* +Render the ca-trust-store init container + volumes/volumeMounts when the +resolved clusterIngress.caCertificateRef.name is set. Reuses the main +lookup-service image (Fedora-based, has `update-ca-trust` and `tar`) so no +extra image pull happens. The init container reads the CA from a Secret +mounted at /etc/pki/ca-trust/source/anchors/Cluster_Ingress_CA.pem, runs +`update-ca-trust`, and writes the populated trust store to /mnt — the main +container then mounts that same emptyDir at /etc/pki/ca-trust read-only. + +Mirrors v3's overlay-ca-injector.yaml. Required when lookup-service must +verify TLS against a private/self-signed CA when calling other clusters' +endpoints. +*/}} +{{- define "lookup-service.caTrustEnabled" -}} +{{- $ci := include "lookup-service.resolvedClusterIngress" . | fromYaml -}} +{{- $caRef := default dict $ci.caCertificateRef -}} +{{- if $caRef.name }}true{{- end -}} +{{- end -}} diff --git a/installer/charts/educates-training-platform/charts/lookup-service/templates/clusterrole.yaml b/installer/charts/educates-training-platform/charts/lookup-service/templates/clusterrole.yaml new file mode 100644 index 000000000..78c190b24 --- /dev/null +++ b/installer/charts/educates-training-platform/charts/lookup-service/templates/clusterrole.yaml @@ -0,0 +1,37 @@ +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: educates-lookup-service + labels: + {{- include "lookup-service.labels" . | nindent 4 }} +rules: + - apiGroups: [""] + resources: [namespaces] + verbs: [get, list, watch] + - apiGroups: [""] + resources: [events] + verbs: [create] + - apiGroups: [lookup.educates.dev] + resources: [clusterconfigs, clientconfigs, tenantconfigs] + verbs: [get, list, watch, patch, update] + - apiGroups: [lookup.educates.dev] + resources: [clusterconfigs/finalizers, clientconfigs/finalizers, tenantconfigs/finalizers] + verbs: [update] + - apiGroups: [""] + resources: [secrets] + verbs: [get, list, watch] +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: educates-lookup-service + labels: + {{- include "lookup-service.labels" . | nindent 4 }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: educates-lookup-service +subjects: + - kind: ServiceAccount + name: lookup-service + namespace: {{ .Release.Namespace }} diff --git a/installer/charts/educates-training-platform/charts/lookup-service/templates/deployment.yaml b/installer/charts/educates-training-platform/charts/lookup-service/templates/deployment.yaml new file mode 100644 index 000000000..7f5dd846d --- /dev/null +++ b/installer/charts/educates-training-platform/charts/lookup-service/templates/deployment.yaml @@ -0,0 +1,85 @@ +{{- $ci := include "lookup-service.resolvedClusterIngress" . | fromYaml -}} +{{- $caRef := default dict $ci.caCertificateRef -}} +{{- $caEnabled := and $caRef.name true -}} +apiVersion: apps/v1 +kind: Deployment +metadata: + name: lookup-service + namespace: {{ .Release.Namespace }} + labels: + {{- include "lookup-service.labels" . | nindent 4 }} +spec: + replicas: 1 + selector: + matchLabels: + {{- include "lookup-service.selectorLabels" . | nindent 6 }} + template: + metadata: + labels: + {{- include "lookup-service.labels" . | nindent 8 }} + {{- include "lookup-service.selectorLabels" . | nindent 8 }} + spec: + serviceAccountName: lookup-service + {{- with .Values.imagePullSecrets }} + imagePullSecrets: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- if $caEnabled }} + # ca-trust-store init container reuses the main lookup-service image + # (Fedora-based: has `update-ca-trust` and `tar`). Mirrors v3's + # overlay-ca-injector.yaml mechanism with no extra image pull. + initContainers: + - name: ca-trust-store-initialization + image: "{{ include "lookup-service.image.repository" . }}:{{ include "lookup-service.image.tag" . }}" + imagePullPolicy: {{ include "lookup-service.image.pullPolicy" . }} + securityContext: + runAsNonRoot: false + runAsUser: 0 + allowPrivilegeEscalation: false + command: ["/bin/bash", "-c"] + args: + - "update-ca-trust && tar -C /etc/pki/ca-trust -cf - . | tar -C /mnt -xf -" + volumeMounts: + - name: cluster-ca + mountPath: /etc/pki/ca-trust/source/anchors/Cluster_Ingress_CA.pem + subPath: ca.crt + - name: cluster-ca-trust + mountPath: /mnt + {{- end }} + containers: + - name: lookup-service + image: "{{ include "lookup-service.image.repository" . }}:{{ include "lookup-service.image.tag" . }}" + imagePullPolicy: {{ include "lookup-service.image.pullPolicy" . }} + ports: + - containerPort: 8080 + {{- with .Values.resources }} + resources: + {{- toYaml . | nindent 12 }} + {{- end }} + {{- if or .Values.remoteAccessTokenMount.enabled $caEnabled }} + volumeMounts: + {{- if .Values.remoteAccessTokenMount.enabled }} + - name: cluster-access-token + mountPath: /opt/cluster-access-token + {{- end }} + {{- if $caEnabled }} + - name: cluster-ca-trust + mountPath: /etc/pki/ca-trust + readOnly: true + {{- end }} + {{- end }} + {{- if or .Values.remoteAccessTokenMount.enabled $caEnabled }} + volumes: + {{- if .Values.remoteAccessTokenMount.enabled }} + - name: cluster-access-token + secret: + secretName: remote-access-token + {{- end }} + {{- if $caEnabled }} + - name: cluster-ca + secret: + secretName: {{ $caRef.name | quote }} + - name: cluster-ca-trust + emptyDir: {} + {{- end }} + {{- end }} diff --git a/installer/charts/educates-training-platform/charts/lookup-service/templates/ingress.yaml b/installer/charts/educates-training-platform/charts/lookup-service/templates/ingress.yaml new file mode 100644 index 000000000..a19d31121 --- /dev/null +++ b/installer/charts/educates-training-platform/charts/lookup-service/templates/ingress.yaml @@ -0,0 +1,40 @@ +{{- if not .Values.ingress.host }} +{{- fail "lookup-service: .Values.ingress.host must be set (e.g. lookup.workshops.example.com)." }} +{{- end }} +{{- $ci := include "lookup-service.resolvedClusterIngress" . | fromYaml -}} +{{- $tlsRef := default dict $ci.tlsCertificateRef -}} +{{- $tlsSecret := $tlsRef.name -}} +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: lookup-service + namespace: {{ .Release.Namespace }} + labels: + {{- include "lookup-service.labels" . | nindent 4 }} + {{- if $tlsSecret }} + annotations: + ingress.kubernetes.io/force-ssl-redirect: "true" + nginx.ingress.kubernetes.io/force-ssl-redirect: "true" + nginx.ingress.kubernetes.io/ssl-redirect: "true" + {{- end }} +spec: + {{- with .Values.ingress.className }} + ingressClassName: {{ . }} + {{- end }} + rules: + - host: {{ .Values.ingress.host | quote }} + http: + paths: + - path: / + pathType: Prefix + backend: + service: + name: lookup-service + port: + number: 80 + {{- if $tlsSecret }} + tls: + - hosts: + - {{ .Values.ingress.host | quote }} + secretName: {{ $tlsSecret | quote }} + {{- end }} diff --git a/installer/charts/educates-training-platform/charts/lookup-service/templates/secretcopiers.yaml b/installer/charts/educates-training-platform/charts/lookup-service/templates/secretcopiers.yaml new file mode 100644 index 000000000..8900344b5 --- /dev/null +++ b/installer/charts/educates-training-platform/charts/lookup-service/templates/secretcopiers.yaml @@ -0,0 +1,49 @@ +{{- /* +Auto-derive SecretCopier rules pulling the wildcard TLS Secret + the CA +Secret into the release namespace when their refs target a foreign +namespace. Renders independently of the session-manager subchart's +SecretCopier so this chart is installable standalone — under the umbrella +both subcharts render their own rules (idempotent: the same source-Secret +is copied once regardless of how many copy rules reference it). + +Requires the secrets.educates.dev CRDs from the secrets-manager subchart +to be present in-cluster. +*/ -}} +{{- $ns := .Release.Namespace -}} +{{- $ci := include "lookup-service.resolvedClusterIngress" . | fromYaml -}} +{{- $tlsRef := default dict $ci.tlsCertificateRef -}} +{{- $caRef := default dict $ci.caCertificateRef -}} +{{- $tlsName := default "" $tlsRef.name -}} +{{- $tlsNs := default "" $tlsRef.namespace -}} +{{- $caName := default "" $caRef.name -}} +{{- $caNs := default "" $caRef.namespace -}} +{{- $tlsRule := and $tlsName $tlsNs (ne $tlsNs $ns) -}} +{{- $caRule := and $caName $caNs (ne $caNs $ns) -}} +{{- if or $tlsRule $caRule }} +apiVersion: secrets.educates.dev/v1beta1 +kind: SecretCopier +metadata: + name: educates-lookup-service-ingress-secrets + labels: + {{- include "lookup-service.labels" . | nindent 4 }} +spec: + rules: + {{- if $tlsRule }} + - sourceSecret: + name: {{ $tlsName | quote }} + namespace: {{ $tlsNs | quote }} + targetNamespaces: + nameSelector: + matchNames: + - {{ $ns | quote }} + {{- end }} + {{- if $caRule }} + - sourceSecret: + name: {{ $caName | quote }} + namespace: {{ $caNs | quote }} + targetNamespaces: + nameSelector: + matchNames: + - {{ $ns | quote }} + {{- end }} +{{- end }} diff --git a/installer/charts/educates-training-platform/charts/lookup-service/templates/service.yaml b/installer/charts/educates-training-platform/charts/lookup-service/templates/service.yaml new file mode 100644 index 000000000..e39a949d8 --- /dev/null +++ b/installer/charts/educates-training-platform/charts/lookup-service/templates/service.yaml @@ -0,0 +1,14 @@ +apiVersion: v1 +kind: Service +metadata: + name: lookup-service + namespace: {{ .Release.Namespace }} + labels: + {{- include "lookup-service.labels" . | nindent 4 }} +spec: + type: ClusterIP + selector: + {{- include "lookup-service.selectorLabels" . | nindent 4 }} + ports: + - port: 80 + targetPort: 8080 diff --git a/installer/charts/educates-training-platform/charts/lookup-service/templates/serviceaccount.yaml b/installer/charts/educates-training-platform/charts/lookup-service/templates/serviceaccount.yaml new file mode 100644 index 000000000..29fb65e23 --- /dev/null +++ b/installer/charts/educates-training-platform/charts/lookup-service/templates/serviceaccount.yaml @@ -0,0 +1,7 @@ +apiVersion: v1 +kind: ServiceAccount +metadata: + name: lookup-service + namespace: {{ .Release.Namespace }} + labels: + {{- include "lookup-service.labels" . | nindent 4 }} diff --git a/installer/charts/educates-training-platform/charts/lookup-service/values.schema.json b/installer/charts/educates-training-platform/charts/lookup-service/values.schema.json new file mode 100644 index 000000000..8052c8892 --- /dev/null +++ b/installer/charts/educates-training-platform/charts/lookup-service/values.schema.json @@ -0,0 +1,97 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "Educates lookup-service subchart values", + "type": "object", + "additionalProperties": false, + + "definitions": { + "imageRef": { + "description": "Image reference. Empty `repository` falls through to the imageRegistry-derived default; empty `tag` falls through to Chart.AppVersion.", + "type": "object", + "additionalProperties": false, + "properties": { + "repository": { "type": "string" }, + "tag": { "type": "string" }, + "pullPolicy": { + "type": "string", + "enum": ["", "Always", "IfNotPresent", "Never"] + } + } + }, + + "secretRef": { + "description": "Reference to a Kubernetes Secret. Empty `name` means the ref is unset.", + "type": "object", + "additionalProperties": false, + "properties": { + "name": { "type": "string" }, + "namespace": { "type": "string" } + } + } + }, + + "properties": { + "development": { + "description": "Local-development overrides. Leave empty in normal use — Chart.yaml annotations (`educates.dev/image-registry-{host,namespace}`) provide the publish-time defaults.", + "type": "object", + "additionalProperties": false, + "properties": { + "imageRegistry": { + "type": "object", + "additionalProperties": false, + "properties": { + "host": { "type": "string" }, + "namespace": { "type": "string" } + } + } + } + }, + + "image": { "$ref": "#/definitions/imageRef" }, + + "imagePullSecrets": { + "description": "Pod-spec imagePullSecrets attached to the lookup-service pod itself. Standard Kubernetes [{name: ...}] shape.", + "type": "array", + "items": { + "type": "object", + "additionalProperties": false, + "required": ["name"], + "properties": { + "name": { "type": "string", "minLength": 1 } + } + } + }, + + "resources": { "type": "object" }, + + "clusterIngress": { + "type": "object", + "additionalProperties": false, + "description": "Cluster-wide ingress identity. Same shape as the umbrella's `global.clusterIngress`; under the umbrella, set values there and they propagate here.", + "properties": { + "tlsCertificateRef": { "$ref": "#/definitions/secretRef" }, + "caCertificateRef": { "$ref": "#/definitions/secretRef" } + } + }, + + "ingress": { + "type": "object", + "additionalProperties": false, + "properties": { + "host": { "type": "string" }, + "className": { "type": "string" } + } + }, + + "remoteAccessTokenMount": { + "type": "object", + "additionalProperties": false, + "properties": { + "enabled": { "type": "boolean" } + } + }, + + "enabled": { "type": "boolean" }, + "global": { "type": "object" } + } +} diff --git a/installer/charts/educates-training-platform/charts/lookup-service/values.yaml b/installer/charts/educates-training-platform/charts/lookup-service/values.yaml new file mode 100644 index 000000000..416c96c39 --- /dev/null +++ b/installer/charts/educates-training-platform/charts/lookup-service/values.yaml @@ -0,0 +1,64 @@ +# Values for the lookup-service subchart. + +# Local-development override. Leave empty in normal use — image refs +# resolve from Chart.yaml annotations (`educates.dev/image-registry-host` +# / `-namespace`) which the chart's publish workflow updates per fork. +# Override at the umbrella level under `global.development.imageRegistry` +# to redirect every Educates-image reference (across all subcharts) in +# one knob. +development: + imageRegistry: + host: "" + namespace: "" + +image: + # Empty `repository` derives `{imageRegistry.host}/{imageRegistry.namespace}/educates-lookup-service`. + # Empty `tag` falls through to `Chart.AppVersion`. + repository: "" + tag: "" + pullPolicy: "" + +# Image pull secret references in the operator namespace. +imagePullSecrets: [] + +resources: {} + +# Cluster-wide ingress identity. Same shape as the umbrella's +# `global.clusterIngress`; under the umbrella, set values there and they +# propagate here automatically. This subchart consumes: +# +# - `tlsCertificateRef` — TLS Secret backing this Ingress. Typically the +# wildcard cert covering `*.` (which includes the lookup-service +# hostname). Empty disables TLS on the Ingress. +# - `caCertificateRef` — CA Secret. When set, the chart renders a +# ca-trust-store init container that builds a trust store from the CA +# and the main container mounts it at `/etc/pki/ca-trust`. Required +# when the lookup-service must verify TLS against a private/self-signed +# CA when calling other clusters' lookup-service endpoints. +# +# When either ref's `namespace` differs from the release namespace, the +# chart auto-creates a SecretCopier so the runtime finds the Secret locally. +clusterIngress: + tlsCertificateRef: + name: "" + namespace: "" + caCertificateRef: + name: "" + namespace: "" + +ingress: + # Fully-qualified hostname for the lookup-service ingress (e.g. + # `lookup.workshops.example.com`). The v4 operator computes this from + # the LookupService CR's prefix and EducatesClusterConfig.status.domain. + host: "" + # IngressClass name. Empty leaves the cluster default. + className: "" + +# When true, the Deployment mounts the `remote-access-token` Secret at +# /opt/cluster-access-token. Set true automatically by the operator when +# the umbrella's `remote-access.enabled` is on; can be set explicitly when +# installing this subchart standalone. The lookup-service runtime only +# requires this when serving a "local" ClusterConfig target (no kubeconfig +# secretRef). +remoteAccessTokenMount: + enabled: true diff --git a/installer/charts/educates-training-platform/charts/node-ca-injector/Chart.yaml b/installer/charts/educates-training-platform/charts/node-ca-injector/Chart.yaml new file mode 100644 index 000000000..41ab3ad86 --- /dev/null +++ b/installer/charts/educates-training-platform/charts/node-ca-injector/Chart.yaml @@ -0,0 +1,22 @@ +apiVersion: v2 +name: node-ca-injector +description: | + Educates node-ca-injector. Renders a controller Deployment + privileged + per-node DaemonSet that watches Ingress resources, derives the set of + hosts to trust the cluster's wildcard CA against, and writes per-host + containerd registry-CA configuration into /etc/containerd/certs.d on + each node. Used so containerd can pull images from registries fronted + by a private/self-signed CA without manual node configuration. + + Defaults to disabled at the umbrella level (`node-ca-injector.enabled: + false`); opt in when a private CA is in use AND containerd-level trust + is needed (e.g., image pulls from a private registry behind that CA). + Per-pod CA trust is handled separately by the ca-trust-store init + container in the session-manager and lookup-service Deployments. +type: application +version: 4.0.0-alpha.1 +appVersion: "3.7.1" +kubeVersion: ">=1.31.0-0" +annotations: + educates.dev/image-registry-host: "ghcr.io" + educates.dev/image-registry-namespace: "educates" diff --git a/installer/charts/educates-training-platform/charts/node-ca-injector/templates/_helpers.tpl b/installer/charts/educates-training-platform/charts/node-ca-injector/templates/_helpers.tpl new file mode 100644 index 000000000..f99c9fa91 --- /dev/null +++ b/installer/charts/educates-training-platform/charts/node-ca-injector/templates/_helpers.tpl @@ -0,0 +1,86 @@ +{{- define "node-ca-injector.labels" -}} +app.kubernetes.io/name: node-ca-injector +app.kubernetes.io/instance: {{ .Release.Name }} +app.kubernetes.io/component: node-ca-injector +app.kubernetes.io/part-of: educates +app.kubernetes.io/managed-by: {{ .Release.Service }} +app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} +helm.sh/chart: {{ printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} +{{- end -}} + +{{/* +Resolve cross-cutting blocks (imageRegistry, clusterIngress) by deep-merging +the umbrella's `global.` over this subchart's local block. Globals win +where set; subchart-local defaults pass through otherwise. Returned as a +YAML string — consume via `fromYaml`. +*/}} +{{- define "node-ca-injector.resolvedImageRegistry" -}} +{{- $local := default dict (default dict .Values.development).imageRegistry -}} +{{- $global := default dict (default dict (default dict .Values.global).development).imageRegistry -}} +{{- $merged := mergeOverwrite (deepCopy $local) $global -}} +{{- if not $merged.host -}} + {{- $_ := set $merged "host" (index .Chart.Annotations "educates.dev/image-registry-host" | default "") -}} +{{- end -}} +{{- if not $merged.namespace -}} + {{- $_ := set $merged "namespace" (index .Chart.Annotations "educates.dev/image-registry-namespace" | default "") -}} +{{- end -}} +{{- toYaml $merged -}} +{{- end -}} + +{{- define "node-ca-injector.resolvedClusterIngress" -}} +{{- $local := default dict .Values.clusterIngress -}} +{{- $global := default dict (default dict .Values.global).clusterIngress -}} +{{- toYaml (mergeOverwrite (deepCopy $local) $global) -}} +{{- end -}} + +{{- define "node-ca-injector.imageRegistryPrefix" -}} +{{- $ir := include "node-ca-injector.resolvedImageRegistry" . | fromYaml -}} +{{- $host := default "" $ir.host -}} +{{- $ns := default "" $ir.namespace -}} +{{- if and $host $ns -}} +{{ $host }}/{{ $ns }} +{{- else if $host -}} +{{ $host }} +{{- else -}} +{{- fail "imageRegistry.host could not be resolved. Either set Chart.yaml annotation `educates.dev/image-registry-host` (publish-time default) or override locally via .development.imageRegistry / .global.development.imageRegistry." -}} +{{- end -}} +{{- end -}} + +{{- define "node-ca-injector.image.repository" -}} +{{- if .Values.image.repository -}} +{{ .Values.image.repository }} +{{- else -}} +{{ include "node-ca-injector.imageRegistryPrefix" . }}/educates-node-ca-injector +{{- end -}} +{{- end -}} + +{{- define "node-ca-injector.image.tag" -}} +{{- default .Chart.AppVersion .Values.image.tag -}} +{{- end -}} + +{{- define "node-ca-injector.image.pullPolicy" -}} +{{- if .Values.image.pullPolicy -}} +{{ .Values.image.pullPolicy }} +{{- else -}} +{{- $tag := include "node-ca-injector.image.tag" . -}} +{{- if or (eq $tag "latest") (eq $tag "main") (eq $tag "master") (eq $tag "develop") -}} +Always +{{- else -}} +IfNotPresent +{{- end -}} +{{- end -}} +{{- end -}} + +{{/* +Resolve the CA Secret name for the DaemonSet's volume mount. Required — +without a CA ref the DaemonSet has nothing to mount and the chart fails +fast. +*/}} +{{- define "node-ca-injector.caSecretName" -}} +{{- $ci := include "node-ca-injector.resolvedClusterIngress" . | fromYaml -}} +{{- $caRef := default dict $ci.caCertificateRef -}} +{{- if not $caRef.name -}} +{{- fail "node-ca-injector requires clusterIngress.caCertificateRef.name to be set (typically via .global.clusterIngress.caCertificateRef)" -}} +{{- end -}} +{{ $caRef.name }} +{{- end -}} diff --git a/installer/charts/educates-training-platform/charts/node-ca-injector/templates/clusterrole.yaml b/installer/charts/educates-training-platform/charts/node-ca-injector/templates/clusterrole.yaml new file mode 100644 index 000000000..89e1cd37c --- /dev/null +++ b/installer/charts/educates-training-platform/charts/node-ca-injector/templates/clusterrole.yaml @@ -0,0 +1,10 @@ +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: educates-node-ca-injector + labels: + {{- include "node-ca-injector.labels" . | nindent 4 }} +rules: + - apiGroups: ["networking.k8s.io"] + resources: ["ingresses"] + verbs: ["get", "list", "watch"] diff --git a/installer/charts/educates-training-platform/charts/node-ca-injector/templates/clusterrolebinding.yaml b/installer/charts/educates-training-platform/charts/node-ca-injector/templates/clusterrolebinding.yaml new file mode 100644 index 000000000..03dba428c --- /dev/null +++ b/installer/charts/educates-training-platform/charts/node-ca-injector/templates/clusterrolebinding.yaml @@ -0,0 +1,14 @@ +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: educates-node-ca-injector + labels: + {{- include "node-ca-injector.labels" . | nindent 4 }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: educates-node-ca-injector +subjects: + - kind: ServiceAccount + name: node-ca-injector + namespace: {{ .Release.Namespace }} diff --git a/installer/charts/educates-training-platform/charts/node-ca-injector/templates/daemonset.yaml b/installer/charts/educates-training-platform/charts/node-ca-injector/templates/daemonset.yaml new file mode 100644 index 000000000..9abd640be --- /dev/null +++ b/installer/charts/educates-training-platform/charts/node-ca-injector/templates/daemonset.yaml @@ -0,0 +1,62 @@ +apiVersion: apps/v1 +kind: DaemonSet +metadata: + name: node-ca-injector + namespace: {{ .Release.Namespace }} + labels: + {{- include "node-ca-injector.labels" . | nindent 4 }} + app.kubernetes.io/role: sync +spec: + selector: + matchLabels: + app: node-ca-injector + template: + metadata: + labels: + {{- include "node-ca-injector.labels" . | nindent 8 }} + app.kubernetes.io/role: sync + app: node-ca-injector + spec: + tolerations: + - operator: Exists + {{- with .Values.imagePullSecrets }} + imagePullSecrets: + {{- toYaml . | nindent 8 }} + {{- end }} + containers: + - name: sync + image: "{{ include "node-ca-injector.image.repository" . }}:{{ include "node-ca-injector.image.tag" . }}" + imagePullPolicy: {{ include "node-ca-injector.image.pullPolicy" . }} + args: ["sync"] + # Privileged: writes per-host containerd registry-CA configuration + # under /etc/containerd/certs.d/ on the host. + securityContext: + privileged: true + volumeMounts: + - name: hosts-config + mountPath: /config/hosts + readOnly: true + - name: ca-secret + mountPath: /config/ca + readOnly: true + - name: containerd-certs-d + mountPath: /host/etc/containerd/certs.d + {{- with .Values.sync.resources }} + resources: + {{- toYaml . | nindent 12 }} + {{- end }} + volumes: + # `educates-registry-hosts` is created by the controller Deployment + # from the cluster's Ingress resources. Marked `optional` so the + # DaemonSet starts before the controller has populated it. + - name: hosts-config + configMap: + name: educates-registry-hosts + optional: true + - name: ca-secret + secret: + secretName: {{ include "node-ca-injector.caSecretName" . | quote }} + - name: containerd-certs-d + hostPath: + path: /etc/containerd/certs.d + type: DirectoryOrCreate diff --git a/installer/charts/educates-training-platform/charts/node-ca-injector/templates/deployment.yaml b/installer/charts/educates-training-platform/charts/node-ca-injector/templates/deployment.yaml new file mode 100644 index 000000000..a612bf68c --- /dev/null +++ b/installer/charts/educates-training-platform/charts/node-ca-injector/templates/deployment.yaml @@ -0,0 +1,39 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: node-ca-injector-controller + namespace: {{ .Release.Namespace }} + labels: + {{- include "node-ca-injector.labels" . | nindent 4 }} + app.kubernetes.io/role: controller +spec: + replicas: 1 + selector: + matchLabels: + app: node-ca-injector-controller + template: + metadata: + labels: + {{- include "node-ca-injector.labels" . | nindent 8 }} + app.kubernetes.io/role: controller + app: node-ca-injector-controller + spec: + serviceAccountName: node-ca-injector + {{- with .Values.imagePullSecrets }} + imagePullSecrets: + {{- toYaml . | nindent 8 }} + {{- end }} + containers: + - name: controller + image: "{{ include "node-ca-injector.image.repository" . }}:{{ include "node-ca-injector.image.tag" . }}" + imagePullPolicy: {{ include "node-ca-injector.image.pullPolicy" . }} + args: ["controller"] + env: + - name: OPERATOR_NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + {{- with .Values.controller.resources }} + resources: + {{- toYaml . | nindent 12 }} + {{- end }} diff --git a/installer/charts/educates-training-platform/charts/node-ca-injector/templates/role.yaml b/installer/charts/educates-training-platform/charts/node-ca-injector/templates/role.yaml new file mode 100644 index 000000000..260054c1a --- /dev/null +++ b/installer/charts/educates-training-platform/charts/node-ca-injector/templates/role.yaml @@ -0,0 +1,11 @@ +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + name: node-ca-injector + namespace: {{ .Release.Namespace }} + labels: + {{- include "node-ca-injector.labels" . | nindent 4 }} +rules: + - apiGroups: [""] + resources: ["configmaps"] + verbs: ["get", "list", "watch", "create", "update", "delete", "patch"] diff --git a/installer/charts/educates-training-platform/charts/node-ca-injector/templates/rolebinding.yaml b/installer/charts/educates-training-platform/charts/node-ca-injector/templates/rolebinding.yaml new file mode 100644 index 000000000..069497f2f --- /dev/null +++ b/installer/charts/educates-training-platform/charts/node-ca-injector/templates/rolebinding.yaml @@ -0,0 +1,15 @@ +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: node-ca-injector + namespace: {{ .Release.Namespace }} + labels: + {{- include "node-ca-injector.labels" . | nindent 4 }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: node-ca-injector +subjects: + - kind: ServiceAccount + name: node-ca-injector + namespace: {{ .Release.Namespace }} diff --git a/installer/charts/educates-training-platform/charts/node-ca-injector/templates/secretcopiers.yaml b/installer/charts/educates-training-platform/charts/node-ca-injector/templates/secretcopiers.yaml new file mode 100644 index 000000000..2a7c13c56 --- /dev/null +++ b/installer/charts/educates-training-platform/charts/node-ca-injector/templates/secretcopiers.yaml @@ -0,0 +1,33 @@ +{{- /* +Auto-derive a SecretCopier rule pulling the CA Secret into the release +namespace when its ref targets a foreign namespace. Renders independently +of session-manager and lookup-service SecretCopiers so this chart is +installable standalone — under the umbrella each subchart that consumes +the same global ref renders its own rule (idempotent: the same source- +Secret is copied once regardless of how many rules reference it). + +Requires the secrets.educates.dev CRDs from the secrets-manager subchart +to be present in-cluster. +*/ -}} +{{- $ns := .Release.Namespace -}} +{{- $ci := include "node-ca-injector.resolvedClusterIngress" . | fromYaml -}} +{{- $caRef := default dict $ci.caCertificateRef -}} +{{- $caName := default "" $caRef.name -}} +{{- $caNs := default "" $caRef.namespace -}} +{{- if and $caName $caNs (ne $caNs $ns) }} +apiVersion: secrets.educates.dev/v1beta1 +kind: SecretCopier +metadata: + name: educates-node-ca-injector-secrets + labels: + {{- include "node-ca-injector.labels" . | nindent 4 }} +spec: + rules: + - sourceSecret: + name: {{ $caName | quote }} + namespace: {{ $caNs | quote }} + targetNamespaces: + nameSelector: + matchNames: + - {{ $ns | quote }} +{{- end }} diff --git a/installer/charts/educates-training-platform/charts/node-ca-injector/templates/serviceaccount.yaml b/installer/charts/educates-training-platform/charts/node-ca-injector/templates/serviceaccount.yaml new file mode 100644 index 000000000..ab5756465 --- /dev/null +++ b/installer/charts/educates-training-platform/charts/node-ca-injector/templates/serviceaccount.yaml @@ -0,0 +1,11 @@ +apiVersion: v1 +kind: ServiceAccount +metadata: + name: node-ca-injector + namespace: {{ .Release.Namespace }} + labels: + {{- include "node-ca-injector.labels" . | nindent 4 }} +{{- with .Values.imagePullSecrets }} +imagePullSecrets: + {{- toYaml . | nindent 2 }} +{{- end }} diff --git a/installer/charts/educates-training-platform/charts/node-ca-injector/values.schema.json b/installer/charts/educates-training-platform/charts/node-ca-injector/values.schema.json new file mode 100644 index 000000000..e6d0e021e --- /dev/null +++ b/installer/charts/educates-training-platform/charts/node-ca-injector/values.schema.json @@ -0,0 +1,88 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "Educates node-ca-injector subchart values", + "type": "object", + "additionalProperties": false, + "description": "Cross-cutting blocks (clusterIngress, imageRegistry) may come from the umbrella's `.global` instead of being set here. Subchart-local values pass through when globals are unset; globals win when both are set. Helpers enforce non-empty resolved values at template time.", + + "definitions": { + "imageRef": { + "description": "Image reference. Empty `repository` falls through to the imageRegistry-derived default; empty `tag` falls through to Chart.AppVersion.", + "type": "object", + "additionalProperties": false, + "properties": { + "repository": { "type": "string" }, + "tag": { "type": "string" }, + "pullPolicy": { + "type": "string", + "enum": ["", "Always", "IfNotPresent", "Never"] + } + } + }, + + "secretRef": { + "description": "Reference to a Kubernetes Secret. Empty `name` means the ref is unset.", + "type": "object", + "additionalProperties": false, + "properties": { + "name": { "type": "string" }, + "namespace": { "type": "string" } + } + }, + + "podResources": { + "type": "object", + "additionalProperties": false, + "properties": { + "resources": { "type": "object" } + } + } + }, + + "properties": { + "development": { + "description": "Local-development overrides. Leave empty in normal use — Chart.yaml annotations (`educates.dev/image-registry-{host,namespace}`) provide the publish-time defaults.", + "type": "object", + "additionalProperties": false, + "properties": { + "imageRegistry": { + "type": "object", + "additionalProperties": false, + "properties": { + "host": { "type": "string" }, + "namespace": { "type": "string" } + } + } + } + }, + + "image": { "$ref": "#/definitions/imageRef" }, + + "imagePullSecrets": { + "description": "Pod-spec imagePullSecrets attached to the controller and DaemonSet pods. Standard Kubernetes [{name: ...}] shape.", + "type": "array", + "items": { + "type": "object", + "additionalProperties": false, + "required": ["name"], + "properties": { + "name": { "type": "string", "minLength": 1 } + } + } + }, + + "clusterIngress": { + "type": "object", + "additionalProperties": false, + "properties": { + "caCertificateRef": { "$ref": "#/definitions/secretRef" } + } + }, + + "controller": { "$ref": "#/definitions/podResources" }, + "sync": { "$ref": "#/definitions/podResources" }, + + "enabled": { "type": "boolean" }, + "global": { "type": "object" } + } +} diff --git a/installer/charts/educates-training-platform/charts/node-ca-injector/values.yaml b/installer/charts/educates-training-platform/charts/node-ca-injector/values.yaml new file mode 100644 index 000000000..531733c9e --- /dev/null +++ b/installer/charts/educates-training-platform/charts/node-ca-injector/values.yaml @@ -0,0 +1,53 @@ +# Values for the node-ca-injector subchart. +# +# Renders a controller Deployment + privileged per-node DaemonSet that +# write containerd registry-CA configuration into /etc/containerd/certs.d +# so containerd can pull images from registries fronted by the cluster's +# private/self-signed CA. Default-OFF at the umbrella; opt in when a +# private CA is in use AND containerd-level trust is needed. + +# Local-development override. Leave empty in normal use — image refs +# resolve from Chart.yaml annotations (`educates.dev/image-registry-host` +# / `-namespace`) which the chart's publish workflow updates per fork. +development: + imageRegistry: + host: "" + namespace: "" + +image: + # Empty `repository` derives `{imageRegistry.host}/{imageRegistry.namespace}/educates-node-ca-injector`. + # Empty `tag` falls through to `Chart.AppVersion`. + repository: "" + tag: "" + pullPolicy: "" + +# Image pull secret references in the operator namespace. +imagePullSecrets: [] + +# Cluster-wide ingress identity. Same shape as the umbrella's +# `global.clusterIngress`; under the umbrella, set values there and they +# propagate here automatically. This subchart consumes `caCertificateRef` +# — without a Secret name, the rendered DaemonSet has nothing to mount and +# the chart fails fast at template time. +clusterIngress: + caCertificateRef: + name: "" + namespace: "" + +# Pod-level resource requests and limits for the controller Deployment +# and the per-node DaemonSet. +controller: + resources: + requests: + memory: "64Mi" + cpu: "50m" + limits: + memory: "128Mi" + +sync: + resources: + requests: + memory: "32Mi" + cpu: "10m" + limits: + memory: "64Mi" diff --git a/installer/charts/educates-training-platform/charts/remote-access/Chart.yaml b/installer/charts/educates-training-platform/charts/remote-access/Chart.yaml new file mode 100644 index 000000000..c4c112dd6 --- /dev/null +++ b/installer/charts/educates-training-platform/charts/remote-access/Chart.yaml @@ -0,0 +1,13 @@ +apiVersion: v2 +name: remote-access +description: | + Read-only ServiceAccount, ClusterRole, and long-lived + service-account-token Secret used by external clients (e.g., the + `educates` CLI used against a remote cluster) to discover + training.educates.dev resources. Independently toggleable so that + installs which need cross-cluster CLI access can opt in without + pulling in the lookup-service component. +type: application +version: 4.0.0-alpha.1 +appVersion: "3.7.1" +kubeVersion: ">=1.31.0-0" diff --git a/installer/charts/educates-training-platform/charts/remote-access/templates/_helpers.tpl b/installer/charts/educates-training-platform/charts/remote-access/templates/_helpers.tpl new file mode 100644 index 000000000..77328c37a --- /dev/null +++ b/installer/charts/educates-training-platform/charts/remote-access/templates/_helpers.tpl @@ -0,0 +1,9 @@ +{{- define "remote-access.labels" -}} +app.kubernetes.io/name: remote-access +app.kubernetes.io/instance: {{ .Release.Name }} +app.kubernetes.io/component: remote-access +app.kubernetes.io/part-of: educates +app.kubernetes.io/managed-by: {{ .Release.Service }} +app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} +helm.sh/chart: {{ printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} +{{- end -}} diff --git a/installer/charts/educates-training-platform/charts/remote-access/templates/clusterrole.yaml b/installer/charts/educates-training-platform/charts/remote-access/templates/clusterrole.yaml new file mode 100644 index 000000000..194ba0444 --- /dev/null +++ b/installer/charts/educates-training-platform/charts/remote-access/templates/clusterrole.yaml @@ -0,0 +1,33 @@ +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: educates-remote-access + labels: + {{- include "remote-access.labels" . | nindent 4 }} +rules: + - apiGroups: [training.educates.dev] + resources: + - trainingportals + - workshopenvironments + - workshopsessions + - workshopallocations + - workshops + verbs: [get, list, watch] + - apiGroups: [""] + resources: [customresourcedefinitions] + verbs: [get, list, watch] +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: educates-remote-access + labels: + {{- include "remote-access.labels" . | nindent 4 }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: educates-remote-access +subjects: + - kind: ServiceAccount + name: remote-access + namespace: {{ .Release.Namespace }} diff --git a/installer/charts/educates-training-platform/charts/remote-access/templates/serviceaccount.yaml b/installer/charts/educates-training-platform/charts/remote-access/templates/serviceaccount.yaml new file mode 100644 index 000000000..bc360fc5f --- /dev/null +++ b/installer/charts/educates-training-platform/charts/remote-access/templates/serviceaccount.yaml @@ -0,0 +1,21 @@ +apiVersion: v1 +kind: ServiceAccount +metadata: + name: remote-access + namespace: {{ .Release.Namespace }} + labels: + {{- include "remote-access.labels" . | nindent 4 }} +--- +# Long-lived service-account-token Secret. Manually created because +# Kubernetes 1.24+ no longer auto-generates these for ServiceAccounts. +# Mounted by the lookup-service Deployment when remote-access.enabled. +apiVersion: v1 +kind: Secret +metadata: + name: remote-access-token + namespace: {{ .Release.Namespace }} + annotations: + kubernetes.io/service-account.name: remote-access + labels: + {{- include "remote-access.labels" . | nindent 4 }} +type: kubernetes.io/service-account-token diff --git a/installer/charts/educates-training-platform/charts/remote-access/values.schema.json b/installer/charts/educates-training-platform/charts/remote-access/values.schema.json new file mode 100644 index 000000000..61ab582c9 --- /dev/null +++ b/installer/charts/educates-training-platform/charts/remote-access/values.schema.json @@ -0,0 +1,11 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "Educates remote-access subchart values", + "description": "Read-only RBAC surface for external CLI clients. No configurable knobs in v0.1.0 — enable/disable is the only control.", + "type": "object", + "additionalProperties": false, + "properties": { + "enabled": { "type": "boolean" }, + "global": { "type": "object" } + } +} diff --git a/installer/charts/educates-training-platform/charts/remote-access/values.yaml b/installer/charts/educates-training-platform/charts/remote-access/values.yaml new file mode 100644 index 000000000..1ac97d868 --- /dev/null +++ b/installer/charts/educates-training-platform/charts/remote-access/values.yaml @@ -0,0 +1,6 @@ +# Values for the remote-access subchart. +# +# This subchart has no configurable knobs in v0.1.0 — it produces a fixed +# set of resources (ServiceAccount, long-lived token Secret, ClusterRole, +# ClusterRoleBinding). Enable/disable is controlled by the umbrella's +# `remote-access.enabled` value. diff --git a/installer/charts/educates-training-platform/charts/secrets-manager/Chart.yaml b/installer/charts/educates-training-platform/charts/secrets-manager/Chart.yaml new file mode 100644 index 000000000..f24f7c2da --- /dev/null +++ b/installer/charts/educates-training-platform/charts/secrets-manager/Chart.yaml @@ -0,0 +1,13 @@ +apiVersion: v2 +name: secrets-manager +description: | + Educates secrets-manager component. Reconciles SecretCopier, SecretExporter, + SecretImporter, and SecretInjector resources to propagate secrets across + namespaces. +type: application +version: 4.0.0-alpha.1 +appVersion: "3.7.1" +annotations: + educates.dev/image-registry-host: "ghcr.io" + educates.dev/image-registry-namespace: "educates" +kubeVersion: ">=1.31.0-0" diff --git a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/educates/10-secrets-manager/01-crds-secretcopier.yaml b/installer/charts/educates-training-platform/charts/secrets-manager/crds/secretcopier.yaml similarity index 99% rename from carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/educates/10-secrets-manager/01-crds-secretcopier.yaml rename to installer/charts/educates-training-platform/charts/secrets-manager/crds/secretcopier.yaml index c59f268fb..f48d60011 100644 --- a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/educates/10-secrets-manager/01-crds-secretcopier.yaml +++ b/installer/charts/educates-training-platform/charts/secrets-manager/crds/secretcopier.yaml @@ -1,4 +1,3 @@ ---- apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: diff --git a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/educates/10-secrets-manager/01-crds-secretexporter.yaml b/installer/charts/educates-training-platform/charts/secrets-manager/crds/secretexporter.yaml similarity index 99% rename from carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/educates/10-secrets-manager/01-crds-secretexporter.yaml rename to installer/charts/educates-training-platform/charts/secrets-manager/crds/secretexporter.yaml index 644fccecb..2937c828d 100644 --- a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/educates/10-secrets-manager/01-crds-secretexporter.yaml +++ b/installer/charts/educates-training-platform/charts/secrets-manager/crds/secretexporter.yaml @@ -1,4 +1,3 @@ ---- apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: diff --git a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/educates/10-secrets-manager/01-crds-secretimporter.yaml b/installer/charts/educates-training-platform/charts/secrets-manager/crds/secretimporter.yaml similarity index 99% rename from carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/educates/10-secrets-manager/01-crds-secretimporter.yaml rename to installer/charts/educates-training-platform/charts/secrets-manager/crds/secretimporter.yaml index a8c3e6c4a..b28f05f8b 100644 --- a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/educates/10-secrets-manager/01-crds-secretimporter.yaml +++ b/installer/charts/educates-training-platform/charts/secrets-manager/crds/secretimporter.yaml @@ -1,4 +1,3 @@ ---- apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: diff --git a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/educates/10-secrets-manager/01-crds-secretinjector.yaml b/installer/charts/educates-training-platform/charts/secrets-manager/crds/secretinjector.yaml similarity index 99% rename from carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/educates/10-secrets-manager/01-crds-secretinjector.yaml rename to installer/charts/educates-training-platform/charts/secrets-manager/crds/secretinjector.yaml index bcd90559e..5e2353e1e 100644 --- a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/educates/10-secrets-manager/01-crds-secretinjector.yaml +++ b/installer/charts/educates-training-platform/charts/secrets-manager/crds/secretinjector.yaml @@ -1,4 +1,3 @@ ---- apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: diff --git a/installer/charts/educates-training-platform/charts/secrets-manager/templates/_helpers.tpl b/installer/charts/educates-training-platform/charts/secrets-manager/templates/_helpers.tpl new file mode 100644 index 000000000..6f404cef8 --- /dev/null +++ b/installer/charts/educates-training-platform/charts/secrets-manager/templates/_helpers.tpl @@ -0,0 +1,89 @@ +{{/* +Common labels applied to all resources rendered by this subchart. +*/}} +{{- define "secrets-manager.labels" -}} +app.kubernetes.io/name: secrets-manager +app.kubernetes.io/instance: {{ .Release.Name }} +app.kubernetes.io/component: secrets-manager +app.kubernetes.io/part-of: educates +app.kubernetes.io/managed-by: {{ .Release.Service }} +app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} +helm.sh/chart: {{ printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} +{{- end -}} + +{{/* +Selector labels — stable across upgrades, must not include the chart version. +*/}} +{{- define "secrets-manager.selectorLabels" -}} +deployment: secrets-manager +{{- end -}} + +{{/* +Resolve cross-cutting blocks (imageRegistry, clusterSecurity) by deep-merging +the umbrella's `global.` over this subchart's local block. Globals win +where set; subchart-local defaults pass through otherwise. Returned as a +YAML string — consume via `fromYaml`. +*/}} +{{- define "secrets-manager.resolvedImageRegistry" -}} +{{- $local := default dict (default dict .Values.development).imageRegistry -}} +{{- $global := default dict (default dict (default dict .Values.global).development).imageRegistry -}} +{{- $merged := mergeOverwrite (deepCopy $local) $global -}} +{{- if not $merged.host -}} + {{- $_ := set $merged "host" (index .Chart.Annotations "educates.dev/image-registry-host" | default "") -}} +{{- end -}} +{{- if not $merged.namespace -}} + {{- $_ := set $merged "namespace" (index .Chart.Annotations "educates.dev/image-registry-namespace" | default "") -}} +{{- end -}} +{{- toYaml $merged -}} +{{- end -}} + +{{- define "secrets-manager.resolvedClusterSecurity" -}} +{{- $local := default dict .Values.clusterSecurity -}} +{{- $global := default dict (default dict .Values.global).clusterSecurity -}} +{{- toYaml (mergeOverwrite (deepCopy $local) $global) -}} +{{- end -}} + +{{- define "secrets-manager.imageRegistryPrefix" -}} +{{- $ir := include "secrets-manager.resolvedImageRegistry" . | fromYaml -}} +{{- $host := default "" $ir.host -}} +{{- $ns := default "" $ir.namespace -}} +{{- if and $host $ns -}} +{{ $host }}/{{ $ns }} +{{- else if $host -}} +{{ $host }} +{{- else -}} +{{- fail "imageRegistry.host could not be resolved. Either set Chart.yaml annotation `educates.dev/image-registry-host` (publish-time default) or override locally via .development.imageRegistry / .global.development.imageRegistry." -}} +{{- end -}} +{{- end -}} + +{{- define "secrets-manager.image.repository" -}} +{{- if .Values.image.repository -}} +{{ .Values.image.repository }} +{{- else -}} +{{ include "secrets-manager.imageRegistryPrefix" . }}/educates-secrets-manager +{{- end -}} +{{- end -}} + +{{/* +Resolve the container image tag, defaulting to .Chart.AppVersion when unset. +*/}} +{{- define "secrets-manager.image.tag" -}} +{{- default .Chart.AppVersion .Values.image.tag -}} +{{- end -}} + +{{/* +Auto-derive imagePullPolicy: Always for floating tags, IfNotPresent otherwise. +An explicit pullPolicy in values wins. +*/}} +{{- define "secrets-manager.image.pullPolicy" -}} +{{- if .Values.image.pullPolicy -}} +{{ .Values.image.pullPolicy }} +{{- else -}} +{{- $tag := include "secrets-manager.image.tag" . -}} +{{- if or (eq $tag "latest") (eq $tag "main") (eq $tag "master") (eq $tag "develop") -}} +Always +{{- else -}} +IfNotPresent +{{- end -}} +{{- end -}} +{{- end -}} diff --git a/installer/charts/educates-training-platform/charts/secrets-manager/templates/clusterrole.yaml b/installer/charts/educates-training-platform/charts/secrets-manager/templates/clusterrole.yaml new file mode 100644 index 000000000..ad179ee00 --- /dev/null +++ b/installer/charts/educates-training-platform/charts/secrets-manager/templates/clusterrole.yaml @@ -0,0 +1,25 @@ +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: educates-secrets-manager + labels: + {{- include "secrets-manager.labels" . | nindent 4 }} +rules: + - apiGroups: [""] + resources: [events] + verbs: [create] + - apiGroups: [""] + resources: [secrets] + verbs: [get, list, watch, create, delete, deletecollection, patch, update] + - apiGroups: [""] + resources: [namespaces] + verbs: [get, list, watch] + - apiGroups: [""] + resources: [serviceaccounts] + verbs: [get, list, watch, patch, update] + - apiGroups: [secrets.educates.dev] + resources: [secretcopiers, secretexporters, secretimporters, secretinjectors] + verbs: [get, list, watch, patch, update] + - apiGroups: [secrets.educates.dev] + resources: [secretcopiers/finalizers, secretimporters/finalizers] + verbs: [update] diff --git a/installer/charts/educates-training-platform/charts/secrets-manager/templates/clusterrolebinding.yaml b/installer/charts/educates-training-platform/charts/secrets-manager/templates/clusterrolebinding.yaml new file mode 100644 index 000000000..004ca6d36 --- /dev/null +++ b/installer/charts/educates-training-platform/charts/secrets-manager/templates/clusterrolebinding.yaml @@ -0,0 +1,36 @@ +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: educates-secrets-manager + labels: + {{- include "secrets-manager.labels" . | nindent 4 }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: educates-secrets-manager +subjects: + - kind: ServiceAccount + name: secrets-manager + namespace: {{ .Release.Namespace }} +{{- $cs := include "secrets-manager.resolvedClusterSecurity" . | fromYaml }} +{{- if eq $cs.policyEngine "OpenShiftSCC" }} +--- +# OpenShift only. Binds the secrets-manager ServiceAccount to the cluster's +# baseline SCC ClusterRole. The `educates-baseline-scc` ClusterRole itself +# is expected to be installed out-of-band (or by a future operator-managed +# step); this binding only takes effect on a cluster where it exists. +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: educates-secrets-manager-scc + labels: + {{- include "secrets-manager.labels" . | nindent 4 }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: educates-baseline-scc +subjects: + - kind: ServiceAccount + name: secrets-manager + namespace: {{ .Release.Namespace }} +{{- end }} diff --git a/installer/charts/educates-training-platform/charts/secrets-manager/templates/deployment.yaml b/installer/charts/educates-training-platform/charts/secrets-manager/templates/deployment.yaml new file mode 100644 index 000000000..456ce6a7c --- /dev/null +++ b/installer/charts/educates-training-platform/charts/secrets-manager/templates/deployment.yaml @@ -0,0 +1,70 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: secrets-manager + namespace: {{ .Release.Namespace }} + labels: + {{- include "secrets-manager.labels" . | nindent 4 }} +spec: + replicas: 1 + strategy: + type: Recreate + selector: + matchLabels: + {{- include "secrets-manager.selectorLabels" . | nindent 6 }} + template: + metadata: + labels: + {{- include "secrets-manager.labels" . | nindent 8 }} + {{- include "secrets-manager.selectorLabels" . | nindent 8 }} + spec: + serviceAccountName: secrets-manager + automountServiceAccountToken: false + {{- with .Values.imagePullSecrets }} + imagePullSecrets: + {{- toYaml . | nindent 8 }} + {{- end }} + securityContext: + runAsNonRoot: true + runAsUser: 1001 + containers: + - name: operator + image: "{{ include "secrets-manager.image.repository" . }}:{{ include "secrets-manager.image.tag" . }}" + imagePullPolicy: {{ include "secrets-manager.image.pullPolicy" . }} + env: + - name: LOG_LEVEL + value: {{ .Values.logLevel | quote }} + securityContext: + allowPrivilegeEscalation: false + capabilities: + drop: ["ALL"] + startupProbe: + httpGet: + path: /healthz?probe=startup + port: 8080 + initialDelaySeconds: 15 + periodSeconds: 10 + timeoutSeconds: 5 + successThreshold: 1 + failureThreshold: 4 + livenessProbe: + httpGet: + path: /healthz?probe=liveness + port: 8080 + initialDelaySeconds: 15 + periodSeconds: 30 + timeoutSeconds: 5 + successThreshold: 1 + failureThreshold: 3 + {{- with .Values.resources }} + resources: + {{- toYaml . | nindent 12 }} + {{- end }} + volumeMounts: + - name: token + mountPath: /var/run/secrets/kubernetes.io/serviceaccount + readOnly: true + volumes: + - name: token + secret: + secretName: secrets-manager-token diff --git a/installer/charts/educates-training-platform/charts/secrets-manager/templates/serviceaccount.yaml b/installer/charts/educates-training-platform/charts/secrets-manager/templates/serviceaccount.yaml new file mode 100644 index 000000000..9108edb83 --- /dev/null +++ b/installer/charts/educates-training-platform/charts/secrets-manager/templates/serviceaccount.yaml @@ -0,0 +1,24 @@ +apiVersion: v1 +kind: ServiceAccount +metadata: + name: secrets-manager + namespace: {{ .Release.Namespace }} + labels: + {{- include "secrets-manager.labels" . | nindent 4 }} +--- +# Long-lived service account token. Created explicitly because Kubernetes +# 1.24+ no longer auto-generates these for ServiceAccounts. The +# secrets-manager Deployment disables automountServiceAccountToken and +# mounts this Secret at the standard token path so the kopf-based Python +# operator gets a stable, non-rotating token. Behaviour preserved +# unchanged from v3. +apiVersion: v1 +kind: Secret +metadata: + name: secrets-manager-token + namespace: {{ .Release.Namespace }} + annotations: + kubernetes.io/service-account.name: secrets-manager + labels: + {{- include "secrets-manager.labels" . | nindent 4 }} +type: kubernetes.io/service-account-token diff --git a/installer/charts/educates-training-platform/charts/secrets-manager/values.schema.json b/installer/charts/educates-training-platform/charts/secrets-manager/values.schema.json new file mode 100644 index 000000000..d1534a83b --- /dev/null +++ b/installer/charts/educates-training-platform/charts/secrets-manager/values.schema.json @@ -0,0 +1,73 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "Educates secrets-manager subchart values", + "type": "object", + "additionalProperties": false, + + "definitions": { + "imageRef": { + "description": "Image reference. Empty `repository` falls through to the imageRegistry-derived default; empty `tag` falls through to Chart.AppVersion.", + "type": "object", + "additionalProperties": false, + "properties": { + "repository": { "type": "string" }, + "tag": { "type": "string" }, + "pullPolicy": { + "type": "string", + "enum": ["", "Always", "IfNotPresent", "Never"] + } + } + } + }, + + "properties": { + "development": { + "description": "Local-development overrides. Leave empty in normal use — Chart.yaml annotations (`educates.dev/image-registry-{host,namespace}`) provide the publish-time defaults.", + "type": "object", + "additionalProperties": false, + "properties": { + "imageRegistry": { + "type": "object", + "additionalProperties": false, + "properties": { + "host": { "type": "string" }, + "namespace": { "type": "string" } + } + } + } + }, + + "image": { "$ref": "#/definitions/imageRef" }, + + "imagePullSecrets": { + "description": "Pod-spec imagePullSecrets attached to the secrets-manager pod itself. Standard Kubernetes [{name: ...}] shape.", + "type": "array", + "items": { + "type": "object", + "additionalProperties": false, + "required": ["name"], + "properties": { + "name": { "type": "string", "minLength": 1 } + } + } + }, + + "resources": { "type": "object" }, + + "clusterSecurity": { + "type": "object", + "additionalProperties": false, + "properties": { + "policyEngine": { + "type": "string", + "enum": ["Kyverno", "PodSecurityStandards", "OpenShiftSCC", "None"] + } + } + }, + + "logLevel": { "type": "string" }, + + "enabled": { "type": "boolean" }, + "global": { "type": "object" } + } +} diff --git a/installer/charts/educates-training-platform/charts/secrets-manager/values.yaml b/installer/charts/educates-training-platform/charts/secrets-manager/values.yaml new file mode 100644 index 000000000..dd21ae3ac --- /dev/null +++ b/installer/charts/educates-training-platform/charts/secrets-manager/values.yaml @@ -0,0 +1,42 @@ +# Values for the secrets-manager subchart. +# +# In a v4 install the operator derives these values from the SecretsManager +# CR (and EducatesClusterConfig.status). They can also be set directly when +# installing the chart standalone. + +# Local-development override. Leave empty in normal use — image refs +# resolve from Chart.yaml annotations (`educates.dev/image-registry-host` +# / `-namespace`) which the chart's publish workflow updates per fork. +# Override at the umbrella level under `global.development.imageRegistry` +# to redirect every Educates-image reference (across all subcharts) in +# one knob. +development: + imageRegistry: + host: "" + namespace: "" + +image: + # Empty `repository` derives `{imageRegistry.host}/{imageRegistry.namespace}/educates-secrets-manager`. + # Empty `tag` falls through to `Chart.AppVersion`. + repository: "" + tag: "" + pullPolicy: "" + +# Image pull secret references in the operator namespace. Each entry is a +# Kubernetes LocalObjectReference: { name: }. +imagePullSecrets: [] + +# Pod-level resource requests and limits. +resources: {} + +# Cluster-level security policy enforcement. Only `OpenShiftSCC` triggers +# this subchart to render anything (a ClusterRoleBinding for the secrets- +# manager ServiceAccount to the `educates-baseline-scc` ClusterRole). +# Other values are no-ops here — full enforcement lives in the session- +# manager subchart and the umbrella's `global.clusterSecurity`. This local +# block exists for standalone installs. +clusterSecurity: + policyEngine: Kyverno # Kyverno | PodSecurityStandards | OpenShiftSCC | None + +# Operator log level. +logLevel: info diff --git a/installer/charts/educates-training-platform/charts/session-manager/Chart.yaml b/installer/charts/educates-training-platform/charts/session-manager/Chart.yaml new file mode 100644 index 000000000..fa7c3e10d --- /dev/null +++ b/installer/charts/educates-training-platform/charts/session-manager/Chart.yaml @@ -0,0 +1,19 @@ +apiVersion: v2 +name: session-manager +description: | + Educates session-manager component. Reconciles Workshop, WorkshopEnvironment, + WorkshopSession, WorkshopRequest, WorkshopAllocation, and TrainingPortal + resources, and ships the supporting services (training-portal, assets-server, + image-cache, docker-registry). +type: application +version: 4.0.0-alpha.1 +appVersion: "3.7.1" +kubeVersion: ">=1.31.0-0" +annotations: + # Publish-time defaults for the registry that hosts Educates images. The + # release workflow updates these per fork (via `yq -i`) so the chart that + # gets shipped points at the right registry without a values override. + # Override at install time only via `development.imageRegistry` (a + # local-dev knob — see values.yaml). + educates.dev/image-registry-host: "ghcr.io" + educates.dev/image-registry-namespace: "educates" diff --git a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/educates/11-session-manager/01-crds-trainingportal.yaml b/installer/charts/educates-training-platform/charts/session-manager/crds/trainingportal.yaml similarity index 99% rename from carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/educates/11-session-manager/01-crds-trainingportal.yaml rename to installer/charts/educates-training-platform/charts/session-manager/crds/trainingportal.yaml index bca36e39c..4ca1f5471 100644 --- a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/educates/11-session-manager/01-crds-trainingportal.yaml +++ b/installer/charts/educates-training-platform/charts/session-manager/crds/trainingportal.yaml @@ -1,4 +1,3 @@ ---- apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: diff --git a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/educates/11-session-manager/01-crds-workshop.yaml b/installer/charts/educates-training-platform/charts/session-manager/crds/workshop.yaml similarity index 99% rename from carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/educates/11-session-manager/01-crds-workshop.yaml rename to installer/charts/educates-training-platform/charts/session-manager/crds/workshop.yaml index 204ac3876..4a7f7a706 100644 --- a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/educates/11-session-manager/01-crds-workshop.yaml +++ b/installer/charts/educates-training-platform/charts/session-manager/crds/workshop.yaml @@ -1,4 +1,3 @@ ---- apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: diff --git a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/educates/11-session-manager/01-crds-workshopallocation.yaml b/installer/charts/educates-training-platform/charts/session-manager/crds/workshopallocation.yaml similarity index 99% rename from carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/educates/11-session-manager/01-crds-workshopallocation.yaml rename to installer/charts/educates-training-platform/charts/session-manager/crds/workshopallocation.yaml index 88ac887a2..04b6b7db7 100644 --- a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/educates/11-session-manager/01-crds-workshopallocation.yaml +++ b/installer/charts/educates-training-platform/charts/session-manager/crds/workshopallocation.yaml @@ -1,4 +1,3 @@ ---- apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: diff --git a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/educates/11-session-manager/01-crds-workshopenvironment.yaml b/installer/charts/educates-training-platform/charts/session-manager/crds/workshopenvironment.yaml similarity index 99% rename from carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/educates/11-session-manager/01-crds-workshopenvironment.yaml rename to installer/charts/educates-training-platform/charts/session-manager/crds/workshopenvironment.yaml index f52551dec..22b158f21 100644 --- a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/educates/11-session-manager/01-crds-workshopenvironment.yaml +++ b/installer/charts/educates-training-platform/charts/session-manager/crds/workshopenvironment.yaml @@ -1,4 +1,3 @@ ---- apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: diff --git a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/educates/11-session-manager/01-crds-workshoprequest.yaml b/installer/charts/educates-training-platform/charts/session-manager/crds/workshoprequest.yaml similarity index 99% rename from carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/educates/11-session-manager/01-crds-workshoprequest.yaml rename to installer/charts/educates-training-platform/charts/session-manager/crds/workshoprequest.yaml index 268e8dd71..0920454c0 100644 --- a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/educates/11-session-manager/01-crds-workshoprequest.yaml +++ b/installer/charts/educates-training-platform/charts/session-manager/crds/workshoprequest.yaml @@ -1,4 +1,3 @@ ---- apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: diff --git a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/educates/11-session-manager/01-crds-workshopsession.yaml b/installer/charts/educates-training-platform/charts/session-manager/crds/workshopsession.yaml similarity index 99% rename from carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/educates/11-session-manager/01-crds-workshopsession.yaml rename to installer/charts/educates-training-platform/charts/session-manager/crds/workshopsession.yaml index 577f9edb4..bc703beb1 100644 --- a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/educates/11-session-manager/01-crds-workshopsession.yaml +++ b/installer/charts/educates-training-platform/charts/session-manager/crds/workshopsession.yaml @@ -1,4 +1,3 @@ ---- apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: diff --git a/installer/charts/educates-training-platform/charts/session-manager/files/kyverno-policies/README.md b/installer/charts/educates-training-platform/charts/session-manager/files/kyverno-policies/README.md new file mode 100644 index 000000000..35ee8f07e --- /dev/null +++ b/installer/charts/educates-training-platform/charts/session-manager/files/kyverno-policies/README.md @@ -0,0 +1,89 @@ +# Bundled Kyverno workshop policies + +These are **Kyverno `ValidatingPolicy` resources** (`policies.kyverno.io`), +the policy type Kyverno 1.18 recommends in place of the legacy `ClusterPolicy` +(`kyverno.io`). Two independent paths, mirroring v3's split between +`01-clusterpolicies.yaml` and `06-secrets.yaml`: + +## `cluster-policies/` — applied cluster-wide + +Vendored from +[kyverno/policies](https://github.com/kyverno/policies) +(`origin/release-1.18`, matching the Kyverno version the operator bundles — +see `KyvernoAppVersion` in `installer/operator/vendored-charts/embed.go`), +from the `pod-security-vpol` set. Both Pod Security Standards profiles are +installed unconditionally as `ValidatingPolicy` resources when +`clusterSecurity.policyEngine: Kyverno` — workshops don't pick a profile, so +both must be present. Action is `Audit` (`validationActions: [Audit]`), +inherited from upstream. + +| Directory | Source | What it covers | +|---|---|---| +| `cluster-policies/baseline/` | `pod-security-vpol/baseline/*` | Pod Security Standards baseline | +| `cluster-policies/restricted/` | `pod-security-vpol/restricted/*` | Pod Security Standards restricted | + +The upstream `pod-security-vpol` baseline drops the `disallow-host-ports-range` +"Alternate" policy that the CEL set carried; it folds into `disallow-host-ports`. +We follow that curation (these are `Audit`-only cluster-wide, so no enforcement +change). + +## `workshop-policies/` — bundled into the educates-config Secret + +Concatenated into the `kyverno-policies.yaml` Secret key when +`workshopSecurity.rulesEngine: Kyverno`. session-manager reads the stream and +creates a **per-workshop-environment copy** of each policy, scoped to the +environment's session namespaces via `spec.matchConstraints.namespaceSelector` +(see `session-manager/handlers/kyverno_rules.py`). They are **not** applied +cluster-wide — only as `educates-environment--` ValidatingPolicies +once a workshop is created. The per-env action follows the workshop's +`session.namespaces.security.rules.action` (`Enforce` → `Deny`, `Audit` → +`Audit`), overriding the bundled file's own action. + +| File pattern | Source | +|---|---| +| `disallow-cri-sock-mount.yaml`, `disallow-empty-ingress-host.yaml`, `restrict-service-external-ips.yaml`, `restrict-node-port.yaml` | `kyverno/policies` `best-practices-vpol/*` | +| `disallow-localhost-services.yaml`, `prevent-cr8escape.yaml`, `restrict-loadbalancer.yaml` | `kyverno/policies` `other-vpol/*` | +| `disallow-ingress-nginx-custom-snippets.yaml`, `restrict-annotations.yaml`, `restrict-ingress-paths.yaml` | Hand-ported to `ValidatingPolicy` from `nginx-ingress-cel/*` (no upstream `-vpol` variant exists) | +| `require-ingress-session-name.yaml` | Educates-internal; rewritten from the legacy JMESPath ClusterPolicy to `ValidatingPolicy` CEL (reads the session name from `namespaceObject`) | + +## User-supplied workshop policies and the ClusterPolicy deprecation + +`workshopSecurity.additionalKyvernoPolicies` entries flow through the same +per-workshop scoping. A new Policy type (`ValidatingPolicy`, etc.) is scoped +natively. A legacy `ClusterPolicy` is **still scoped but deprecated**: the +runtime logs a warning and continues. This tracks Kyverno's own timeline — +`ClusterPolicy` is deprecated in 1.18 and removed in 1.20 — and Educates will +drop support for workshop-provided ClusterPolicies on the same schedule. +Migrate them to `ValidatingPolicy`. + +## Hand-ported policies + +The three nginx-ingress policies and `require-ingress-session-name` have no +upstream `-vpol` variant, so they are maintained here by hand. When refreshing, +do **not** overwrite them from upstream. `disallow-ingress-nginx-custom-snippets` +matches both ConfigMap and Ingress; its two original rules became one policy +whose validations are each guarded by `request.kind.kind`. These are +security-critical CEL — validate against real resources, not just rendering. + +## Refreshing the bundle + +Re-vendor whenever the bundled Kyverno chart is bumped in +`installer/operator/vendored-charts/` — the branch must match the new +`KyvernoAppVersion` (e.g. Kyverno `v1.18.x` → branch `release-1.18`). + +1. Clone the matching release branch: + `git clone --depth 1 --branch release-1.NN https://github.com/kyverno/policies` +2. Replace the YAML under `cluster-policies/` and `workshop-policies/` from the + `*-vpol` directories, keeping filenames flat — drop the per-policy subdirs + and the `kustomization.yaml` / `.chainsaw-test` / `.kyverno-test` / + `artifacthub-pkg.yml` helpers. Copy only the files listed in the tables + above; leave the four hand-ported policies untouched. +3. `helm template` the session-manager chart with + `--set global.clusterSecurity.policyEngine=Kyverno + --set workshopSecurity.rulesEngine=Kyverno`; confirm the cluster-policies + render as `ValidatingPolicy`, the `kyverno-policies.yaml` Secret key renders, + and the policy *names* inside the stream are unchanged (the runtime names the + per-env copies after them, and workshop `exclude` lists reference them). +4. `make -C installer/operator package-local-charts` to refresh the embedded + session-manager subchart tarball the operator ships. +5. Update the branch reference and the source tables above. diff --git a/installer/charts/educates-training-platform/charts/session-manager/files/kyverno-policies/cluster-policies/baseline/disallow-capabilities.yaml b/installer/charts/educates-training-platform/charts/session-manager/files/kyverno-policies/cluster-policies/baseline/disallow-capabilities.yaml new file mode 100644 index 000000000..9923b375d --- /dev/null +++ b/installer/charts/educates-training-platform/charts/session-manager/files/kyverno-policies/cluster-policies/baseline/disallow-capabilities.yaml @@ -0,0 +1,43 @@ +apiVersion: policies.kyverno.io/v1alpha1 +kind: ValidatingPolicy +metadata: + name: disallow-capabilities + annotations: + policies.kyverno.io/title: Disallow Capabilities in ValidatingPolicy + policies.kyverno.io/category: Pod Security Standards (Baseline) in ValidatingPolicy + policies.kyverno.io/severity: medium + policies.kyverno.io/minversion: 1.14.0 + kyverno.io/kubernetes-version: "1.30+" + policies.kyverno.io/subject: Pod + policies.kyverno.io/description: >- + Adding capabilities beyond those listed in the policy must be disallowed. +spec: + validationActions: + - Audit + evaluation: + background: + enabled: true + matchConstraints: + resourceRules: + - apiGroups: [""] + apiVersions: ["v1"] + operations: ["CREATE", "UPDATE"] + resources: ["pods"] + variables: + - name: allowedCapabilities + expression: >- + ['AUDIT_WRITE','CHOWN','DAC_OVERRIDE','FOWNER','FSETID','KILL','MKNOD','NET_BIND_SERVICE','SETFCAP','SETGID','SETPCAP','SETUID','SYS_CHROOT'] + - name: allContainers + expression: >- + (object.spec.containers + + object.spec.?initContainers.orValue([]) + + object.spec.?ephemeralContainers.orValue([])) + validations: + - expression: >- + variables.allContainers.all(container, + container.?securityContext.?capabilities.?add.orValue([]).all(capability, capability == '' || + capability in variables.allowedCapabilities)) + message: >- + Any capabilities added beyond the allowed list (AUDIT_WRITE, CHOWN, DAC_OVERRIDE, FOWNER, + FSETID, KILL, MKNOD, NET_BIND_SERVICE, SETFCAP, SETGID, SETPCAP, SETUID, SYS_CHROOT) + are disallowed. diff --git a/installer/charts/educates-training-platform/charts/session-manager/files/kyverno-policies/cluster-policies/baseline/disallow-host-namespaces.yaml b/installer/charts/educates-training-platform/charts/session-manager/files/kyverno-policies/cluster-policies/baseline/disallow-host-namespaces.yaml new file mode 100644 index 000000000..460ae049d --- /dev/null +++ b/installer/charts/educates-training-platform/charts/session-manager/files/kyverno-policies/cluster-policies/baseline/disallow-host-namespaces.yaml @@ -0,0 +1,41 @@ +apiVersion: policies.kyverno.io/v1alpha1 +kind: ValidatingPolicy +metadata: + name: disallow-host-namespaces + annotations: + policies.kyverno.io/title: Disallow Host Namespaces in ValidatingPolicy + policies.kyverno.io/category: Pod Security Standards (Baseline) in ValidatingPolicy + policies.kyverno.io/severity: medium + policies.kyverno.io/minversion: 1.14.0 + kyverno.io/kubernetes-version: "1.30+" + policies.kyverno.io/subject: Pod + policies.kyverno.io/description: >- + Host namespaces (Process ID namespace, Inter-Process Communication namespace, and + network namespace) allow access to shared information and can be used to elevate + privileges. Pods should not be allowed access to host namespaces. This policy ensures + fields which make use of these host namespaces are unset or set to `false`. +spec: + validationActions: + - Audit + evaluation: + background: + enabled: true + matchConstraints: + resourceRules: + - apiGroups: [""] + apiVersions: ["v1"] + operations: ["CREATE", "UPDATE"] + resources: ["pods"] + variables: + - name: hostNetwork + expression: "object.spec.?hostNetwork.orValue(false)" + - name: hostIPC + expression: "object.spec.?hostIPC.orValue(false)" + - name: hostPID + expression: "object.spec.?hostPID.orValue(false)" + validations: + - expression: >- + !(variables.hostNetwork || variables.hostIPC || variables.hostPID) + message: >- + Sharing the host namespaces is disallowed. The fields spec.hostNetwork, + spec.hostIPC, and spec.hostPID must be unset or set to `false`. diff --git a/installer/charts/educates-training-platform/charts/session-manager/files/kyverno-policies/cluster-policies/baseline/disallow-host-path.yaml b/installer/charts/educates-training-platform/charts/session-manager/files/kyverno-policies/cluster-policies/baseline/disallow-host-path.yaml new file mode 100644 index 000000000..1218234ff --- /dev/null +++ b/installer/charts/educates-training-platform/charts/session-manager/files/kyverno-policies/cluster-policies/baseline/disallow-host-path.yaml @@ -0,0 +1,32 @@ +apiVersion: policies.kyverno.io/v1alpha1 +kind: ValidatingPolicy +metadata: + name: disallow-host-path + annotations: + policies.kyverno.io/title: Disallow hostPath in ValidatingPolicy + policies.kyverno.io/category: Pod Security Standards (Baseline) in ValidatingPolicy + policies.kyverno.io/severity: medium + policies.kyverno.io/subject: Pod,Volume + policies.kyverno.io/minversion: 1.14.0 + kyverno.io/kubernetes-version: "1.30+" + policies.kyverno.io/description: >- + HostPath volumes let Pods use host directories and volumes in containers. + Using host resources can be used to access shared data or escalate privileges + and should not be allowed. This policy ensures no hostPath volumes are in use. +spec: + validationActions: + - Audit + evaluation: + background: + enabled: true + matchConstraints: + resourceRules: + - apiGroups: [""] + apiVersions: ["v1"] + operations: ["CREATE", "UPDATE"] + resources: ["pods"] + validations: + - expression: >- + object.spec.?volumes.orValue([]).all(volume, !has(volume.hostPath)) + message: >- + HostPath volumes are forbidden. The field spec.volumes[*].hostPath must be unset diff --git a/installer/charts/educates-training-platform/charts/session-manager/files/kyverno-policies/cluster-policies/baseline/disallow-host-ports.yaml b/installer/charts/educates-training-platform/charts/session-manager/files/kyverno-policies/cluster-policies/baseline/disallow-host-ports.yaml new file mode 100644 index 000000000..fa3e0d32d --- /dev/null +++ b/installer/charts/educates-training-platform/charts/session-manager/files/kyverno-policies/cluster-policies/baseline/disallow-host-ports.yaml @@ -0,0 +1,40 @@ +apiVersion: policies.kyverno.io/v1alpha1 +kind: ValidatingPolicy +metadata: + name: disallow-host-ports + annotations: + policies.kyverno.io/title: Disallow hostPorts in ValidatingPolicy + policies.kyverno.io/category: Pod Security Standards (Baseline) in ValidatingPolicy + policies.kyverno.io/severity: medium + policies.kyverno.io/subject: Pod + policies.kyverno.io/minversion: 1.14.0 + kyverno.io/kubernetes-version: "1.30+" + policies.kyverno.io/description: >- + Access to host ports allows potential snooping of network traffic and should not be + allowed, or at minimum restricted to a known list. This policy ensures the `hostPort` + field is unset or set to `0`. +spec: + validationActions: + - Audit + evaluation: + background: + enabled: true + matchConstraints: + resourceRules: + - apiGroups: [""] + apiVersions: ["v1"] + operations: ["CREATE", "UPDATE"] + resources: ["pods"] + variables: + - name: allContainers + expression: >- + object.spec.containers + + object.spec.?initContainers.orValue([]) + + object.spec.?ephemeralContainers.orValue([]) + validations: + - expression: >- + variables.allContainers.all(container, + container.?ports.orValue([]).all(port, port.?hostPort.orValue(0) == 0)) + message: >- + Use of host ports is disallowed. The field spec.containers[*].ports[*].hostPort + must either be unset or set to `0`. \ No newline at end of file diff --git a/installer/charts/educates-training-platform/charts/session-manager/files/kyverno-policies/cluster-policies/baseline/disallow-host-process.yaml b/installer/charts/educates-training-platform/charts/session-manager/files/kyverno-policies/cluster-policies/baseline/disallow-host-process.yaml new file mode 100644 index 000000000..8fd97d5b2 --- /dev/null +++ b/installer/charts/educates-training-platform/charts/session-manager/files/kyverno-policies/cluster-policies/baseline/disallow-host-process.yaml @@ -0,0 +1,43 @@ +apiVersion: policies.kyverno.io/v1alpha1 +kind: ValidatingPolicy +metadata: + name: disallow-host-process + annotations: + policies.kyverno.io/title: Disallow hostProcess in ValidatingPolicy + policies.kyverno.io/category: Pod Security Standards (Baseline) in ValidatingPolicy + policies.kyverno.io/severity: medium + policies.kyverno.io/subject: Pod + policies.kyverno.io/minversion: 1.14.0 + kyverno.io/kubernetes-version: "1.30+" + policies.kyverno.io/description: >- + Windows pods offer the ability to run HostProcess containers which enables privileged + access to the Windows node. Privileged access to the host is disallowed in the baseline + policy. HostProcess pods are an alpha feature as of Kubernetes v1.22. This policy ensures + the `hostProcess` field, if present, is set to `false`. +spec: + validationActions: + - Audit + evaluation: + background: + enabled: true + matchConstraints: + resourceRules: + - apiGroups: [""] + apiVersions: ["v1"] + operations: ["CREATE", "UPDATE"] + resources: ["pods"] + variables: + - name: allContainers + expression: >- + object.spec.containers + + object.spec.?initContainers.orValue([]) + + object.spec.?ephemeralContainers.orValue([]) + validations: + - expression: >- + variables.allContainers.all(container, + container.?securityContext.?windowsOptions.?hostProcess.orValue(false) == false) + message: >- + HostProcess containers are disallowed. The field spec.containers[*].securityContext.windowsOptions.hostProcess, + spec.initContainers[*].securityContext.windowsOptions.hostProcess, and + spec.ephemeralContainers[*].securityContext.windowsOptions.hostProcess + must either be undefined or set to `false`. diff --git a/installer/charts/educates-training-platform/charts/session-manager/files/kyverno-policies/cluster-policies/baseline/disallow-privileged-containers.yaml b/installer/charts/educates-training-platform/charts/session-manager/files/kyverno-policies/cluster-policies/baseline/disallow-privileged-containers.yaml new file mode 100644 index 000000000..a5065bad3 --- /dev/null +++ b/installer/charts/educates-training-platform/charts/session-manager/files/kyverno-policies/cluster-policies/baseline/disallow-privileged-containers.yaml @@ -0,0 +1,36 @@ +apiVersion: policies.kyverno.io/v1alpha1 +kind: ValidatingPolicy +metadata: + name: disallow-privileged-containers + annotations: + policies.kyverno.io/title: Disallow Privileged Containers in ValidatingPolicy + policies.kyverno.io/category: Pod Security Standards (Baseline) in ValidatingPolicy + policies.kyverno.io/severity: medium + policies.kyverno.io/subject: Pod + policies.kyverno.io/minversion: 1.14.0 + kyverno.io/kyverno-version: 1.14.0 + kyverno.io/kubernetes-version: "1.30+" + policies.kyverno.io/description: >- + Privileged mode disables most security mechanisms and must not be allowed. This policy + ensures Pods do not call for privileged mode. +spec: + validationActions: + - Audit + evaluation: + background: + enabled: true + matchConstraints: + resourceRules: + - apiGroups: [""] + apiVersions: ["v1"] + operations: ["CREATE", "UPDATE"] + resources: ["pods"] + variables: + - name: allContainers + expression: >- + object.spec.containers + + object.spec.?initContainers.orValue([]) + + object.spec.?ephemeralContainers.orValue([]) + validations: + - expression: "variables.allContainers.all(container, container.?securityContext.?privileged.orValue(false) == false)" + message: "Privileged mode is disallowed. All containers must set the securityContext.privileged field to `false` or unset the field." \ No newline at end of file diff --git a/installer/charts/educates-training-platform/charts/session-manager/files/kyverno-policies/cluster-policies/baseline/disallow-proc-mount.yaml b/installer/charts/educates-training-platform/charts/session-manager/files/kyverno-policies/cluster-policies/baseline/disallow-proc-mount.yaml new file mode 100644 index 000000000..cec810f72 --- /dev/null +++ b/installer/charts/educates-training-platform/charts/session-manager/files/kyverno-policies/cluster-policies/baseline/disallow-proc-mount.yaml @@ -0,0 +1,38 @@ +apiVersion: policies.kyverno.io/v1alpha1 +kind: ValidatingPolicy +metadata: + name: disallow-proc-mount + annotations: + policies.kyverno.io/title: Disallow procMount in ValidatingPolicy + policies.kyverno.io/category: Pod Security Standards (Baseline) in ValidatingPolicy + policies.kyverno.io/severity: medium + policies.kyverno.io/subject: Pod + policies.kyverno.io/minversion: 1.14.0 + kyverno.io/kyverno-version: 1.14.0 + kyverno.io/kubernetes-version: "1.30+" + policies.kyverno.io/description: >- + The default /proc masks are set up to reduce attack surface and should be required. This policy + ensures nothing but the default procMount can be specified. Note that in order for users + to deviate from the `Default` procMount requires setting a feature gate at the API + server. +spec: + validationActions: + - Audit + evaluation: + background: + enabled: true + matchConstraints: + resourceRules: + - apiGroups: [""] + apiVersions: ["v1"] + operations: ["CREATE", "UPDATE"] + resources: ["pods"] + variables: + - name: allContainers + expression: >- + object.spec.containers + + object.spec.?initContainers.orValue([]) + + object.spec.?ephemeralContainers.orValue([]) + validations: + - expression: "variables.allContainers.all(container, container.?securityContext.?procMount.orValue('Default') == 'Default')" + message: "Changing the proc mount from the default is not allowed." \ No newline at end of file diff --git a/installer/charts/educates-training-platform/charts/session-manager/files/kyverno-policies/cluster-policies/baseline/disallow-selinux.yaml b/installer/charts/educates-training-platform/charts/session-manager/files/kyverno-policies/cluster-policies/baseline/disallow-selinux.yaml new file mode 100644 index 000000000..ca670923f --- /dev/null +++ b/installer/charts/educates-training-platform/charts/session-manager/files/kyverno-policies/cluster-policies/baseline/disallow-selinux.yaml @@ -0,0 +1,59 @@ +apiVersion: policies.kyverno.io/v1alpha1 +kind: ValidatingPolicy +metadata: + name: disallow-selinux + annotations: + policies.kyverno.io/title: Disallow SELinux in ValidatingPolicy + policies.kyverno.io/category: Pod Security Standards (Baseline) in ValidatingPolicy + policies.kyverno.io/severity: medium + policies.kyverno.io/subject: Pod + policies.kyverno.io/minversion: 1.14.0 + kyverno.io/kyverno-version: 1.14.0 + kyverno.io/kubernetes-version: "1.30+" + policies.kyverno.io/description: >- + SELinux options can be used to escalate privileges and should not be allowed. This policy + ensures that the `seLinuxOptions` field is undefined. +spec: + validationActions: + - Audit + evaluation: + background: + enabled: true + matchConstraints: + resourceRules: + - apiGroups: [""] + apiVersions: ["v1"] + operations: ["CREATE", "UPDATE"] + resources: ["pods"] + variables: + - name: allContainerTypes + expression: >- + object.spec.containers + + object.spec.?initContainers.orValue([]) + + object.spec.?ephemeralContainers.orValue([]) + - name: seLinuxTypes + expression: "['container_t', 'container_init_t', 'container_kvm_t']" + - name: hasValidSELinuxType + expression: >- + object.spec.?securityContext.?seLinuxOptions.?type.orValue('') == '' || + variables.seLinuxTypes.exists(type, type == object.spec.securityContext.seLinuxOptions.type) + - name: hasValidSELinuxUserRole + expression: >- + object.spec.?securityContext.?seLinuxOptions.?user.orValue('') == '' && + object.spec.?securityContext.?seLinuxOptions.?role.orValue('') == '' + validations: + - expression: >- + variables.hasValidSELinuxType && + variables.allContainerTypes.all(container, + container.?securityContext.?seLinuxOptions.?type.orValue('') == '' || + variables.seLinuxTypes.exists(type, type == container.securityContext.seLinuxOptions.type)) + message: >- + Setting the SELinux type is restricted. The field securityContext.seLinuxOptions.type + must either be unset or set to one of the allowed values (container_t, container_init_t, or container_kvm_t). + - expression: >- + variables.hasValidSELinuxUserRole && + variables.allContainerTypes.all(container, + container.?securityContext.?seLinuxOptions.?user.orValue('') == '' && + container.?securityContext.?seLinuxOptions.?role.orValue('') == '') + message: >- + Setting the SELinux user or role is forbidden. The fields seLinuxOptions.user and seLinuxOptions.role must be unset. diff --git a/installer/charts/educates-training-platform/charts/session-manager/files/kyverno-policies/cluster-policies/baseline/restrict-seccomp.yaml b/installer/charts/educates-training-platform/charts/session-manager/files/kyverno-policies/cluster-policies/baseline/restrict-seccomp.yaml new file mode 100644 index 000000000..628aa38f1 --- /dev/null +++ b/installer/charts/educates-training-platform/charts/session-manager/files/kyverno-policies/cluster-policies/baseline/restrict-seccomp.yaml @@ -0,0 +1,47 @@ +apiVersion: policies.kyverno.io/v1alpha1 +kind: ValidatingPolicy +metadata: + name: restrict-seccomp + annotations: + policies.kyverno.io/title: Restrict Seccomp in ValidatingPolicy + policies.kyverno.io/category: Pod Security Standards (Baseline) in ValidatingPolicy + policies.kyverno.io/severity: medium + policies.kyverno.io/subject: Pod + policies.kyverno.io/minversion: 1.14.0 + kyverno.io/kyverno-version: 1.14.0 + kyverno.io/kubernetes-version: "1.30+" + policies.kyverno.io/description: >- + The seccomp profile must not be explicitly set to Unconfined. This policy, + requiring Kubernetes v1.30 or later, ensures that seccomp is unset or + set to `RuntimeDefault` or `Localhost`. +spec: + validationActions: + - Audit + evaluation: + background: + enabled: true + matchConstraints: + resourceRules: + - apiGroups: [""] + apiVersions: ["v1"] + operations: ["CREATE", "UPDATE"] + resources: ["pods"] + variables: + - name: allContainers + expression: >- + object.spec.containers + + object.spec.?initContainers.orValue([]) + + object.spec.?ephemeralContainers.orValue([]) + - name: allowedProfileTypes + expression: "['RuntimeDefault', 'Localhost']" + - name: hasValidSeccompProfile + expression: >- + object.spec.?securityContext.?seccompProfile.?type.orValue('Localhost') in variables.allowedProfileTypes + validations: + - expression: >- + variables.hasValidSeccompProfile && + variables.allContainers.all(container, + container.?securityContext.?seccompProfile.?type.orValue('Localhost') in variables.allowedProfileTypes) + message: >- + Use of custom Seccomp profiles is disallowed. The field + `securityContext.seccompProfile.type` must be unset or set to `RuntimeDefault` or `Localhost`. diff --git a/installer/charts/educates-training-platform/charts/session-manager/files/kyverno-policies/cluster-policies/baseline/restrict-sysctls.yaml b/installer/charts/educates-training-platform/charts/session-manager/files/kyverno-policies/cluster-policies/baseline/restrict-sysctls.yaml new file mode 100644 index 000000000..429b14474 --- /dev/null +++ b/installer/charts/educates-training-platform/charts/session-manager/files/kyverno-policies/cluster-policies/baseline/restrict-sysctls.yaml @@ -0,0 +1,44 @@ +apiVersion: policies.kyverno.io/v1alpha1 +kind: ValidatingPolicy +metadata: + name: restrict-sysctls + annotations: + policies.kyverno.io/title: Restrict sysctls in ValidatingPolicy + policies.kyverno.io/category: Pod Security Standards (Baseline) in ValidatingPolicy + policies.kyverno.io/severity: medium + policies.kyverno.io/subject: Pod + policies.kyverno.io/minversion: 1.14.0 + kyverno.io/kyverno-version: 1.14.0 + kyverno.io/kubernetes-version: "1.30+" + policies.kyverno.io/description: >- + Sysctls can disable security mechanisms or affect all containers on a + host, and should be disallowed except for an allowed "safe" subset. A + sysctl is considered safe if it is namespaced in the container or the + Pod, and it is isolated from other Pods or processes on the same Node. + This policy ensures that only those "safe" subsets can be specified in + a Pod. +spec: + validationActions: + - Audit + evaluation: + background: + enabled: true + matchConstraints: + resourceRules: + - apiGroups: [""] + apiVersions: ["v1"] + operations: ["CREATE", "UPDATE"] + resources: ["pods"] + variables: + - name: allowedSysctls + expression: "['kernel.shm_rmid_forced','net.ipv4.ip_local_port_range','net.ipv4.ip_unprivileged_port_start','net.ipv4.tcp_syncookies','net.ipv4.ping_group_range']" + validations: + - expression: >- + object.spec.?securityContext.?sysctls.orValue([]).all(sysctl, + sysctl.?name.orValue('') in variables.allowedSysctls) + message: >- + Setting additional sysctls above the allowed type is disallowed. + The field spec.securityContext.sysctls must be unset or not use any other names + than kernel.shm_rmid_forced, net.ipv4.ip_local_port_range, + net.ipv4.ip_unprivileged_port_start, net.ipv4.tcp_syncookies and + net.ipv4.ping_group_range. \ No newline at end of file diff --git a/installer/charts/educates-training-platform/charts/session-manager/files/kyverno-policies/cluster-policies/restricted/disallow-capabilities-strict.yaml b/installer/charts/educates-training-platform/charts/session-manager/files/kyverno-policies/cluster-policies/restricted/disallow-capabilities-strict.yaml new file mode 100644 index 000000000..c919a7b05 --- /dev/null +++ b/installer/charts/educates-training-platform/charts/session-manager/files/kyverno-policies/cluster-policies/restricted/disallow-capabilities-strict.yaml @@ -0,0 +1,46 @@ +apiVersion: policies.kyverno.io/v1alpha1 +kind: ValidatingPolicy +metadata: + name: disallow-capabilities-strict + annotations: + policies.kyverno.io/title: Disallow Capabilities (Strict) in ValidatingPolicy + policies.kyverno.io/category: Pod Security Standards (Restricted) in ValidatingPolicy + policies.kyverno.io/severity: medium + policies.kyverno.io/minversion: 1.14.0 + kyverno.io/kyverno-version: 1.14.0 + kyverno.io/kubernetes-version: "1.30+" + policies.kyverno.io/subject: Pod + policies.kyverno.io/description: >- + Adding capabilities other than `NET_BIND_SERVICE` is disallowed. In addition, + all containers must explicitly drop `ALL` capabilities. +spec: + validationActions: + - Audit + evaluation: + background: + enabled: true + matchConstraints: + resourceRules: + - apiGroups: [""] + apiVersions: ["v1"] + operations: ["CREATE", "UPDATE"] + resources: ["pods"] + variables: + - name: allContainers + expression: >- + object.spec.containers + + (object.spec.?initContainers.orValue([])) + + (object.spec.?ephemeralContainers.orValue([])) + validations: + - expression: >- + variables.allContainers.all(container, + container.?securityContext.?capabilities.?drop.orValue([]).exists_one(capability, capability == 'ALL')) + message: >- + Containers must drop `ALL` capabilities. + - expression: >- + variables.allContainers.all(container, + container.?securityContext.?capabilities.?add.orValue([]).size() == 0 || + (container.securityContext.capabilities.add.orValue([]).size() == 1 && + container.securityContext.capabilities.add[0] == 'NET_BIND_SERVICE')) + message: >- + Any capabilities added other than NET_BIND_SERVICE are disallowed. diff --git a/installer/charts/educates-training-platform/charts/session-manager/files/kyverno-policies/cluster-policies/restricted/disallow-privilege-escalation.yaml b/installer/charts/educates-training-platform/charts/session-manager/files/kyverno-policies/cluster-policies/restricted/disallow-privilege-escalation.yaml new file mode 100644 index 000000000..22dcceb72 --- /dev/null +++ b/installer/charts/educates-training-platform/charts/session-manager/files/kyverno-policies/cluster-policies/restricted/disallow-privilege-escalation.yaml @@ -0,0 +1,40 @@ +apiVersion: policies.kyverno.io/v1alpha1 +kind: ValidatingPolicy +metadata: + name: disallow-privilege-escalation + annotations: + policies.kyverno.io/title: Disallow Privilege Escalation in ValidatingPolicy + policies.kyverno.io/category: Pod Security Standards (Restricted) in ValidatingPolicy + policies.kyverno.io/severity: medium + policies.kyverno.io/subject: Pod + policies.kyverno.io/minversion: 1.14.0 + kyverno.io/kyverno-version: 1.14.0 + kyverno.io/kubernetes-version: "1.30+" + policies.kyverno.io/description: >- + Privilege escalation, such as via set-user-ID or set-group-ID file mode, should not be allowed. + This policy ensures the `allowPrivilegeEscalation` field is set to `false`. +spec: + validationActions: + - Audit + evaluation: + background: + enabled: true + matchConstraints: + resourceRules: + - apiGroups: [""] + apiVersions: ["v1"] + operations: ["CREATE", "UPDATE"] + resources: ["pods"] + variables: + - name: allContainers + expression: >- + object.spec.containers + + object.spec.?initContainers.orValue([]) + + object.spec.?ephemeralContainers.orValue([]) + validations: + - expression: >- + variables.allContainers.all(container, + container.?securityContext.allowPrivilegeEscalation.orValue(true) == false) + message: >- + Privilege escalation is disallowed. + All containers must set the securityContext.allowPrivilegeEscalation field to `false`. diff --git a/installer/charts/educates-training-platform/charts/session-manager/files/kyverno-policies/cluster-policies/restricted/require-run-as-non-root-user.yaml b/installer/charts/educates-training-platform/charts/session-manager/files/kyverno-policies/cluster-policies/restricted/require-run-as-non-root-user.yaml new file mode 100644 index 000000000..57379496e --- /dev/null +++ b/installer/charts/educates-training-platform/charts/session-manager/files/kyverno-policies/cluster-policies/restricted/require-run-as-non-root-user.yaml @@ -0,0 +1,46 @@ +apiVersion: policies.kyverno.io/v1alpha1 +kind: ValidatingPolicy +metadata: + name: require-run-as-non-root-user + annotations: + policies.kyverno.io/title: Require Run As Non-Root User in ValidatingPolicy + policies.kyverno.io/category: Pod Security Standards (Restricted) in ValidatingPolicy + policies.kyverno.io/severity: medium + policies.kyverno.io/subject: Pod + policies.kyverno.io/minversion: 1.14.0 + kyverno.io/kyverno-version: 1.14.0 + kyverno.io/kubernetes-version: "1.30+" + policies.kyverno.io/description: >- + Containers must be required to run as non-root users. This policy ensures + `runAsUser` is either unset or set to a number greater than zero. +spec: + validationActions: + - Audit + evaluation: + background: + enabled: true + matchConstraints: + resourceRules: + - apiGroups: [""] + apiVersions: ["v1"] + operations: ["CREATE", "UPDATE"] + resources: ["pods"] + variables: + - name: allContainers + expression: >- + object.spec.containers + + object.spec.?initContainers.orValue([]) + + object.spec.?ephemeralContainers.orValue([]) + validations: + - expression: >- + object.spec.?securityContext.?runAsUser.orValue(1) > 0 + message: >- + Running as root is not allowed. The field spec.securityContext.runAsUser + must be unset or set to a number greater than zero. + - expression: >- + variables.allContainers.all(container, + container.?securityContext.?runAsUser.orValue(1) > 0) + message: >- + Running as root is not allowed. The field spec.containers[*].securityContext.runAsUser, + spec.initContainers[*].securityContext.runAsUser, and + spec.ephemeralContainers[*].securityContext.runAsUser must be unset or set to a number greater than zero. diff --git a/installer/charts/educates-training-platform/charts/session-manager/files/kyverno-policies/cluster-policies/restricted/require-run-as-nonroot.yaml b/installer/charts/educates-training-platform/charts/session-manager/files/kyverno-policies/cluster-policies/restricted/require-run-as-nonroot.yaml new file mode 100644 index 000000000..8acd55418 --- /dev/null +++ b/installer/charts/educates-training-platform/charts/session-manager/files/kyverno-policies/cluster-policies/restricted/require-run-as-nonroot.yaml @@ -0,0 +1,42 @@ +apiVersion: policies.kyverno.io/v1alpha1 +kind: ValidatingPolicy +metadata: + name: require-run-as-nonroot + annotations: + policies.kyverno.io/title: Require runAsNonRoot in ValidatingPolicy + policies.kyverno.io/category: Pod Security Standards (Restricted) in ValidatingPolicy + policies.kyverno.io/severity: medium + policies.kyverno.io/subject: Pod + policies.kyverno.io/minversion: 1.14.0 + kyverno.io/kyverno-version: 1.14.0 + kyverno.io/kubernetes-version: "1.30+" + policies.kyverno.io/description: >- + Containers must be required to run as non-root. This policy ensures + `runAsNonRoot` is set to true. +spec: + validationActions: + - Audit + evaluation: + background: + enabled: true + matchConstraints: + resourceRules: + - apiGroups: [""] + apiVersions: ["v1"] + operations: ["CREATE", "UPDATE"] + resources: ["pods"] + variables: + - name: ctnrs + expression: >- + object.spec.containers + + object.spec.?initContainers.orValue([]) + + object.spec.?ephemeralContainers.orValue([]) + validations: + - expression: >- + (object.spec.?securityContext.?runAsNonRoot.orValue(false) == true + && variables.ctnrs.all(c, c.?securityContext.?runAsNonRoot.orValue(true) == true)) + || variables.ctnrs.all(c, c.?securityContext.?runAsNonRoot.orValue(false) == true) + message: >- + Running as root is not allowed. Either spec.securityContext.runAsNonRoot + must be set to true, or all containers (spec.containers[*], spec.initContainers[*], + spec.ephemeralContainers[*]) must have securityContext.runAsNonRoot set to true. diff --git a/installer/charts/educates-training-platform/charts/session-manager/files/kyverno-policies/cluster-policies/restricted/restrict-seccomp-strict.yaml b/installer/charts/educates-training-platform/charts/session-manager/files/kyverno-policies/cluster-policies/restricted/restrict-seccomp-strict.yaml new file mode 100644 index 000000000..95ce3c74b --- /dev/null +++ b/installer/charts/educates-training-platform/charts/session-manager/files/kyverno-policies/cluster-policies/restricted/restrict-seccomp-strict.yaml @@ -0,0 +1,43 @@ +apiVersion: policies.kyverno.io/v1alpha1 +kind: ValidatingPolicy +metadata: + name: restrict-seccomp-strict + annotations: + policies.kyverno.io/title: Restrict Seccomp (Strict) in ValidatingPolicy + policies.kyverno.io/category: Pod Security Standards (Restricted) in ValidatingPolicy + policies.kyverno.io/severity: medium + policies.kyverno.io/subject: Pod + policies.kyverno.io/minversion: 1.14.0 + kyverno.io/kyverno-version: 1.14.0 + kyverno.io/kubernetes-version: "1.30+" + policies.kyverno.io/description: >- + The seccomp profile in the Restricted group must not be explicitly set to Unconfined + but additionally must also not allow an unset value. This policy, + requiring Kubernetes v1.30 or later, ensures that seccomp is + set to `RuntimeDefault` or `Localhost`. A known issue prevents a policy such as this + using `anyPattern` from being persisted properly in Kubernetes 1.23.0-1.23.2. +spec: + validationActions: + - Audit + evaluation: + background: + enabled: true + matchConstraints: + resourceRules: + - apiGroups: [""] + apiVersions: ["v1"] + operations: ["CREATE", "UPDATE"] + resources: ["pods"] + variables: + - name: allContainers + expression: >- + object.spec.containers + + object.spec.?initContainers.orValue([]) + + object.spec.?ephemeralContainers.orValue([]) + validations: + - expression: >- + object.spec.?securityContext.?seccompProfile.?type.orValue('RuntimeDefault') in ['RuntimeDefault', 'Localhost'] + && variables.allContainers.all(container, + container.?securityContext.?seccompProfile.?type.orValue('RuntimeDefault') in ['RuntimeDefault', 'Localhost']) + message: >- + seccompProfile.type must be either 'RuntimeDefault' or 'Localhost'. \ No newline at end of file diff --git a/installer/charts/educates-training-platform/charts/session-manager/files/kyverno-policies/cluster-policies/restricted/restrict-volume-types.yaml b/installer/charts/educates-training-platform/charts/session-manager/files/kyverno-policies/cluster-policies/restricted/restrict-volume-types.yaml new file mode 100644 index 000000000..0111152d4 --- /dev/null +++ b/installer/charts/educates-training-platform/charts/session-manager/files/kyverno-policies/cluster-policies/restricted/restrict-volume-types.yaml @@ -0,0 +1,42 @@ +apiVersion: policies.kyverno.io/v1alpha1 +kind: ValidatingPolicy +metadata: + name: restrict-volume-types + annotations: + policies.kyverno.io/title: Restrict Volume Types in ValidatingPolicy + policies.kyverno.io/category: Pod Security Standards (Restricted) in ValidatingPolicy + policies.kyverno.io/severity: medium + policies.kyverno.io/subject: Pod,Volume + policies.kyverno.io/minversion: 1.14.0 + kyverno.io/kubernetes-version: "1.30+" + kyverno.io/kyverno-version: 1.14.0 + policies.kyverno.io/description: >- + In addition to restricting HostPath volumes, the restricted pod security profile + limits usage of non-core volume types to those defined through PersistentVolumes. + This policy blocks any other type of volume other than those in the allow list. +spec: + validationActions: + - Audit + evaluation: + background: + enabled: true + matchConstraints: + resourceRules: + - apiGroups: [""] + apiVersions: ["v1"] + operations: ["CREATE", "UPDATE"] + resources: ["pods"] + validations: + - expression: >- + !has(object.spec.volumes) || + object.spec.volumes.all(vol, has(vol.configMap) || + has(vol.csi) || + has(vol.downwardAPI) || + has(vol.emptyDir) || + has(vol.ephemeral) || + has(vol.persistentVolumeClaim) || + has(vol.projected) || + has(vol.secret)) + message: >- + Only the following types of volumes may be used: configMap, csi, downwardAPI, + emptyDir, ephemeral, persistentVolumeClaim, projected, and secret. diff --git a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/educates/_ytt_lib/kyverno-policies/upstream/best-practices-cel/disallow-cri-sock-mount/disallow-cri-sock-mount.yaml b/installer/charts/educates-training-platform/charts/session-manager/files/kyverno-policies/workshop-policies/disallow-cri-sock-mount.yaml similarity index 80% rename from carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/educates/_ytt_lib/kyverno-policies/upstream/best-practices-cel/disallow-cri-sock-mount/disallow-cri-sock-mount.yaml rename to installer/charts/educates-training-platform/charts/session-manager/files/kyverno-policies/workshop-policies/disallow-cri-sock-mount.yaml index b243dd332..342968ae7 100644 --- a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/educates/_ytt_lib/kyverno-policies/upstream/best-practices-cel/disallow-cri-sock-mount/disallow-cri-sock-mount.yaml +++ b/installer/charts/educates-training-platform/charts/session-manager/files/kyverno-policies/workshop-policies/disallow-cri-sock-mount.yaml @@ -1,14 +1,14 @@ -apiVersion: kyverno.io/v1 -kind: ClusterPolicy +apiVersion: policies.kyverno.io/v1alpha1 +kind: ValidatingPolicy metadata: name: disallow-container-sock-mounts annotations: - policies.kyverno.io/title: Disallow CRI socket mounts in CEL expressions - policies.kyverno.io/category: Best Practices, EKS Best Practices in CEL + policies.kyverno.io/title: Disallow CRI socket mounts in VPOL + policies.kyverno.io/category: Best Practices, EKS Best Practices in VPOl policies.kyverno.io/severity: medium policies.kyverno.io/subject: Pod - policies.kyverno.io/minversion: 1.11.0 - kyverno.io/kubernetes-version: "1.26-1.27" + policies.kyverno.io/minversion: 1.14.0 + kyverno.io/kubernetes-version: "1.30" policies.kyverno.io/description: >- Container daemon socket bind mounts allows access to the container engine on the node. This access can be used for privilege escalation and to manage containers @@ -17,28 +17,24 @@ metadata: to or replacement of this policy, preventing users from mounting the parent directories (/var/run and /var) may be necessary to completely prevent socket bind mounts. spec: - validationFailureAction: Audit - background: true - rules: - - name: validate-socket-mounts - match: - any: - - resources: - kinds: - - Pod - operations: - - CREATE - - UPDATE - validate: - cel: - variables: + validationActions: [Audit] + evaluation: + background: + enabled: true + matchConstraints: + resourceRules: + - apiGroups: [''] + apiVersions: [v1] + operations: [CREATE, UPDATE] + resources: [pods] + variables: - name: hasVolumes expression: "!has(object.spec.volumes)" - name: volumes expression: "object.spec.volumes" - name: volumesWithHostPath expression: "variables.volumes.filter(volume, has(volume.hostPath))" - expressions: + validations: - expression: >- variables.hasVolumes || variables.volumesWithHostPath.all(volume, !volume.hostPath.path.matches('/var/run/docker.sock')) diff --git a/installer/charts/educates-training-platform/charts/session-manager/files/kyverno-policies/workshop-policies/disallow-empty-ingress-host.yaml b/installer/charts/educates-training-platform/charts/session-manager/files/kyverno-policies/workshop-policies/disallow-empty-ingress-host.yaml new file mode 100644 index 000000000..cf4045141 --- /dev/null +++ b/installer/charts/educates-training-platform/charts/session-manager/files/kyverno-policies/workshop-policies/disallow-empty-ingress-host.yaml @@ -0,0 +1,31 @@ +apiVersion: policies.kyverno.io/v1alpha1 +kind: ValidatingPolicy +metadata: + name: disallow-empty-ingress-host + annotations: + policies.kyverno.io/title: Disallow empty Ingress host in VPOL + policies.kyverno.io/category: Best Practices in VPOL + policies.kyverno.io/minversion: 1.14.0 + kyverno.io/kubernetes-version: "1.30" + policies.kyverno.io/severity: medium + policies.kyverno.io/subject: Ingress + policies.kyverno.io/description: >- + An ingress resource needs to define an actual host name + in order to be valid. This policy ensures that there is a + hostname for each rule defined. +spec: + validationActions: [Audit] + evaluation: + background: + enabled: false + matchConstraints: + resourceRules: + - apiGroups: ["networking.k8s.io"] + apiVersions: ["v1"] + operations: ["CREATE", "UPDATE"] + resources: ["ingresses"] + validations: + - expression: >- + object.spec.?rules.orValue([]).all(rule, has(rule.host) && has(rule.http)) + message: "The Ingress host name must be defined, not empty." + diff --git a/installer/charts/educates-training-platform/charts/session-manager/files/kyverno-policies/workshop-policies/disallow-ingress-nginx-custom-snippets.yaml b/installer/charts/educates-training-platform/charts/session-manager/files/kyverno-policies/workshop-policies/disallow-ingress-nginx-custom-snippets.yaml new file mode 100644 index 000000000..f697ea0ff --- /dev/null +++ b/installer/charts/educates-training-platform/charts/session-manager/files/kyverno-policies/workshop-policies/disallow-ingress-nginx-custom-snippets.yaml @@ -0,0 +1,43 @@ +apiVersion: policies.kyverno.io/v1alpha1 +kind: ValidatingPolicy +metadata: + name: disallow-ingress-nginx-custom-snippets + annotations: + policies.kyverno.io/title: Disallow Custom Snippets in ValidatingPolicy + policies.kyverno.io/category: Security, NGINX Ingress in ValidatingPolicy + policies.kyverno.io/subject: ConfigMap, Ingress + policies.kyverno.io/description: >- + Users that can create or update ingress objects can use the custom snippets + feature to obtain all secrets in the cluster (CVE-2021-25742). This policy + disables allow-snippet-annotations in the ingress-nginx configuration and + blocks *-snippet annotations on an Ingress. + See: https://github.com/kubernetes/ingress-nginx/issues/7837 + Hand-ported to ValidatingPolicy from nginx-ingress-cel (no upstream -vpol variant + exists). The two original rules (ConfigMap, Ingress) become one policy matching + both kinds, with each validation guarded by request.kind so it only applies to + the resource it was written for. +spec: + validationActions: + - Deny + evaluation: + background: + enabled: true + matchConstraints: + resourceRules: + - apiGroups: [""] + apiVersions: ["v1"] + operations: ["CREATE", "UPDATE"] + resources: ["configmaps"] + - apiGroups: ["networking.k8s.io"] + apiVersions: ["v1"] + operations: ["CREATE", "UPDATE"] + resources: ["ingresses"] + validations: + - expression: >- + request.kind.kind != 'ConfigMap' || + object.?data[?'allow-snippet-annotations'].orValue('false') == 'false' + message: "ingress-nginx allow-snippet-annotations must be set to false" + - expression: >- + request.kind.kind != 'Ingress' || + !object.metadata.?annotations.orValue({}).exists(annotation, annotation.endsWith('-snippet')) + message: "ingress-nginx custom snippets are not allowed" diff --git a/installer/charts/educates-training-platform/charts/session-manager/files/kyverno-policies/workshop-policies/disallow-localhost-services.yaml b/installer/charts/educates-training-platform/charts/session-manager/files/kyverno-policies/workshop-policies/disallow-localhost-services.yaml new file mode 100644 index 000000000..7bb246cdd --- /dev/null +++ b/installer/charts/educates-training-platform/charts/session-manager/files/kyverno-policies/workshop-policies/disallow-localhost-services.yaml @@ -0,0 +1,31 @@ +apiVersion: policies.kyverno.io/v1alpha1 +kind: ValidatingPolicy +metadata: + name: no-localhost-service + annotations: + policies.kyverno.io/title: Disallow Localhost ExternalName Services in ValidatingPolicy + policies.kyverno.io/category: Sample in Vpol + policies.kyverno.io/severity: medium + policies.kyverno.io/subject: Service + policies.kyverno.io/minversion: 1.14.0 + kyverno.io/kubernetes-version: "1.30" + policies.kyverno.io/description: >- + A Service of type ExternalName which points back to localhost can potentially be used to exploit + vulnerabilities in some Ingress controllers. This policy audits Services of type ExternalName + if the externalName field refers to localhost. +spec: + validationActions: + - Audit + evaluation: + background: + enabled: true + matchConstraints: + resourceRules: + - apiGroups: [""] + apiVersions: ["v1"] + operations: ["CREATE", "UPDATE"] + resources: ["services"] + validations: + - expression: "object.spec.type != 'ExternalName' || object.spec.externalName != 'localhost'" + message: "Service of type ExternalName cannot point to localhost." + diff --git a/installer/charts/educates-training-platform/charts/session-manager/files/kyverno-policies/workshop-policies/prevent-cr8escape.yaml b/installer/charts/educates-training-platform/charts/session-manager/files/kyverno-policies/workshop-policies/prevent-cr8escape.yaml new file mode 100644 index 000000000..60a85b88f --- /dev/null +++ b/installer/charts/educates-training-platform/charts/session-manager/files/kyverno-policies/workshop-policies/prevent-cr8escape.yaml @@ -0,0 +1,34 @@ +apiVersion: policies.kyverno.io/v1alpha1 +kind: ValidatingPolicy +metadata: + name: prevent-cr8escape + annotations: + policies.kyverno.io/title: Prevent cr8escape (CVE-2022-0811) in ValidatingPolicy + policies.kyverno.io/category: Other in Vpol + policies.kyverno.io/severity: high + kyverno.io/kyverno-version: 1.14.0 + policies.kyverno.io/minversion: 1.14.0 + kyverno.io/kubernetes-version: "1.30" + policies.kyverno.io/subject: Pod + policies.kyverno.io/description: >- + A vulnerability "cr8escape" (CVE-2022-0811) in CRI-O the container runtime engine + underpinning Kubernetes allows attackers to escape from a Kubernetes container + and gain root access to the host. The recommended remediation is to disallow + sysctl settings with + or = in their value. +spec: + validationActions: [Deny] + evaluation: + background: + enabled: true + matchConstraints: + resourceRules: + - apiGroups: [""] + apiVersions: ["v1"] + operations: ["CREATE", "UPDATE"] + resources: ["pods"] + validations: + - expression: >- + object.spec.?securityContext.?sysctls.orValue([]).all(sysctl, + !has(sysctl.value) || (!sysctl.value.contains('+') && !sysctl.value.contains('='))) + message: "characters '+' or '=' are not allowed in sysctls values" + diff --git a/installer/charts/educates-training-platform/charts/session-manager/files/kyverno-policies/workshop-policies/require-ingress-session-name.yaml b/installer/charts/educates-training-platform/charts/session-manager/files/kyverno-policies/workshop-policies/require-ingress-session-name.yaml new file mode 100644 index 000000000..9012fe53c --- /dev/null +++ b/installer/charts/educates-training-platform/charts/session-manager/files/kyverno-policies/workshop-policies/require-ingress-session-name.yaml @@ -0,0 +1,36 @@ +apiVersion: policies.kyverno.io/v1alpha1 +kind: ValidatingPolicy +metadata: + name: require-ingress-session-name + annotations: + policies.kyverno.io/title: Require workshop session name in Ingress host + policies.kyverno.io/category: Educates + policies.kyverno.io/subject: Ingress + policies.kyverno.io/description: >- + Every Ingress created in a workshop session namespace must embed the session + name in each rule's host, so a session cannot publish ingresses for hostnames + belonging to other sessions. Educates-internal policy (no upstream variant); + rewritten from the legacy JMESPath ClusterPolicy to ValidatingPolicy CEL. + The session name is read from the request namespace's + `training.educates.dev/session.name` label via namespaceObject (replacing the + old apiCall). Fail-closed: when the label is absent the Ingress is denied, + preserving the original behaviour. +spec: + validationActions: + - Deny + evaluation: + background: + enabled: true + matchConstraints: + resourceRules: + - apiGroups: ["networking.k8s.io"] + apiVersions: ["v1"] + operations: ["CREATE", "UPDATE"] + resources: ["ingresses"] + validations: + - expression: >- + has(namespaceObject.metadata.labels) && + 'training.educates.dev/session.name' in namespaceObject.metadata.labels && + object.spec.?rules.orValue([]).all(rule, + rule.?host.orValue('').contains(namespaceObject.metadata.labels['training.educates.dev/session.name'])) + message: "Ingress host name must embed the workshop session name." diff --git a/installer/charts/educates-training-platform/charts/session-manager/files/kyverno-policies/workshop-policies/restrict-annotations.yaml b/installer/charts/educates-training-platform/charts/session-manager/files/kyverno-policies/workshop-policies/restrict-annotations.yaml new file mode 100644 index 000000000..90349d528 --- /dev/null +++ b/installer/charts/educates-training-platform/charts/session-manager/files/kyverno-policies/workshop-policies/restrict-annotations.yaml @@ -0,0 +1,39 @@ +apiVersion: policies.kyverno.io/v1alpha1 +kind: ValidatingPolicy +metadata: + name: restrict-annotations + annotations: + policies.kyverno.io/title: Restrict NGINX Ingress annotation values in ValidatingPolicy + policies.kyverno.io/category: Security, NGINX Ingress in ValidatingPolicy + policies.kyverno.io/severity: high + policies.kyverno.io/subject: Ingress + policies.kyverno.io/description: >- + This policy mitigates CVE-2021-25746 by restricting `metadata.annotations` to safe values. + See: https://github.com/kubernetes/ingress-nginx/blame/main/internal/ingress/inspector/rules.go. + This issue has been fixed in NGINX Ingress v1.2.0. For NGINX Ingress version 1.0.5+ the + "annotation-value-word-blocklist" configuration setting is also recommended. + Please refer to the CVE for details. + Hand-ported to ValidatingPolicy from nginx-ingress-cel (no upstream -vpol variant exists). +spec: + validationActions: + - Deny + evaluation: + background: + enabled: true + matchConstraints: + resourceRules: + - apiGroups: ["networking.k8s.io"] + apiVersions: ["v1"] + operations: ["CREATE", "UPDATE"] + resources: ["ingresses"] + validations: + - expression: >- + !has(object.metadata.annotations) || + ( + !object.metadata.annotations.exists(annotation, object.metadata.annotations[annotation].matches('\\s*alias\\s*.*;')) && + !object.metadata.annotations.exists(annotation, object.metadata.annotations[annotation].matches('\\s*root\\s*.*;')) && + !object.metadata.annotations.exists(annotation, object.metadata.annotations[annotation].matches('/etc/(passwd|shadow|group|nginx|ingress-controller)')) && + !object.metadata.annotations.exists(annotation, object.metadata.annotations[annotation].matches('/var/run/secrets')) && + !object.metadata.annotations.exists(annotation, object.metadata.annotations[annotation].matches('.*_by_lua.*')) + ) + message: "metadata.annotations value is not allowed" diff --git a/installer/charts/educates-training-platform/charts/session-manager/files/kyverno-policies/workshop-policies/restrict-ingress-paths.yaml b/installer/charts/educates-training-platform/charts/session-manager/files/kyverno-policies/workshop-policies/restrict-ingress-paths.yaml new file mode 100644 index 000000000..64a6cc3ae --- /dev/null +++ b/installer/charts/educates-training-platform/charts/session-manager/files/kyverno-policies/workshop-policies/restrict-ingress-paths.yaml @@ -0,0 +1,34 @@ +apiVersion: policies.kyverno.io/v1alpha1 +kind: ValidatingPolicy +metadata: + name: restrict-ingress-paths + annotations: + policies.kyverno.io/title: Restrict NGINX Ingress path values in ValidatingPolicy + policies.kyverno.io/category: Security, NGINX Ingress in ValidatingPolicy + policies.kyverno.io/severity: high + policies.kyverno.io/subject: Ingress + policies.kyverno.io/description: >- + This policy mitigates CVE-2021-25745 by restricting `spec.rules[].http.paths[].path` to safe values. + Additional paths can be added as required. This issue has been fixed in NGINX Ingress v1.2.0. + Please refer to the CVE for details. + Hand-ported to ValidatingPolicy from nginx-ingress-cel (no upstream -vpol variant exists). +spec: + validationActions: + - Deny + evaluation: + background: + enabled: true + matchConstraints: + resourceRules: + - apiGroups: ["networking.k8s.io"] + apiVersions: ["v1"] + operations: ["CREATE", "UPDATE"] + resources: ["ingresses"] + validations: + - expression: >- + object.spec.?rules.orValue([]).all(rule, + rule.?http.?paths.orValue([]).all(p, + !p.path.contains('/etc') && !p.path.contains('/var/run/secrets') && + !p.path.contains('/root') && !p.path.contains('/var/run/kubernetes/serviceaccount') && + !p.path.contains('/etc/kubernetes/admin.conf'))) + message: "spec.rules[].http.paths[].path value is not allowed" diff --git a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/educates/_ytt_lib/kyverno-policies/upstream/other-cel/restrict-loadbalancer/restrict-loadbalancer.yaml b/installer/charts/educates-training-platform/charts/session-manager/files/kyverno-policies/workshop-policies/restrict-loadbalancer.yaml similarity index 53% rename from carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/educates/_ytt_lib/kyverno-policies/upstream/other-cel/restrict-loadbalancer/restrict-loadbalancer.yaml rename to installer/charts/educates-training-platform/charts/session-manager/files/kyverno-policies/workshop-policies/restrict-loadbalancer.yaml index 08b7cb558..1842cde89 100644 --- a/carvel-packages/installer/bundle/config/ytt/_ytt_lib/packages/educates/_ytt_lib/kyverno-policies/upstream/other-cel/restrict-loadbalancer/restrict-loadbalancer.yaml +++ b/installer/charts/educates-training-platform/charts/session-manager/files/kyverno-policies/workshop-policies/restrict-loadbalancer.yaml @@ -1,14 +1,14 @@ -apiVersion: kyverno.io/v1 -kind: ClusterPolicy +apiVersion: policies.kyverno.io/v1alpha1 +kind: ValidatingPolicy metadata: name: no-loadbalancer-service annotations: - policies.kyverno.io/title: Disallow Service Type LoadBalancer in CEL expressions - policies.kyverno.io/category: Sample in CEL + policies.kyverno.io/title: Disallow Service Type LoadBalancer in ValidatingPolicy + policies.kyverno.io/category: Sample in Vpol policies.kyverno.io/severity: medium policies.kyverno.io/subject: Service - policies.kyverno.io/minversion: 1.11.0 - kyverno.io/kubernetes-version: "1.26-1.27" + policies.kyverno.io/minversion: 1.14.0 + kyverno.io/kubernetes-version: "1.30" policies.kyverno.io/description: >- Especially in cloud provider environments, a Service having type LoadBalancer will cause the provider to respond by creating a load balancer somewhere in the customer account. This adds @@ -16,21 +16,18 @@ metadata: overrun established budgets and security practices set by the organization. This policy restricts use of the Service type LoadBalancer. spec: - validationFailureAction: Audit - background: true - rules: - - name: no-LoadBalancer - match: - any: - - resources: - kinds: - - Service - operations: - - CREATE - - UPDATE - validate: - cel: - expressions: - - expression: "object.spec.type != 'LoadBalancer'" - message: "Service of type LoadBalancer is not allowed." + validationActions: + - Audit + evaluation: + background: + enabled: true + matchConstraints: + resourceRules: + - apiGroups: [""] + apiVersions: ["v1"] + operations: ["CREATE", "UPDATE"] + resources: ["services"] + validations: + - expression: "object.spec.type != 'LoadBalancer'" + message: "Service of type LoadBalancer is not allowed." diff --git a/installer/charts/educates-training-platform/charts/session-manager/files/kyverno-policies/workshop-policies/restrict-node-port.yaml b/installer/charts/educates-training-platform/charts/session-manager/files/kyverno-policies/workshop-policies/restrict-node-port.yaml new file mode 100644 index 000000000..43f10702b --- /dev/null +++ b/installer/charts/educates-training-platform/charts/session-manager/files/kyverno-policies/workshop-policies/restrict-node-port.yaml @@ -0,0 +1,33 @@ +apiVersion: policies.kyverno.io/v1 +kind: ValidatingPolicy +metadata: + annotations: + policies.kyverno.io/category: Best Practices + policies.kyverno.io/description: >- + This policy restricts the creation of Services with type NodePort. + NodePort services expose applications on a static port on each node, which + can pose security risks and complicate network management. + policies.kyverno.io/severity: medium + policies.kyverno.io/subject: Service + policies.kyverno.io/title: Restrict NodePort Services + name: restrict-nodeport +spec: + evaluation: + background: + enabled: true + matchConstraints: + resourceRules: + - apiGroups: + - '' + apiVersions: + - v1 + operations: + - CREATE + - UPDATE + resources: + - services + validationActions: + - Audit + validations: + - expression: object.spec.type != 'NodePort' + message: Services of type NodePort are not allowed. diff --git a/installer/charts/educates-training-platform/charts/session-manager/files/kyverno-policies/workshop-policies/restrict-service-external-ips.yaml b/installer/charts/educates-training-platform/charts/session-manager/files/kyverno-policies/workshop-policies/restrict-service-external-ips.yaml new file mode 100644 index 000000000..bc43c5d3a --- /dev/null +++ b/installer/charts/educates-training-platform/charts/session-manager/files/kyverno-policies/workshop-policies/restrict-service-external-ips.yaml @@ -0,0 +1,31 @@ +apiVersion: policies.kyverno.io/v1 +kind: ValidatingPolicy +metadata: + annotations: + policies.kyverno.io/category: Best Practices + policies.kyverno.io/description: >- + This policy restricts the use of externalIPs in Service resources. + External IPs can pose security risks and should be carefully controlled. + policies.kyverno.io/severity: medium + policies.kyverno.io/title: Restrict External IPs + name: restrict-external-ips +spec: + evaluation: + background: + enabled: true + matchConstraints: + resourceRules: + - apiGroups: + - '' + apiVersions: + - v1 + operations: + - CREATE + - UPDATE + resources: + - services + validationActions: + - Audit + validations: + - expression: '!has(object.spec.externalIPs) || size(object.spec.externalIPs) == 0' + message: externalIPs are not allowed. diff --git a/installer/charts/educates-training-platform/charts/session-manager/templates/_helpers.tpl b/installer/charts/educates-training-platform/charts/session-manager/templates/_helpers.tpl new file mode 100644 index 000000000..e8a09445b --- /dev/null +++ b/installer/charts/educates-training-platform/charts/session-manager/templates/_helpers.tpl @@ -0,0 +1,513 @@ +{{- define "session-manager.labels" -}} +app.kubernetes.io/name: session-manager +app.kubernetes.io/instance: {{ .Release.Name }} +app.kubernetes.io/component: session-manager +app.kubernetes.io/part-of: educates +app.kubernetes.io/managed-by: {{ .Release.Service }} +app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} +helm.sh/chart: {{ printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} +{{- end -}} + +{{- define "session-manager.selectorLabels" -}} +deployment: session-manager +{{- end -}} + +{{/* +Resolve a cross-cutting values block (clusterIngress, clusterSecurity) by +deep-merging the umbrella's `global:` over the subchart's local block. +Globals win where set; subchart-local defaults pass through otherwise. +Returned as a YAML string — consume via `fromYaml`. +*/}} + +{{/* +Resolve the development imageRegistry override. Reads BOTH `.development. +imageRegistry` (subchart-local) and `.global.development.imageRegistry` +(umbrella global), with global winning per-leaf. Returns the user's intent +verbatim — no Chart.yaml annotation fallback. Consumers that need the +"effective" registry for chart-rendered refs should use +`session-manager.resolvedImageRegistry` instead, which falls back to +annotations. + +This raw form is what gets emitted into the operator-config blob's +`imageRegistry` field — empty in normal use, so the runtime falls back to +`registry.default.svc.cluster.local` for `$(image_repository)` workshop +content placeholder resolution. +*/}} +{{- define "session-manager.resolvedDevelopmentImageRegistry" -}} +{{- $local := default dict (default dict .Values.development).imageRegistry -}} +{{- $global := default dict (default dict (default dict .Values.global).development).imageRegistry -}} +{{- toYaml (mergeOverwrite (deepCopy $local) $global) -}} +{{- end -}} + +{{/* +Resolve the effective imageRegistry for chart-rendered refs (chart pod +image, pause image, Educates-published entries in the imageVersions +helper). Layered resolution: + 1. `.development.imageRegistry` (subchart-local) and + `.global.development.imageRegistry` (umbrella global), deep-merged + with global winning. + 2. Per-leaf fallback to Chart.yaml annotations + (`educates.dev/image-registry-host` / `-namespace`) when the merged + value is empty. Annotations are the publish-time default — the + release workflow updates them per fork. +*/}} +{{- define "session-manager.resolvedImageRegistry" -}} +{{- $merged := include "session-manager.resolvedDevelopmentImageRegistry" . | fromYaml -}} +{{- if not $merged.host -}} + {{- $_ := set $merged "host" (index .Chart.Annotations "educates.dev/image-registry-host" | default "") -}} +{{- end -}} +{{- if not $merged.namespace -}} + {{- $_ := set $merged "namespace" (index .Chart.Annotations "educates.dev/image-registry-namespace" | default "") -}} +{{- end -}} +{{- toYaml $merged -}} +{{- end -}} + +{{- define "session-manager.resolvedClusterIngress" -}} +{{- $local := default dict .Values.clusterIngress -}} +{{- $global := default dict (default dict .Values.global).clusterIngress -}} +{{- toYaml (mergeOverwrite (deepCopy $local) $global) -}} +{{- end -}} + +{{- define "session-manager.resolvedClusterSecurity" -}} +{{- $local := default dict .Values.clusterSecurity -}} +{{- $global := default dict (default dict .Values.global).clusterSecurity -}} +{{- toYaml (mergeOverwrite (deepCopy $local) $global) -}} +{{- end -}} + +{{/* +Compose the registry+namespace prefix from the resolved imageRegistry. +Two forms: + host + namespace -> "{host}/{namespace}" + host alone -> "{host}" +Used as the default prefix for the chart-pod image, the pause image, and the +Educates-published entries in the `imageVersions` helper. A user that points +imageRegistry at a fork or a local registry redirects all three at once. +*/}} +{{- define "session-manager.imageRegistryPrefix" -}} +{{- $ir := include "session-manager.resolvedImageRegistry" . | fromYaml -}} +{{- $host := default "" $ir.host -}} +{{- $ns := default "" $ir.namespace -}} +{{- if and $host $ns -}} +{{ $host }}/{{ $ns }} +{{- else if $host -}} +{{ $host }} +{{- else -}} +{{- fail "imageRegistry.host could not be resolved. Either set Chart.yaml annotation `educates.dev/image-registry-host` (publish-time default) or override locally via .development.imageRegistry / .global.development.imageRegistry." -}} +{{- end -}} +{{- end -}} + +{{- define "session-manager.image.repository" -}} +{{- if .Values.image.repository -}} +{{ .Values.image.repository }} +{{- else -}} +{{ include "session-manager.imageRegistryPrefix" . }}/educates-session-manager +{{- end -}} +{{- end -}} + +{{- define "session-manager.image.tag" -}} +{{- default .Chart.AppVersion .Values.image.tag -}} +{{- end -}} + +{{- define "session-manager.image.pullPolicy" -}} +{{- if .Values.image.pullPolicy -}} +{{ .Values.image.pullPolicy }} +{{- else -}} +{{- $tag := include "session-manager.image.tag" . -}} +{{- if or (eq $tag "latest") (eq $tag "main") (eq $tag "master") (eq $tag "develop") -}} +Always +{{- else -}} +IfNotPresent +{{- end -}} +{{- end -}} +{{- end -}} + +{{/* +True when the resolved clusterIngress.caCertificateRef.name is set — drives +rendering of the chart-side ca-trust-store init container in the +session-manager Deployment. The init container reuses the main session-manager +image (Fedora-based: has `update-ca-trust` and `tar`), so no extra image pull +on the node. Mirrors the runtime-side overlay session-manager already applies +to spawned pods (workshopsession.py) and v3's overlay-ca-injector.yaml. +*/}} +{{- define "session-manager.caTrustEnabled" -}} +{{- $ci := include "session-manager.resolvedClusterIngress" . | fromYaml -}} +{{- $caRef := default dict $ci.caCertificateRef -}} +{{- if $caRef.name }}true{{- end -}} +{{- end -}} + +{{/* +Image references the image-puller DaemonSet pre-pulls, as a YAML array. +An explicit imagePrePuller.images wins verbatim. When empty, default to +the v3-equivalent set — training-portal + base-environment — resolved +through the imageVersions inventory so registry relocation +(development.imageRegistry) and per-name imageVersions overrides are +honoured. Mirrors v3's image-puller DaemonSet, which always pre-pulled +training-portal plus a prePullImages list defaulting to +["base-environment"]. +*/}} +{{- define "session-manager.prePullImages" -}} +{{- if .Values.imagePrePuller.images -}} +{{ toYaml .Values.imagePrePuller.images }} +{{- else -}} +{{- $inventory := include "session-manager.imageVersions" . | fromYamlArray -}} +{{- $defaults := list -}} +{{- range $inventory -}} +{{- if or (eq .name "training-portal") (eq .name "base-environment") -}} +{{- $defaults = append $defaults .image -}} +{{- end -}} +{{- end -}} +{{ toYaml $defaults }} +{{- end -}} +{{- end -}} + +{{- define "session-manager.pause.image.repository" -}} +{{- if .Values.imagePrePuller.pauseImage.repository -}} +{{ .Values.imagePrePuller.pauseImage.repository }} +{{- else -}} +{{ include "session-manager.imageRegistryPrefix" . }}/educates-pause-container +{{- end -}} +{{- end -}} + +{{- define "session-manager.pause.image.tag" -}} +{{- default .Chart.AppVersion .Values.imagePrePuller.pauseImage.tag -}} +{{- end -}} + +{{- define "session-manager.pause.image.pullPolicy" -}} +{{- if .Values.imagePrePuller.pauseImage.pullPolicy -}} +{{ .Values.imagePrePuller.pauseImage.pullPolicy }} +{{- else -}} +{{- $tag := include "session-manager.pause.image.tag" . -}} +{{- if or (eq $tag "latest") (eq $tag "main") (eq $tag "master") (eq $tag "develop") -}} +Always +{{- else -}} +IfNotPresent +{{- end -}} +{{- end -}} +{{- end -}} + +{{/* +Auto-derive imagePullPolicy for an arbitrary fully-qualified image ref +passed in as a string. +*/}} +{{- define "session-manager.derivedPullPolicy" -}} +{{- $parts := splitList ":" . -}} +{{- $tag := "" -}} +{{- if eq (len $parts) 1 -}} + {{- $tag = "" -}} +{{- else -}} + {{- $tag = last $parts -}} +{{- end -}} +{{- if or (eq $tag "") (eq $tag "latest") (eq $tag "main") (eq $tag "master") (eq $tag "develop") -}} +Always +{{- else -}} +IfNotPresent +{{- end -}} +{{- end -}} + +{{/* +Derive ingress protocol from the resolved clusterIngress. `protocol` wins +when set; otherwise "https" if a tlsCertificateRef.name is provided, "http" +otherwise. Mirrors operator_config.py's own derivation. +*/}} +{{- define "session-manager.derivedProtocol" -}} +{{- $ci := include "session-manager.resolvedClusterIngress" . | fromYaml -}} +{{- $tlsRef := default dict $ci.tlsCertificateRef -}} +{{- if $ci.protocol -}} +{{- $ci.protocol -}} +{{- else if $tlsRef.name -}} +https +{{- else -}} +http +{{- end -}} +{{- end -}} + +{{/* +Build the YAML stream for the `kyverno-policies.yaml` key of the +`educates-config` Secret. session-manager reads the result via +`yaml.load_all` and creates a per-workshop-environment copy of each policy, +scoped to the environment's session namespaces (see handlers/kyverno_rules.py). +Concatenates: + 1. Bundled workshop policies under files/kyverno-policies/workshop-policies/ + (when workshopSecurity.rulesEngine == "Kyverno"). These are now + `ValidatingPolicy` resources (policies.kyverno.io). + 2. User-supplied policies from workshopSecurity.additionalKyvernoPolicies + (also gated on Kyverno). A new Policy type (ValidatingPolicy, ...) is + scoped natively; a legacy ClusterPolicy is still scoped but deprecated + (the runtime logs a warning), tracking Kyverno's own ClusterPolicy + removal in 1.20. +Each document is separated by `---\n`. +*/}} +{{- define "session-manager.kyvernoPoliciesContent" -}} +{{- $ws := .Values.workshopSecurity -}} +{{- $output := "" -}} +{{- if eq $ws.rulesEngine "Kyverno" -}} + {{- range $path, $_ := .Files.Glob "files/kyverno-policies/workshop-policies/*.yaml" -}} + {{- $content := $.Files.Get $path | trim -}} + {{- $output = printf "%s---\n%s\n" $output $content -}} + {{- end -}} + {{- range default list $ws.additionalKyvernoPolicies -}} + {{- $content := toYaml . | trim -}} + {{- $output = printf "%s---\n%s\n" $output $content -}} + {{- end -}} +{{- end -}} +{{- $output -}} +{{- end -}} + +{{/* +Default `imageVersions` set the chart ships, mirroring v3's +carvel-installer `images.yaml`. Two kinds of entries: + + - Educates-published images. Repository prefix derived from + `imageRegistry.{host,namespace}` so a fork or local registry + redirects them in one knob; tag derived from `.Chart.AppVersion` + so a chart release that bumps the runtime moves these in lock- + step. + - Upstream pins (docker-in-docker, loftsh-*, debian-base) that + aren't Educates-published. Hard-coded to specific upstream refs; + `imageRegistry` does NOT relocate them — override the matching + `imageVersions` entry directly when mirroring. + +User overrides in `.Values.imageVersions` are merged in BY NAME — each +user entry replaces the default with the same `name`, but other defaults +pass through untouched. Names not in this default list are appended, +which preserves forward-compat with new runtime images. + +Returns the merged list as a YAML array string (consume via fromYamlArray). +*/}} +{{- define "session-manager.imageVersions" -}} +{{- $repo := include "session-manager.imageRegistryPrefix" . -}} +{{- $v := .Chart.AppVersion -}} +{{- $defaults := list + (dict "name" "training-portal" "image" (printf "%s/educates-training-portal:%s" $repo $v)) + (dict "name" "docker-registry" "image" (printf "%s/educates-docker-registry:%s" $repo $v)) + (dict "name" "tunnel-manager" "image" (printf "%s/educates-tunnel-manager:%s" $repo $v)) + (dict "name" "image-cache" "image" (printf "%s/educates-image-cache:%s" $repo $v)) + (dict "name" "assets-server" "image" (printf "%s/educates-assets-server:%s" $repo $v)) + (dict "name" "contour-bundle" "image" (printf "%s/educates-contour-bundle:%s" $repo $v)) + (dict "name" "base-environment" "image" (printf "%s/educates-base-environment:%s" $repo $v)) + (dict "name" "jdk8-environment" "image" (printf "%s/educates-jdk8-environment:%s" $repo $v)) + (dict "name" "jdk11-environment" "image" (printf "%s/educates-jdk11-environment:%s" $repo $v)) + (dict "name" "jdk17-environment" "image" (printf "%s/educates-jdk17-environment:%s" $repo $v)) + (dict "name" "jdk21-environment" "image" (printf "%s/educates-jdk21-environment:%s" $repo $v)) + (dict "name" "conda-environment" "image" (printf "%s/educates-conda-environment:%s" $repo $v)) + (dict "name" "debian-base-image" "image" "debian:sid-20230502-slim") + (dict "name" "docker-in-docker" "image" "docker:27.5.1-dind") + (dict "name" "loftsh-kubernetes-v1.31" "image" "ghcr.io/loft-sh/kubernetes:v1.31.1") + (dict "name" "loftsh-kubernetes-v1.32" "image" "ghcr.io/loft-sh/kubernetes:v1.32.1") + (dict "name" "loftsh-kubernetes-v1.33" "image" "ghcr.io/loft-sh/kubernetes:v1.33.4") + (dict "name" "loftsh-kubernetes-v1.34" "image" "ghcr.io/loft-sh/kubernetes:v1.34.0") + (dict "name" "loftsh-vcluster" "image" "ghcr.io/loft-sh/vcluster-oss:0.30.2") +-}} +{{- $overrides := dict -}} +{{- range default list .Values.imageVersions -}} + {{- $_ := set $overrides .name .image -}} +{{- end -}} +{{- $merged := list -}} +{{- $defaultNames := dict -}} +{{- range $defaults -}} + {{- $name := .name -}} + {{- $image := .image -}} + {{- if hasKey $overrides $name -}} + {{- $image = index $overrides $name -}} + {{- end -}} + {{- $merged = append $merged (dict "name" $name "image" $image) -}} + {{- $_ := set $defaultNames $name true -}} +{{- end -}} +{{- range default list .Values.imageVersions -}} + {{- if not (hasKey $defaultNames .name) -}} + {{- $merged = append $merged (dict "name" .name "image" .image) -}} + {{- end -}} +{{- end -}} +{{- toYaml $merged -}} +{{- end -}} + +{{/* +Resolve training-portal credentials with stability across `helm upgrade` and +session-manager pod restarts. Priority for each field: + + 1. User-supplied non-empty value in .Values.trainingPortal.{credentials, + clients}. Explicit operator intent always wins. + 2. Previously-persisted value, read back from the live `educates-config` + Secret if present. This is what keeps generated credentials stable + across upgrades and restarts. + 3. Generated defaults: fixed usernames ("educates", "robot@educates"); + 32-char randAlphaNum for passwords and OAuth client id/secret. + +The runtime's xget() helper falls back to its own defaults only when keys are +*absent* — not when they're set to empty strings. The chart previously +emitted `username: ""` / `password: ""` keys unconditionally, which made the +runtime use "" verbatim and broke training-portal initialisation. This helper +ensures non-empty values land in the rendered config. + +The lookup-based reuse mirrors the v3 carvel installer's "ytt-generated-once +at install time" semantics. `helm lookup` returns nil during `helm template` +(no cluster connection); in that case the generated branch produces fresh +values, which is the expected behaviour for offline rendering. +*/}} +{{- define "session-manager.resolvedTrainingPortal" -}} +{{- $tp := default dict .Values.trainingPortal -}} +{{- $cur := dict -}} +{{- $existing := lookup "v1" "Secret" .Release.Namespace "educates-config" -}} +{{- if $existing -}} + {{- $raw := index (default dict $existing.data) "educates-operator-config.yaml" | default "" -}} + {{- if $raw -}} + {{- $cfg := $raw | b64dec | fromYaml -}} + {{- $cur = default dict (dig "trainingPortal" dict $cfg) -}} + {{- end -}} +{{- end -}} +{{- $adminUsername := dig "credentials" "admin" "username" "" $tp -}} +{{- if eq $adminUsername "" -}}{{- $adminUsername = dig "credentials" "admin" "username" "" $cur -}}{{- end -}} +{{- if eq $adminUsername "" -}}{{- $adminUsername = "educates" -}}{{- end -}} +{{- $adminPassword := dig "credentials" "admin" "password" "" $tp -}} +{{- if eq $adminPassword "" -}}{{- $adminPassword = dig "credentials" "admin" "password" "" $cur -}}{{- end -}} +{{- if eq $adminPassword "" -}}{{- $adminPassword = randAlphaNum 32 -}}{{- end -}} +{{- $robotUsername := dig "credentials" "robot" "username" "" $tp -}} +{{- if eq $robotUsername "" -}}{{- $robotUsername = dig "credentials" "robot" "username" "" $cur -}}{{- end -}} +{{- if eq $robotUsername "" -}}{{- $robotUsername = "robot@educates" -}}{{- end -}} +{{- $robotPassword := dig "credentials" "robot" "password" "" $tp -}} +{{- if eq $robotPassword "" -}}{{- $robotPassword = dig "credentials" "robot" "password" "" $cur -}}{{- end -}} +{{- if eq $robotPassword "" -}}{{- $robotPassword = randAlphaNum 32 -}}{{- end -}} +{{- $robotClientId := dig "clients" "robot" "id" "" $tp -}} +{{- if eq $robotClientId "" -}}{{- $robotClientId = dig "clients" "robot" "id" "" $cur -}}{{- end -}} +{{- if eq $robotClientId "" -}}{{- $robotClientId = randAlphaNum 32 -}}{{- end -}} +{{- $robotClientSecret := dig "clients" "robot" "secret" "" $tp -}} +{{- if eq $robotClientSecret "" -}}{{- $robotClientSecret = dig "clients" "robot" "secret" "" $cur -}}{{- end -}} +{{- if eq $robotClientSecret "" -}}{{- $robotClientSecret = randAlphaNum 32 -}}{{- end -}} +{{- $out := dict + "credentials" (dict + "admin" (dict "username" $adminUsername "password" $adminPassword) + "robot" (dict "username" $robotUsername "password" $robotPassword) + ) + "clients" (dict + "robot" (dict "id" $robotClientId "secret" $robotClientSecret) + ) +-}} +{{- toYaml $out -}} +{{- end -}} + +{{/* +Compose the `educates-operator-config.yaml` Secret content from typed values. +Auto-injects `operator.namespace` (release ns) and `version` (.Chart.AppVersion +— the bundled Educates runtime version, distinct from the chart-package +`Chart.Version`). Lowercases policy/rules engine names to match the runtime's +expected casing. Materialises empty-string TLS/CA refs explicitly — the runtime +reads these via xget() with no default, so absent keys become Python None and +crash later when encoded as strings (see project_runtime_config_quirks memory). +Deep-merges .Values.config on top so the escape hatch wins on conflict. +*/}} +{{- define "session-manager.operatorConfigYAML" -}} +{{- $ci := include "session-manager.resolvedClusterIngress" . | fromYaml -}} +{{- if not $ci.domain -}} +{{- fail "clusterIngress.domain is required (set globally under .global.clusterIngress.domain or locally under session-manager.clusterIngress.domain)" -}} +{{- end -}} +{{- $tlsRef := default dict $ci.tlsCertificateRef -}} +{{- $caRef := default dict $ci.caCertificateRef -}} +{{- $cs := include "session-manager.resolvedClusterSecurity" . | fromYaml -}} +{{- $ws := .Values.workshopSecurity -}} +{{/* +Emit the user-supplied development.imageRegistry verbatim into the runtime +config — NOT the annotation-resolved one. Empty in normal use means the +runtime falls back to `registry.default.svc.cluster.local` for the +`$(image_repository)` workshop-content placeholder. The chart's own +imageVersions helper handles all Educates runtime images explicitly with +fully-qualified refs, so emitting empty here doesn't break runtime image +resolution. +*/}} +{{- $ir := include "session-manager.resolvedDevelopmentImageRegistry" . | fromYaml -}} +{{- $tp := default dict .Values.trainingPortal -}} +{{- $sc := default dict .Values.sessionCookies -}} +{{- $cstg := default dict .Values.clusterStorage -}} +{{- $crt := default dict .Values.clusterRuntime -}} +{{- $cnet := default dict .Values.clusterNetwork -}} +{{- $dd := default dict .Values.dockerDaemon -}} +{{- $proxy := default dict $dd.proxyCache -}} +{{- $wa := default dict .Values.workshopAnalytics -}} +{{- $wstyle := default dict .Values.websiteStyling -}} +{{- $typed := dict + "operator" (dict "namespace" .Release.Namespace) + "version" .Chart.AppVersion + "clusterIngress" (dict + "domain" $ci.domain + "class" (default "" $ci.class) + "protocol" (include "session-manager.derivedProtocol" .) + "tlsCertificateRef" (dict + "name" (default "" $tlsRef.name) + "namespace" (default "" $tlsRef.namespace) + ) + "caCertificateRef" (dict + "name" (default "" $caRef.name) + "namespace" (default "" $caRef.namespace) + ) + ) + "clusterSecurity" (dict "policyEngine" (lower $cs.policyEngine)) + "workshopSecurity" (dict "rulesEngine" (lower $ws.rulesEngine)) + "imageRegistry" (dict + "host" (default "" $ir.host) + "namespace" (default "" $ir.namespace) + ) + "imageVersions" (include "session-manager.imageVersions" . | fromYamlArray) + "trainingPortal" (include "session-manager.resolvedTrainingPortal" . | fromYaml) + "sessionCookies" (dict "domain" (default "" $sc.domain)) + "clusterStorage" (dict + "class" (default "" $cstg.class) + "user" $cstg.user + "group" (default 1 $cstg.group) + ) + "clusterRuntime" (dict "class" (default "" $crt.class)) + "clusterNetwork" (dict "blockCIDRs" (default list $cnet.blockCIDRs)) + "dockerDaemon" (dict + "networkMTU" (default 1400 $dd.networkMTU) + "proxyCache" (dict + "remoteURL" (default "" $proxy.remoteURL) + "username" (default "" $proxy.username) + "password" (default "" $proxy.password) + ) + ) + "workshopAnalytics" (dict + "google" (dict "trackingId" (default "" (dig "google" "trackingId" "" $wa))) + "clarity" (dict "trackingId" (default "" (dig "clarity" "trackingId" "" $wa))) + "amplitude" (dict "trackingId" (default "" (dig "amplitude" "trackingId" "" $wa))) + "webhook" (dict "url" (default "" (dig "webhook" "url" "" $wa))) + ) + "websiteStyling" (dict + "defaultTheme" (default "" $wstyle.defaultTheme) + "frameAncestors" (default list $wstyle.frameAncestors) + ) +-}} +{{- $merged := mergeOverwrite $typed (deepCopy (default dict .Values.config)) -}} +{{- toYaml $merged -}} +{{- end -}} + +{{/* +Map the structured `websiteStyling.inline` values to the flat secret-key shape +the runtime expects in the `default-website-theme` Secret. Returns a YAML map +of stringData entries (or empty if no inline assets are populated). + + workshopDashboard.{html,script,style} -> workshop-dashboard.{html,js,css} + workshopInstructions.{html,script,style} -> workshop-instructions.{html,js,css} + workshopStarted.html -> workshop-started.html + workshopFinished.html -> workshop-finished.html + trainingPortal.{html,script,style} -> training-portal.{html,js,css} +*/}} +{{- define "session-manager.inlineThemeStringData" -}} +{{- $inline := default dict (default dict .Values.websiteStyling).inline -}} +{{- $entries := dict -}} +{{- $tripleSources := list + (list "workshopDashboard" "workshop-dashboard") + (list "workshopInstructions" "workshop-instructions") + (list "trainingPortal" "training-portal") +-}} +{{- range $tripleSources -}} + {{- $key := index . 0 -}} + {{- $prefix := index . 1 -}} + {{- $block := default dict (index $inline $key) -}} + {{- if $block.html }}{{- $_ := set $entries (printf "%s.html" $prefix) $block.html -}}{{- end -}} + {{- if $block.script }}{{- $_ := set $entries (printf "%s.js" $prefix) $block.script -}}{{- end -}} + {{- if $block.style }}{{- $_ := set $entries (printf "%s.css" $prefix) $block.style -}}{{- end -}} +{{- end -}} +{{- $started := default dict $inline.workshopStarted -}} +{{- if $started.html }}{{- $_ := set $entries "workshop-started.html" $started.html -}}{{- end -}} +{{- $finished := default dict $inline.workshopFinished -}} +{{- if $finished.html }}{{- $_ := set $entries "workshop-finished.html" $finished.html -}}{{- end -}} +{{- toYaml $entries -}} +{{- end -}} diff --git a/installer/charts/educates-training-platform/charts/session-manager/templates/clusterrolebindings.yaml b/installer/charts/educates-training-platform/charts/session-manager/templates/clusterrolebindings.yaml new file mode 100644 index 000000000..f8da51aa6 --- /dev/null +++ b/installer/charts/educates-training-platform/charts/session-manager/templates/clusterrolebindings.yaml @@ -0,0 +1,123 @@ +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: educates-session-manager + labels: + {{- include "session-manager.labels" . | nindent 4 }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: educates-session-manager +subjects: + - kind: ServiceAccount + name: session-manager + namespace: {{ .Release.Namespace }} +--- +# Built-in `admin` ClusterRole binding. Preserved unchanged from v3 — +# the runtime relies on this level of access in the spawned namespaces +# the operator manages. +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: educates-session-manager:admin + labels: + {{- include "session-manager.labels" . | nindent 4 }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: admin +subjects: + - kind: ServiceAccount + name: session-manager + namespace: {{ .Release.Namespace }} +--- +# Kyverno policy management. The Kyverno-shipped +# `kyverno:rbac:admin:policies` ClusterRole exists when Kyverno is +# installed (the v4 default policy engine). Without Kyverno this binding +# resolves to a non-existent role and grants nothing — harmless. It +# covers the legacy kyverno.io ClusterPolicy group, used by the +# deprecated workshop-provided ClusterPolicy path. +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: educates-session-manager:kyverno-policies + labels: + {{- include "session-manager.labels" . | nindent 4 }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: kyverno:rbac:admin:policies +subjects: + - kind: ServiceAccount + name: session-manager + namespace: {{ .Release.Namespace }} +--- +# Lets session-manager manage the per-environment ValidatingPolicy +# objects in the new policies.kyverno.io group (the bundled workshop +# rules are now ValidatingPolicy). Educates-owned role, so the binding is +# always valid; inert without the Kyverno CRD. +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: educates-session-manager:kyverno-validatingpolicies + labels: + {{- include "session-manager.labels" . | nindent 4 }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: educates-session-manager:kyverno-validatingpolicies +subjects: + - kind: ServiceAccount + name: session-manager + namespace: {{ .Release.Namespace }} +{{- if .Values.clusterAdmin }} +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: educates-session-manager:cluster-admin + labels: + {{- include "session-manager.labels" . | nindent 4 }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: cluster-admin +subjects: + - kind: ServiceAccount + name: session-manager + namespace: {{ .Release.Namespace }} +{{- end }} +{{- $cs := include "session-manager.resolvedClusterSecurity" . | fromYaml }} +{{- if eq $cs.policyEngine "OpenShiftSCC" }} +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: educates-session-manager-scc + labels: + {{- include "session-manager.labels" . | nindent 4 }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: educates-baseline-scc +subjects: + - kind: ServiceAccount + name: session-manager + namespace: {{ .Release.Namespace }} +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: educates-image-puller-scc + labels: + {{- include "session-manager.labels" . | nindent 4 }} + app.kubernetes.io/component: image-puller +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: educates-baseline-scc +subjects: + - kind: ServiceAccount + name: image-puller + namespace: {{ .Release.Namespace }} +{{- end }} diff --git a/installer/charts/educates-training-platform/charts/session-manager/templates/clusterroles.yaml b/installer/charts/educates-training-platform/charts/session-manager/templates/clusterroles.yaml new file mode 100644 index 000000000..7c55420db --- /dev/null +++ b/installer/charts/educates-training-platform/charts/session-manager/templates/clusterroles.yaml @@ -0,0 +1,476 @@ +{{- /* +ClusterRoles consumed by the session-manager and the runtime it spawns +(training portal pods, workshop session pods, tunnel manager). Copied +verbatim from v3 — these are the contract between session-manager and +its runtime, and changing them is out of scope for the v4 installer +work. Chart labels are added; the resource bodies are unchanged. +*/ -}} +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: educates-session-manager + labels: + {{- include "session-manager.labels" . | nindent 4 }} +aggregationRule: + clusterRoleSelectors: + - matchLabels: + rbac.educates.dev/extends-workshop-permissions: "true" +# `rules` is intentionally omitted: the clusterrole-aggregation-controller +# owns the .rules field on aggregate ClusterRoles, populating it by merging +# rules from labelled child roles. Declaring `rules: []` here would claim +# field ownership under server-side-apply (Helm v3+ uses SSA on upgrade), +# fighting the aggregation controller and producing a conflict error every +# reconcile: `conflict with "clusterrole-aggregation-controller": .rules`. +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: educates-session-manager:core + labels: + {{- include "session-manager.labels" . | nindent 4 }} + rbac.educates.dev/extends-workshop-permissions: "true" +rules: + - apiGroups: [""] + resources: [namespaces] + verbs: ["*"] + - apiGroups: [""] + resources: [limitranges, resourcequotas] + verbs: ["*"] + - apiGroups: [rbac.authorization.k8s.io] + resources: [clusterroles, clusterrolebindings] + verbs: ["*"] + - apiGroups: [training.educates.dev] + resources: + - workshops + - workshopsessions + - trainingportals + - workshopenvironments + - workshopallocations + - workshoprequests + verbs: ["*"] + - apiGroups: [secrets.educates.dev] + resources: [secretcopiers] + verbs: ["*"] +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: educates-view-session-role + labels: + {{- include "session-manager.labels" . | nindent 4 }} +rules: + - apiGroups: [""] + resources: + - configmaps + - endpoints + - persistentvolumeclaims + - persistentvolumeclaims/status + - pods + - replicationcontrollers + - replicationcontrollers/scale + - serviceaccounts + - services + - services/status + verbs: [get, list, watch] + - apiGroups: [""] + resources: + - bindings + - events + - limitranges + - namespaces/status + - pods/log + - pods/status + - replicationcontrollers/status + - resourcequotas + - resourcequotas/status + verbs: [get, list, watch] + - apiGroups: [""] + resources: [namespaces] + verbs: [get, list, watch] + - apiGroups: [apps] + resources: + - controllerrevisions + - daemonsets + - daemonsets/status + - deployments + - deployments/scale + - deployments/status + - replicasets + - replicasets/scale + - replicasets/status + - statefulsets + - statefulsets/scale + - statefulsets/status + verbs: [get, list, watch] + - apiGroups: [autoscaling] + resources: [horizontalpodautoscalers, horizontalpodautoscalers/status] + verbs: [get, list, watch] + - apiGroups: [batch] + resources: [cronjobs, cronjobs/status, jobs, jobs/status] + verbs: [get, list, watch] + - apiGroups: [extensions] + resources: + - daemonsets + - daemonsets/status + - deployments + - deployments/scale + - deployments/status + - ingresses + - ingresses/status + - replicasets + - replicasets/scale + - replicasets/status + - replicationcontrollers/scale + verbs: [get, list, watch] + - apiGroups: [policy] + resources: [poddisruptionbudgets, poddisruptionbudgets/status] + verbs: [get, list, watch] + - apiGroups: [networking.k8s.io] + resources: [ingresses, ingresses/status] + verbs: [get, list, watch] +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: educates-edit-session-role + labels: + {{- include "session-manager.labels" . | nindent 4 }} +rules: + - apiGroups: [""] + resources: [pods/attach, pods/exec, pods/portforward, pods/proxy, secrets, services/proxy] + verbs: [get, list, watch] + - apiGroups: [""] + resources: [serviceaccounts] + verbs: [impersonate] + - apiGroups: [""] + resources: [pods, pods/attach, pods/exec, pods/portforward, pods/proxy] + verbs: [create, delete, deletecollection, patch, update] + - apiGroups: [""] + resources: + - configmaps + - endpoints + - persistentvolumeclaims + - replicationcontrollers + - replicationcontrollers/scale + - secrets + - serviceaccounts + - services + - services/proxy + verbs: [create, delete, deletecollection, patch, update] + - apiGroups: [apps] + resources: + - daemonsets + - deployments + - deployments/rollback + - deployments/scale + - replicasets + - replicasets/scale + - statefulsets + - statefulsets/scale + verbs: [create, delete, deletecollection, patch, update] + - apiGroups: [autoscaling] + resources: [horizontalpodautoscalers] + verbs: [create, delete, deletecollection, patch, update] + - apiGroups: [batch] + resources: [cronjobs, jobs] + verbs: [create, delete, deletecollection, patch, update] + - apiGroups: [extensions] + resources: + - daemonsets + - deployments + - deployments/rollback + - deployments/scale + - ingresses + - replicasets + - replicasets/scale + - replicationcontrollers/scale + verbs: [create, delete, deletecollection, patch, update] + - apiGroups: [policy] + resources: [poddisruptionbudgets] + verbs: [create, delete, deletecollection, patch, update] + - apiGroups: [networking.k8s.io] + resources: [ingresses] + verbs: [create, delete, deletecollection, patch, update] + - apiGroups: [""] + resources: + - configmaps + - endpoints + - persistentvolumeclaims + - persistentvolumeclaims/status + - pods + - replicationcontrollers + - replicationcontrollers/scale + - serviceaccounts + - services + - services/status + verbs: [get, list, watch] + - apiGroups: [""] + resources: + - bindings + - events + - limitranges + - namespaces/status + - pods/log + - pods/status + - replicationcontrollers/status + - resourcequotas + - resourcequotas/status + verbs: [get, list, watch] + - apiGroups: [""] + resources: [namespaces] + verbs: [get, list, watch] + - apiGroups: [apps] + resources: + - controllerrevisions + - daemonsets + - daemonsets/status + - deployments + - deployments/scale + - deployments/status + - replicasets + - replicasets/scale + - replicasets/status + - statefulsets + - statefulsets/scale + - statefulsets/status + verbs: [get, list, watch] + - apiGroups: [autoscaling] + resources: [horizontalpodautoscalers, horizontalpodautoscalers/status] + verbs: [get, list, watch] + - apiGroups: [batch] + resources: [cronjobs, cronjobs/status, jobs, jobs/status] + verbs: [get, list, watch] + - apiGroups: [extensions] + resources: + - daemonsets + - daemonsets/status + - deployments + - deployments/scale + - deployments/status + - ingresses + - ingresses/status + - replicasets + - replicasets/scale + - replicasets/status + - replicationcontrollers/scale + verbs: [get, list, watch] + - apiGroups: [policy] + resources: [poddisruptionbudgets, poddisruptionbudgets/status] + verbs: [get, list, watch] + - apiGroups: [networking.k8s.io] + resources: [ingresses, ingresses/status] + verbs: [get, list, watch] +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: educates-admin-session-role + labels: + {{- include "session-manager.labels" . | nindent 4 }} +rules: + - apiGroups: [""] + resources: [pods/attach, pods/exec, pods/portforward, pods/proxy, secrets, services/proxy] + verbs: [get, list, watch] + - apiGroups: [""] + resources: [serviceaccounts] + verbs: [impersonate] + - apiGroups: [""] + resources: [pods, pods/attach, pods/exec, pods/portforward, pods/proxy] + verbs: [create, delete, deletecollection, patch, update] + - apiGroups: [""] + resources: + - configmaps + - endpoints + - persistentvolumeclaims + - replicationcontrollers + - replicationcontrollers/scale + - secrets + - serviceaccounts + - services + - services/proxy + verbs: [create, delete, deletecollection, patch, update] + - apiGroups: [apps] + resources: + - daemonsets + - deployments + - deployments/rollback + - deployments/scale + - replicasets + - replicasets/scale + - statefulsets + - statefulsets/scale + verbs: [create, delete, deletecollection, patch, update] + - apiGroups: [autoscaling] + resources: [horizontalpodautoscalers] + verbs: [create, delete, deletecollection, patch, update] + - apiGroups: [batch] + resources: [cronjobs, jobs] + verbs: [create, delete, deletecollection, patch, update] + - apiGroups: [extensions] + resources: + - daemonsets + - deployments + - deployments/rollback + - deployments/scale + - ingresses + - replicasets + - replicasets/scale + - replicationcontrollers/scale + verbs: [create, delete, deletecollection, patch, update] + - apiGroups: [policy] + resources: [poddisruptionbudgets] + verbs: [create, delete, deletecollection, patch, update] + - apiGroups: [networking.k8s.io] + resources: [ingresses] + verbs: [create, delete, deletecollection, patch, update] + - apiGroups: [""] + resources: + - configmaps + - endpoints + - persistentvolumeclaims + - persistentvolumeclaims/status + - pods + - replicationcontrollers + - replicationcontrollers/scale + - serviceaccounts + - services + - services/status + verbs: [get, list, watch] + - apiGroups: [""] + resources: + - bindings + - events + - limitranges + - namespaces/status + - pods/log + - pods/status + - replicationcontrollers/status + - resourcequotas + - resourcequotas/status + verbs: [get, list, watch] + - apiGroups: [""] + resources: [namespaces] + verbs: [get, list, watch] + - apiGroups: [apps] + resources: + - controllerrevisions + - daemonsets + - daemonsets/status + - deployments + - deployments/scale + - deployments/status + - replicasets + - replicasets/scale + - replicasets/status + - statefulsets + - statefulsets/scale + - statefulsets/status + verbs: [get, list, watch] + - apiGroups: [autoscaling] + resources: [horizontalpodautoscalers, horizontalpodautoscalers/status] + verbs: [get, list, watch] + - apiGroups: [batch] + resources: [cronjobs, cronjobs/status, jobs, jobs/status] + verbs: [get, list, watch] + - apiGroups: [extensions] + resources: + - daemonsets + - daemonsets/status + - deployments + - deployments/scale + - deployments/status + - ingresses + - ingresses/status + - replicasets + - replicasets/scale + - replicasets/status + - replicationcontrollers/scale + verbs: [get, list, watch] + - apiGroups: [policy] + resources: [poddisruptionbudgets, poddisruptionbudgets/status] + verbs: [get, list, watch] + - apiGroups: [networking.k8s.io] + resources: [ingresses, ingresses/status] + verbs: [get, list, watch] + - apiGroups: [authorization.k8s.io] + resources: [localsubjectaccessreviews] + verbs: [create] + - apiGroups: [rbac.authorization.k8s.io] + resources: [rolebindings, roles] + verbs: [create, delete, deletecollection, get, list, patch, update, watch] +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: educates-training-portal + labels: + {{- include "session-manager.labels" . | nindent 4 }} +rules: + - apiGroups: [""] + resources: [namespaces] + resourceNames: [default] + verbs: [get] + - apiGroups: [""] + resources: [secrets] + verbs: [get, list, watch, create] + - apiGroups: [training.educates.dev] + resources: + - workshops + - workshopenvironments + - workshopsessions + - workshopallocations + - trainingportals + verbs: [get, list, watch] + - apiGroups: [training.educates.dev] + resources: + - trainingportals/finalizers + - workshopenvironments/finalizers + - workshopsessions/finalizers + verbs: [update] + - apiGroups: [training.educates.dev] + resources: + - workshopenvironments + - workshopsessions + - workshopallocations + verbs: [create, patch, delete] +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: educates-tunnel-manager + labels: + {{- include "session-manager.labels" . | nindent 4 }} +rules: + - apiGroups: [""] + resources: [events] + verbs: [create] + - apiGroups: [""] + resources: [secrets] + verbs: [get, list, watch, create, delete, deletecollection, patch, update] + - apiGroups: [""] + resources: [namespaces] + verbs: [get, list, watch] + - apiGroups: [""] + resources: [serviceaccounts] + verbs: [get, list, watch, patch, update] + - apiGroups: [training.educates.dev] + resources: [workshopsessions] + verbs: [get, list, watch] +--- +# Lets session-manager create the per-workshop-environment Kyverno +# ValidatingPolicy objects (policies.kyverno.io) that scope the bundled +# workshop rules to a workshop's session namespaces. The Kyverno-shipped +# `kyverno:rbac:admin:policies` role (bound separately) only covers the +# legacy kyverno.io ClusterPolicy group, so the new Policy group needs an +# explicit grant. Inert when Kyverno (and the CRD) isn't installed. +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: educates-session-manager:kyverno-validatingpolicies + labels: + {{- include "session-manager.labels" . | nindent 4 }} +rules: + - apiGroups: [policies.kyverno.io] + resources: [validatingpolicies] + verbs: [get, list, watch, create, update, patch, delete] diff --git a/installer/charts/educates-training-platform/charts/session-manager/templates/daemonset-image-puller.yaml b/installer/charts/educates-training-platform/charts/session-manager/templates/daemonset-image-puller.yaml new file mode 100644 index 000000000..6391781cb --- /dev/null +++ b/installer/charts/educates-training-platform/charts/session-manager/templates/daemonset-image-puller.yaml @@ -0,0 +1,45 @@ +{{- if .Values.imagePrePuller.enabled }} +apiVersion: apps/v1 +kind: DaemonSet +metadata: + name: image-puller + namespace: {{ .Release.Namespace }} + labels: + {{- include "session-manager.labels" . | nindent 4 }} +spec: + selector: + matchLabels: + app: image-puller + template: + metadata: + labels: + {{- include "session-manager.labels" . | nindent 8 }} + app.kubernetes.io/component: image-puller + app: image-puller + spec: + serviceAccountName: image-puller + {{- with .Values.imagePullSecrets }} + imagePullSecrets: + {{- toYaml . | nindent 8 }} + {{- end }} + securityContext: + runAsNonRoot: true + runAsUser: 1001 + {{- with include "session-manager.prePullImages" . | fromYamlArray }} + initContainers: + {{- range $i, $image := . }} + - name: prepull-{{ $i }} + image: {{ $image | quote }} + imagePullPolicy: {{ include "session-manager.derivedPullPolicy" $image }} + command: ["/bin/true"] + {{- end }} + {{- end }} + containers: + - name: pause + image: "{{ include "session-manager.pause.image.repository" . }}:{{ include "session-manager.pause.image.tag" . }}" + imagePullPolicy: {{ include "session-manager.pause.image.pullPolicy" . }} + securityContext: + allowPrivilegeEscalation: false + capabilities: + drop: ["ALL"] +{{- end }} diff --git a/installer/charts/educates-training-platform/charts/session-manager/templates/deployment.yaml b/installer/charts/educates-training-platform/charts/session-manager/templates/deployment.yaml new file mode 100644 index 000000000..50f99309e --- /dev/null +++ b/installer/charts/educates-training-platform/charts/session-manager/templates/deployment.yaml @@ -0,0 +1,116 @@ +{{- $ci := include "session-manager.resolvedClusterIngress" . | fromYaml -}} +{{- $caRef := default dict $ci.caCertificateRef -}} +{{- $caEnabled := and $caRef.name true -}} +apiVersion: apps/v1 +kind: Deployment +metadata: + name: session-manager + namespace: {{ .Release.Namespace }} + labels: + {{- include "session-manager.labels" . | nindent 4 }} +spec: + replicas: 1 + strategy: + type: Recreate + selector: + matchLabels: + {{- include "session-manager.selectorLabels" . | nindent 6 }} + template: + metadata: + labels: + {{- include "session-manager.labels" . | nindent 8 }} + {{- include "session-manager.selectorLabels" . | nindent 8 }} + annotations: + # Roll the Deployment whenever the operator config changes so + # session-manager picks up the new YAML without a manual restart. + checksum/config: {{ include (print $.Template.BasePath "/secret-config.yaml") . | sha256sum }} + spec: + serviceAccountName: session-manager + automountServiceAccountToken: false + {{- with .Values.imagePullSecrets }} + imagePullSecrets: + {{- toYaml . | nindent 8 }} + {{- end }} + securityContext: + runAsNonRoot: true + runAsUser: 1001 + {{- if $caEnabled }} + # ca-trust-store init container reuses the main session-manager image + # (Fedora-based: has `update-ca-trust` and `tar`). Mirrors v3's + # overlay-ca-injector.yaml mechanism with no extra image pull. + # Required when session-manager calls TLS endpoints fronted by a + # private/self-signed CA. Runs as root to write to /etc/pki/ca-trust; + # explicitly relaxes the pod-level `runAsNonRoot: true`. + initContainers: + - name: ca-trust-store-initialization + image: "{{ include "session-manager.image.repository" . }}:{{ include "session-manager.image.tag" . }}" + imagePullPolicy: {{ include "session-manager.image.pullPolicy" . }} + securityContext: + runAsNonRoot: false + runAsUser: 0 + allowPrivilegeEscalation: false + command: ["/bin/bash", "-c"] + args: + - "update-ca-trust && tar -C /etc/pki/ca-trust -cf - . | tar -C /mnt -xf -" + volumeMounts: + - name: cluster-ca + mountPath: /etc/pki/ca-trust/source/anchors/Cluster_Ingress_CA.pem + subPath: ca.crt + - name: cluster-ca-trust + mountPath: /mnt + {{- end }} + containers: + - name: operator + image: "{{ include "session-manager.image.repository" . }}:{{ include "session-manager.image.tag" . }}" + imagePullPolicy: {{ include "session-manager.image.pullPolicy" . }} + securityContext: + allowPrivilegeEscalation: false + capabilities: + drop: ["ALL"] + startupProbe: + httpGet: + path: /healthz?probe=startup + port: 8080 + initialDelaySeconds: 15 + periodSeconds: 10 + timeoutSeconds: 1 + successThreshold: 1 + failureThreshold: 4 + livenessProbe: + httpGet: + path: /healthz?probe=liveness + port: 8080 + initialDelaySeconds: 15 + periodSeconds: 30 + timeoutSeconds: 1 + successThreshold: 1 + failureThreshold: 3 + {{- with .Values.resources }} + resources: + {{- toYaml . | nindent 12 }} + {{- end }} + volumeMounts: + - name: config + mountPath: /opt/app-root/config/ + - name: token + mountPath: /var/run/secrets/kubernetes.io/serviceaccount + readOnly: true + {{- if $caEnabled }} + - name: cluster-ca-trust + mountPath: /etc/pki/ca-trust + readOnly: true + {{- end }} + volumes: + - name: config + secret: + secretName: educates-config + - name: token + secret: + secretName: session-manager-token + {{- if $caEnabled }} + - name: cluster-ca + secret: + secretName: {{ $caRef.name | quote }} + - name: cluster-ca-trust + emptyDir: {} + {{- end }} diff --git a/installer/charts/educates-training-platform/charts/session-manager/templates/kyverno-cluster-policies.yaml b/installer/charts/educates-training-platform/charts/session-manager/templates/kyverno-cluster-policies.yaml new file mode 100644 index 000000000..03ce2bdd4 --- /dev/null +++ b/installer/charts/educates-training-platform/charts/session-manager/templates/kyverno-cluster-policies.yaml @@ -0,0 +1,28 @@ +{{- /* +Cluster-wide Kyverno policies, gated on +`clusterSecurity.policyEngine == "Kyverno"`. Two sources: + + 1. The bundled Pod Security Standards profiles (baseline + restricted) + under files/kyverno-policies/cluster-policies/. These are now + `ValidatingPolicy` resources (policies.kyverno.io) vendored from + kyverno/policies' pod-security-vpol set. + 2. User-supplied `clusterSecurity.additionalKyvernoPolicies` — site-specific + policy objects platform admins want installed cluster-wide alongside the + bundle (either the new Policy types or the legacy ClusterPolicy). + +This template is policy-type-agnostic: it emits each document verbatim. The +bundled ValidatingPolicies use `validationActions: [Audit]` so violations are +logged but workloads aren't blocked. User-supplied policies use whatever +action they set. +*/ -}} +{{- $cs := include "session-manager.resolvedClusterSecurity" . | fromYaml -}} +{{- if eq $cs.policyEngine "Kyverno" -}} +{{- range $path, $_ := .Files.Glob "files/kyverno-policies/cluster-policies/*/*.yaml" }} +--- +{{ $.Files.Get $path | trim }} +{{- end }} +{{- range default list $cs.additionalKyvernoPolicies }} +--- +{{ toYaml . | trim }} +{{- end }} +{{- end -}} diff --git a/installer/charts/educates-training-platform/charts/session-manager/templates/secret-config.yaml b/installer/charts/educates-training-platform/charts/session-manager/templates/secret-config.yaml new file mode 100644 index 000000000..ab2f10707 --- /dev/null +++ b/installer/charts/educates-training-platform/charts/session-manager/templates/secret-config.yaml @@ -0,0 +1,15 @@ +apiVersion: v1 +kind: Secret +metadata: + name: educates-config + namespace: {{ .Release.Namespace }} + labels: + {{- include "session-manager.labels" . | nindent 4 }} +stringData: + educates-operator-config.yaml: | + {{- include "session-manager.operatorConfigYAML" . | nindent 4 }} + {{- $kyverno := include "session-manager.kyvernoPoliciesContent" . }} + {{- if $kyverno }} + kyverno-policies.yaml: | + {{- $kyverno | nindent 4 }} + {{- end }} diff --git a/installer/charts/educates-training-platform/charts/session-manager/templates/secret-website-theme.yaml b/installer/charts/educates-training-platform/charts/session-manager/templates/secret-website-theme.yaml new file mode 100644 index 000000000..18c39fea1 --- /dev/null +++ b/installer/charts/educates-training-platform/charts/session-manager/templates/secret-website-theme.yaml @@ -0,0 +1,12 @@ +apiVersion: v1 +kind: Secret +metadata: + name: default-website-theme + namespace: {{ .Release.Namespace }} + labels: + {{- include "session-manager.labels" . | nindent 4 }} +{{- $entries := include "session-manager.inlineThemeStringData" . | trim }} +{{- if and $entries (ne $entries "{}") }} +stringData: + {{- $entries | nindent 2 }} +{{- end }} diff --git a/installer/charts/educates-training-platform/charts/session-manager/templates/secretcopiers.yaml b/installer/charts/educates-training-platform/charts/session-manager/templates/secretcopiers.yaml new file mode 100644 index 000000000..a29f4091d --- /dev/null +++ b/installer/charts/educates-training-platform/charts/session-manager/templates/secretcopiers.yaml @@ -0,0 +1,148 @@ +{{- /* +SecretCopier resources distribute Secrets across namespaces. The +secrets.educates.dev CRDs are owned by the secrets-manager subchart, which is +a hard dependency of session-manager (see decisions.md). + +Four kinds of copy rules: + + 1. Ingress TLS + CA from external source namespaces into the release + namespace. Auto-derived from `clusterIngress.tlsCertificateRef.namespace` + and `clusterIngress.caCertificateRef.namespace` — if either points at a + namespace different from the release namespace, that Secret is copied in. + 2. Image-pull Secrets from external source namespaces into the release + namespace (`secretPropagation.upstream.imagePullSecrets`). + 3. Image-pull Secrets in the release namespace pushed downstream into + workshop-portal and workshop-environment namespaces (selected by label), + from `secretPropagation.imagePullSecretNames`. + 4. Website-theme Secrets from external source namespaces into the release + namespace, from `secretPropagation.upstream.websiteThemes` and from + `websiteStyling.themeDataRefs` whose namespace is set and external. + +Rules referencing a source namespace that equals the release namespace are +skipped (no copy needed). +*/ -}} +{{- $ns := .Release.Namespace -}} +{{- $ci := include "session-manager.resolvedClusterIngress" . | fromYaml -}} +{{- $tlsRef := default dict $ci.tlsCertificateRef -}} +{{- $caRef := default dict $ci.caCertificateRef -}} +{{- $tlsName := default "" $tlsRef.name -}} +{{- $tlsNs := default "" $tlsRef.namespace -}} +{{- $caName := default "" $caRef.name -}} +{{- $caNs := default "" $caRef.namespace -}} +{{- $tlsRule := and $tlsName $tlsNs (ne $tlsNs $ns) -}} +{{- $caRule := and $caName $caNs (ne $caNs $ns) -}} +{{- if or $tlsRule $caRule }} +apiVersion: secrets.educates.dev/v1beta1 +kind: SecretCopier +metadata: + name: educates-ingress-secrets + labels: + {{- include "session-manager.labels" . | nindent 4 }} +spec: + rules: + {{- if $tlsRule }} + - sourceSecret: + name: {{ $tlsName | quote }} + namespace: {{ $tlsNs | quote }} + targetNamespaces: + nameSelector: + matchNames: + - {{ $ns | quote }} + {{- end }} + {{- if $caRule }} + - sourceSecret: + name: {{ $caName | quote }} + namespace: {{ $caNs | quote }} + targetNamespaces: + nameSelector: + matchNames: + - {{ $ns | quote }} + {{- end }} +{{- end }} +{{- $sp := default dict .Values.secretPropagation -}} +{{- $upstream := default dict $sp.upstream -}} +{{- $upstreamPullSecrets := list -}} +{{- range default list $upstream.imagePullSecrets -}} + {{- if and .name .namespace (ne .namespace $ns) -}} + {{- $upstreamPullSecrets = append $upstreamPullSecrets . -}} + {{- end -}} +{{- end -}} +{{- if $upstreamPullSecrets }} +--- +apiVersion: secrets.educates.dev/v1beta1 +kind: SecretCopier +metadata: + name: educates-upstream-image-pull-secrets + labels: + {{- include "session-manager.labels" . | nindent 4 }} +spec: + rules: + {{- range $upstreamPullSecrets }} + - sourceSecret: + name: {{ .name | quote }} + namespace: {{ .namespace | quote }} + targetNamespaces: + nameSelector: + matchNames: + - {{ $ns | quote }} + {{- end }} +{{- end }} +{{- if default list $sp.imagePullSecretNames }} +--- +apiVersion: secrets.educates.dev/v1beta1 +kind: SecretCopier +metadata: + name: educates-downstream-image-pull-secrets + labels: + {{- include "session-manager.labels" . | nindent 4 }} +spec: + rules: + {{- range $sp.imagePullSecretNames }} + - sourceSecret: + name: {{ . | quote }} + namespace: {{ $ns | quote }} + targetNamespaces: + labelSelector: + matchLabels: + training.educates.dev/component: portal + - sourceSecret: + name: {{ . | quote }} + namespace: {{ $ns | quote }} + targetNamespaces: + labelSelector: + matchLabels: + training.educates.dev/component: environment + {{- end }} +{{- end }} +{{- $upstreamThemes := list -}} +{{- range default list $upstream.websiteThemes -}} + {{- if and .name .namespace (ne .namespace $ns) -}} + {{- $upstreamThemes = append $upstreamThemes . -}} + {{- end -}} +{{- end -}} +{{- $wstyle := default dict .Values.websiteStyling -}} +{{- range default list $wstyle.themeDataRefs -}} + {{- if and .name .namespace (ne .namespace $ns) -}} + {{- $upstreamThemes = append $upstreamThemes . -}} + {{- end -}} +{{- end -}} +{{- if $upstreamThemes }} +--- +apiVersion: secrets.educates.dev/v1beta1 +kind: SecretCopier +metadata: + name: educates-upstream-website-themes + labels: + {{- include "session-manager.labels" . | nindent 4 }} +spec: + rules: + {{- range $upstreamThemes }} + - sourceSecret: + name: {{ .name | quote }} + namespace: {{ .namespace | quote }} + targetNamespaces: + nameSelector: + matchNames: + - {{ $ns | quote }} + {{- end }} +{{- end }} diff --git a/installer/charts/educates-training-platform/charts/session-manager/templates/secretinjectors.yaml b/installer/charts/educates-training-platform/charts/session-manager/templates/secretinjectors.yaml new file mode 100644 index 000000000..c428c00b7 --- /dev/null +++ b/installer/charts/educates-training-platform/charts/session-manager/templates/secretinjectors.yaml @@ -0,0 +1,77 @@ +{{- if .Values.secretPropagation.imagePullSecretNames }} +apiVersion: secrets.educates.dev/v1beta1 +kind: SecretInjector +metadata: + name: educates-image-pull-secrets + labels: + {{- include "session-manager.labels" . | nindent 4 }} +spec: + rules: + - targetNamespaces: + labelSelector: + matchLabels: + training.educates.dev/component: portal + sourceSecrets: + nameSelector: + matchNames: + {{- range .Values.secretPropagation.imagePullSecretNames }} + - {{ . | quote }} + {{- end }} + serviceAccounts: + labelSelector: + matchLabels: + training.educates.dev/component: portal + - targetNamespaces: + labelSelector: + matchLabels: + training.educates.dev/component: environment + sourceSecrets: + nameSelector: + matchNames: + {{- range .Values.secretPropagation.imagePullSecretNames }} + - {{ . | quote }} + {{- end }} + serviceAccounts: + labelSelector: + matchLabels: + training.educates.dev/component: environment + - targetNamespaces: + labelSelector: + matchLabels: + training.educates.dev/component: environment + sourceSecrets: + nameSelector: + matchNames: + {{- range .Values.secretPropagation.imagePullSecretNames }} + - {{ . | quote }} + {{- end }} + serviceAccounts: + labelSelector: + matchLabels: + training.educates.dev/component: session +{{- end }} +--- +# `educates-registry-credentials` is a fixed Secret name that the runtime +# materialises per workshop session for in-session image-build use. The +# injector wires it into the default ServiceAccount of every session +# namespace. Always rendered — does nothing until the Secret exists. +apiVersion: secrets.educates.dev/v1beta1 +kind: SecretInjector +metadata: + name: educates-registry-credentials + labels: + {{- include "session-manager.labels" . | nindent 4 }} +spec: + rules: + - targetNamespaces: + labelSelector: + matchLabels: + training.educates.dev/component: session + sourceSecrets: + nameSelector: + matchNames: + - educates-registry-credentials + serviceAccounts: + nameSelector: + matchNames: + - default diff --git a/installer/charts/educates-training-platform/charts/session-manager/templates/serviceaccount.yaml b/installer/charts/educates-training-platform/charts/session-manager/templates/serviceaccount.yaml new file mode 100644 index 000000000..bc1572b82 --- /dev/null +++ b/installer/charts/educates-training-platform/charts/session-manager/templates/serviceaccount.yaml @@ -0,0 +1,32 @@ +apiVersion: v1 +kind: ServiceAccount +metadata: + name: session-manager + namespace: {{ .Release.Namespace }} + labels: + {{- include "session-manager.labels" . | nindent 4 }} +--- +# Long-lived service-account-token Secret. Manually created because +# Kubernetes 1.24+ no longer auto-generates these for ServiceAccounts. +# The session-manager Deployment disables automountServiceAccountToken +# and mounts this Secret at the standard token path. Behaviour +# preserved unchanged from v3. +apiVersion: v1 +kind: Secret +metadata: + name: session-manager-token + namespace: {{ .Release.Namespace }} + annotations: + kubernetes.io/service-account.name: session-manager + labels: + {{- include "session-manager.labels" . | nindent 4 }} +type: kubernetes.io/service-account-token +--- +apiVersion: v1 +kind: ServiceAccount +metadata: + name: image-puller + namespace: {{ .Release.Namespace }} + labels: + {{- include "session-manager.labels" . | nindent 4 }} + app.kubernetes.io/component: image-puller diff --git a/installer/charts/educates-training-platform/charts/session-manager/values.schema.json b/installer/charts/educates-training-platform/charts/session-manager/values.schema.json new file mode 100644 index 000000000..19b6b5c2d --- /dev/null +++ b/installer/charts/educates-training-platform/charts/session-manager/values.schema.json @@ -0,0 +1,376 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "Educates session-manager subchart values", + "type": "object", + "additionalProperties": false, + "required": ["workshopSecurity"], + "description": "Cross-cutting blocks (clusterIngress, clusterSecurity) may come from the umbrella's `.global` instead of being set here. The `development.imageRegistry` block also has a global counterpart (`.global.development.imageRegistry`). Subchart-local values pass through when globals are unset; globals win when both are set. Helpers enforce non-empty resolved values at template time.", + + "definitions": { + + "imageRef": { + "description": "Image reference. Empty `repository` falls through to the imageRegistry-derived default; empty `tag` falls through to Chart.AppVersion.", + "type": "object", + "additionalProperties": false, + "properties": { + "repository": { "type": "string" }, + "tag": { "type": "string" }, + "pullPolicy": { + "type": "string", + "enum": ["", "Always", "IfNotPresent", "Never"] + } + } + }, + + "secretRef": { + "description": "Reference to a Kubernetes Secret. Empty `name` means the ref is unset.", + "type": "object", + "additionalProperties": false, + "properties": { + "name": { "type": "string" }, + "namespace": { "type": "string" } + } + }, + + "kyvernoClusterPolicy": { + "description": "A Kyverno ClusterPolicy resource. Open shape; only top-level identity is validated.", + "type": "object", + "required": ["apiVersion", "kind", "metadata"], + "properties": { + "apiVersion": { "const": "kyverno.io/v1" }, + "kind": { "const": "ClusterPolicy" }, + "metadata": { + "type": "object", + "required": ["name"], + "properties": { + "name": { "type": "string", "minLength": 1 } + } + } + } + }, + + "trackingIdBlock": { + "type": "object", + "additionalProperties": false, + "properties": { + "trackingId": { "type": "string" } + } + }, + + "stylingTriple": { + "type": "object", + "additionalProperties": false, + "properties": { + "html": { "type": "string" }, + "script": { "type": "string" }, + "style": { "type": "string" } + } + }, + + "stylingHtmlOnly": { + "type": "object", + "additionalProperties": false, + "properties": { + "html": { "type": "string" } + } + } + }, + + "properties": { + + "clusterIngress": { + "type": "object", + "additionalProperties": false, + "properties": { + "domain": { + "type": "string", + "description": "Wildcard subdomain. Required after merging with .global.clusterIngress; helper fails at template time if the resolved value is empty." + }, + "class": { "type": "string" }, + "protocol": { + "type": "string", + "enum": ["", "http", "https"], + "description": "Empty for auto-derive from tlsCertificateRef." + }, + "tlsCertificateRef": { "$ref": "#/definitions/secretRef" }, + "caCertificateRef": { "$ref": "#/definitions/secretRef" } + } + }, + + "clusterSecurity": { + "type": "object", + "additionalProperties": false, + "properties": { + "policyEngine": { + "type": "string", + "enum": ["Kyverno", "PodSecurityStandards", "OpenShiftSCC", "None"] + }, + "additionalKyvernoPolicies": { + "type": "array", + "items": { "$ref": "#/definitions/kyvernoClusterPolicy" } + } + } + }, + + "workshopSecurity": { + "type": "object", + "additionalProperties": false, + "required": ["rulesEngine"], + "properties": { + "rulesEngine": { + "type": "string", + "enum": ["Kyverno", "None"] + }, + "additionalKyvernoPolicies": { + "type": "array", + "items": { "$ref": "#/definitions/kyvernoClusterPolicy" } + } + } + }, + + "development": { + "description": "Local-development overrides. Leave empty in normal use — Chart.yaml annotations (`educates.dev/image-registry-{host,namespace}`) provide the publish-time defaults for chart-rendered image refs, and the runtime falls back to `registry.default.svc.cluster.local` for `$(image_repository)` workshop-content placeholder resolution.", + "type": "object", + "additionalProperties": false, + "properties": { + "imageRegistry": { + "type": "object", + "additionalProperties": false, + "properties": { + "host": { "type": "string" }, + "namespace": { "type": "string" } + } + } + } + }, + + "imageVersions": { + "type": "array", + "items": { + "type": "object", + "additionalProperties": false, + "required": ["name", "image"], + "properties": { + "name": { "type": "string", "minLength": 1 }, + "image": { "type": "string", "minLength": 1 } + } + } + }, + + "image": { "$ref": "#/definitions/imageRef" }, + + "imagePullSecrets": { + "description": "Pod-spec imagePullSecrets attached to the session-manager pod itself. Standard Kubernetes [{name: ...}] shape.", + "type": "array", + "items": { + "type": "object", + "additionalProperties": false, + "required": ["name"], + "properties": { + "name": { "type": "string", "minLength": 1 } + } + } + }, + + "resources": { + "type": "object" + }, + + "clusterAdmin": { "type": "boolean" }, + + "trainingPortal": { + "type": "object", + "additionalProperties": false, + "properties": { + "credentials": { + "type": "object", + "additionalProperties": false, + "properties": { + "admin": { + "type": "object", + "additionalProperties": false, + "properties": { + "username": { "type": "string" }, + "password": { "type": "string" } + } + }, + "robot": { + "type": "object", + "additionalProperties": false, + "properties": { + "username": { "type": "string" }, + "password": { "type": "string" } + } + } + } + }, + "clients": { + "type": "object", + "additionalProperties": false, + "properties": { + "robot": { + "type": "object", + "additionalProperties": false, + "properties": { + "id": { "type": "string" }, + "secret": { "type": "string" } + } + } + } + } + } + }, + + "sessionCookies": { + "type": "object", + "additionalProperties": false, + "properties": { + "domain": { "type": "string" } + } + }, + + "clusterStorage": { + "type": "object", + "additionalProperties": false, + "properties": { + "class": { "type": "string" }, + "user": { "type": ["integer", "null"] }, + "group": { "type": "integer" } + } + }, + + "clusterRuntime": { + "type": "object", + "additionalProperties": false, + "properties": { + "class": { "type": "string" } + } + }, + + "clusterNetwork": { + "type": "object", + "additionalProperties": false, + "properties": { + "blockCIDRs": { + "type": "array", + "items": { "type": "string" } + } + } + }, + + "dockerDaemon": { + "type": "object", + "additionalProperties": false, + "properties": { + "networkMTU": { "type": "integer", "minimum": 0 }, + "proxyCache": { + "type": "object", + "additionalProperties": false, + "properties": { + "remoteURL": { "type": "string" }, + "username": { "type": "string" }, + "password": { "type": "string" } + } + } + } + }, + + "workshopAnalytics": { + "type": "object", + "additionalProperties": false, + "properties": { + "google": { "$ref": "#/definitions/trackingIdBlock" }, + "clarity": { "$ref": "#/definitions/trackingIdBlock" }, + "amplitude": { "$ref": "#/definitions/trackingIdBlock" }, + "webhook": { + "type": "object", + "additionalProperties": false, + "properties": { + "url": { "type": "string" } + } + } + } + }, + + "websiteStyling": { + "type": "object", + "additionalProperties": false, + "properties": { + "inline": { + "type": "object", + "additionalProperties": false, + "description": "Inline HTML/JS/CSS for the fallback default theme. Each populated leaf becomes a stringData entry in the `default-website-theme` Secret.", + "properties": { + "workshopDashboard": { "$ref": "#/definitions/stylingTriple" }, + "workshopInstructions": { "$ref": "#/definitions/stylingTriple" }, + "workshopStarted": { "$ref": "#/definitions/stylingHtmlOnly" }, + "workshopFinished": { "$ref": "#/definitions/stylingHtmlOnly" }, + "trainingPortal": { "$ref": "#/definitions/stylingTriple" } + } + }, + "defaultTheme": { "type": "string" }, + "themeDataRefs": { + "type": "array", + "items": { "$ref": "#/definitions/secretRef" } + }, + "frameAncestors": { + "type": "array", + "items": { "type": "string" } + } + } + }, + + "imagePrePuller": { + "type": "object", + "additionalProperties": false, + "properties": { + "enabled": { "type": "boolean" }, + "pauseImage": { "$ref": "#/definitions/imageRef" }, + "images": { + "type": "array", + "items": { "type": "string", "minLength": 1 } + } + } + }, + + "secretPropagation": { + "type": "object", + "additionalProperties": false, + "properties": { + "imagePullSecretNames": { + "type": "array", + "items": { "type": "string", "minLength": 1 } + }, + "upstream": { + "type": "object", + "additionalProperties": false, + "properties": { + "imagePullSecrets": { + "type": "array", + "items": { "$ref": "#/definitions/secretRef" } + }, + "websiteThemes": { + "type": "array", + "items": { "$ref": "#/definitions/secretRef" } + } + } + } + } + }, + + "config": { + "type": "object", + "description": "Opaque escape hatch deep-merged on top of typed-derived runtime config." + }, + + "enabled": { + "type": "boolean", + "description": "Subchart enable toggle injected by the umbrella chart's dependency mechanism." + }, + + "global": { + "type": "object", + "description": "Helm-injected globals from the umbrella chart." + } + } + } diff --git a/installer/charts/educates-training-platform/charts/session-manager/values.yaml b/installer/charts/educates-training-platform/charts/session-manager/values.yaml new file mode 100644 index 000000000..fc9c0eda1 --- /dev/null +++ b/installer/charts/educates-training-platform/charts/session-manager/values.yaml @@ -0,0 +1,363 @@ +# Values for the session-manager subchart. +# +# In a v4 install, the operator derives these values from the SessionManager CR +# plus EducatesClusterConfig.status. They can also be set directly when +# installing the chart standalone. + +# ============================================================================= +# Cluster-wide ingress identity +# ============================================================================= + +# `domain` is required. Chart fails at template time if empty. +# `protocol` is auto-derived from tlsCertificateRef when empty: "http" if no +# ref is set, "https" otherwise. Override only for external TLS termination +# (router terminates TLS and proxies plain HTTP into the cluster). +clusterIngress: + domain: "" + class: "" + protocol: "" + + # Reference to a kubernetes.io/tls Secret holding the wildcard cert for + # *.. Required keys: tls.crt, tls.key. When `namespace` is empty + # the Secret is assumed to live in the release namespace. When set to a + # different namespace, the chart auto-creates a SecretCopier so the runtime + # finds the Secret locally. + tlsCertificateRef: + name: "" + namespace: "" + + # Reference to a Secret holding the CA certificate used to verify the + # wildcard. Required key: ca.crt. Same namespace semantics as the TLS ref. + caCertificateRef: + name: "" + namespace: "" + +# ============================================================================= +# Security policy enforcement +# ============================================================================= + +# Cluster-level security policy enforcement. +# +# - Kyverno: installs the bundled cluster ClusterPolicies (PSS baseline + +# restricted profiles + operational best-practices) directly to the cluster. +# `additionalKyvernoPolicies` are installed alongside. +# - OpenShiftSCC: installs ClusterRoleBindings binding the session-manager and +# image-puller ServiceAccounts to the `educates-baseline-scc` ClusterRole. +# Implies you're on OpenShift; SCC enforcement comes from the platform. +# - PodSecurityStandards: chart installs nothing at this level; PSS is enforced +# by Kubernetes via namespace labels managed by the runtime. +# - None: no cluster-level policy enforcement. User accepts responsibility. +# +# `additionalKyvernoPolicies` is silently ignored when policyEngine is not +# Kyverno. +clusterSecurity: + policyEngine: Kyverno # Kyverno | PodSecurityStandards | OpenShiftSCC | None + additionalKyvernoPolicies: [] + # - apiVersion: kyverno.io/v1 + # kind: ClusterPolicy + # metadata: + # name: my-cluster-wide-extra + # spec: + # validationFailureAction: Audit + # rules: + # - name: ... + +# Per-workshop policy enforcement. The chart concatenates a curated bundle +# (operational best-practices + Educates-internal `require-ingress-session-name`) +# into the `kyverno-policies.yaml` key of the `educates-config` Secret; +# session-manager clones each rule per workshop environment with a namespace +# selector added. +# +# `additionalKyvernoPolicies` is appended to the same feed and is silently +# ignored when rulesEngine is not Kyverno. +workshopSecurity: + rulesEngine: Kyverno # Kyverno | None + additionalKyvernoPolicies: [] + # - apiVersion: kyverno.io/v1 + # kind: ClusterPolicy + # metadata: + # name: my-per-workshop-extra + # spec: + # rules: + # - name: ... + +# ============================================================================= +# Development overrides +# ============================================================================= +# +# These knobs target the local-development workflow only. In NORMAL USE +# leave the entire `development:` block empty: +# +# - Chart-rendered + runtime-spawned Educates image refs (chart pod, +# pause container, training-portal, base-environment, etc.) are +# composed from Chart.yaml annotations +# (`educates.dev/image-registry-host` / `-namespace`), which the chart's +# publish workflow updates per fork at release time. +# - The runtime config blob's `imageRegistry` field is emitted EMPTY, +# so the runtime falls back to `registry.default.svc.cluster.local` +# when resolving `$(image_repository)` workshop-content placeholders. +# Released workshops have fully-qualified refs in their YAMLs anyway, +# so this fallback is irrelevant outside the dev workflow. +# +# When set, `development.imageRegistry` has TWO simultaneous effects: +# +# 1. Replaces the Chart.yaml annotation defaults. Chart pod, pause +# image, and the Educates-published entries in the `imageVersions` +# helper resolve against `{host}/{namespace}` instead. +# 2. Emits the same `{host}/{namespace}` into the runtime config so +# workshop sessions get `IMAGE_REPOSITORY={host}/{namespace}`. +# Workshops authored against `$(image_repository)/` placeholders +# then resolve there — the typical local-dev flow where you +# `educates publish-workshop` to localhost:5001 and want session- +# spawned workshops to pull from the same place. +# +# Mirrors v3's `imageRegistry` schema knob, which the v3 schema comment +# explicitly described as "for development, experimentation and when +# working on workshop content in a local Educates environment, and should +# not be overridden through a values file in normal use." +development: + imageRegistry: + host: "" + namespace: "" + +# Per-image overrides, merged BY NAME on top of the chart-shipped default +# `imageVersions` list. The default list is built in +# `templates/_helpers.tpl` (`session-manager.imageVersions`) and mirrors +# v3's carvel-installer `images.yaml`: +# - Educates-published images, tag = `Chart.AppVersion`. +# - Upstream pins (docker-in-docker, loftsh-*, debian-base), specific tags. +# An override matching a default by `name` replaces just that entry; other +# defaults pass through. Names not in the default list are appended. +# Use for airgap relocation, JDK/k8s variant pinning, or to mirror images +# under a different registry without forking the helper. +imageVersions: [] + # - name: base-environment + # image: my-registry.example.com/educates/base-environment@sha256:... + +# ============================================================================= +# Session-manager pod +# ============================================================================= + +image: + # Empty `repository` derives `{imageRegistry.host}/{imageRegistry.namespace}/educates-session-manager`. + # Override only when the chart-pod image is hosted somewhere different from + # the rest of the runtime (e.g., a single fork registry exposes everything + # via imageRegistry, but the session-manager image happens to live at a + # custom path). + repository: "" + # Empty tag falls through to `Chart.AppVersion` (the bundled Educates + # runtime version). Override only when pinning a specific runtime + # build, e.g., a development image. + tag: "" + pullPolicy: "" + +# Image-pull Secrets attached to the session-manager pod's own PodSpec. These +# are the Secrets needed to pull the session-manager image itself. For Secrets +# that should propagate into workshop namespaces, see `secretPropagation` below. +imagePullSecrets: [] + +resources: {} + +# Grant the session-manager ServiceAccount the built-in `cluster-admin` +# ClusterRole. Off by default; enable only when workshops need to manage +# cluster-scoped resources beyond what the aggregated `educates-session-manager` +# ClusterRole grants. Note: changed from v3 default of `true`. +clusterAdmin: false + +# ============================================================================= +# Training portal defaults +# ============================================================================= + +# Empty values cause the runtime to generate them on first reconciliation. +# The chart deliberately does NOT use `randAlphaNum` defaults here because that +# would rotate values on every `helm upgrade` and break in-flight workshops. +trainingPortal: + credentials: + admin: + username: "" + password: "" + robot: + username: "" + password: "" + clients: + robot: + id: "" + secret: "" + +# Optional override for the cookie domain used by training portal and +# workshop sessions. Empty means "use the ingress domain." +sessionCookies: + domain: "" + +# ============================================================================= +# Storage +# ============================================================================= + +# `class` empty uses the cluster default StorageClass. +# `user` is null by default (filesystem chown unset). Set to a numeric UID +# only when the storage class maps to NFS and the server requires a specific +# user. Cannot be combined with PodSecurityStandards/Policies enforcement. +# `group` defaults to 1, suitable for clusters with pod security policies. +clusterStorage: + class: "" + user: null + group: 1 + +# ============================================================================= +# Container runtime +# ============================================================================= + +# Optional runtimeClass applied to workshop containers (e.g., "kata" for +# VM-isolated workshops). Empty leaves the cluster default. +clusterRuntime: + class: "" + +# ============================================================================= +# Cluster network policy +# ============================================================================= + +# CIDRs that workshops are blocked from reaching. Default blocks the AWS EC2 +# instance metadata endpoint (IPv4 and IPv6). Set to [] to remove all blocks. +clusterNetwork: + blockCIDRs: + - "169.254.169.254/32" + - "fd00:ec2::254/128" + +# ============================================================================= +# Docker daemon (only used when workshops build images) +# ============================================================================= + +dockerDaemon: + networkMTU: 1400 + # Mirror cache to mitigate Docker Hub pull limits. Set remoteURL to e.g. + # "https://registry-1.docker.io" to enable. + proxyCache: + remoteURL: "" + username: "" + password: "" + +# ============================================================================= +# Analytics +# ============================================================================= + +workshopAnalytics: + google: + trackingId: "" + clarity: + trackingId: "" + amplitude: + trackingId: "" + webhook: + url: "" + +# ============================================================================= +# Website styling and theming +# ============================================================================= + +# Two ways to supply themes: +# +# `inline` — HTML/JS/CSS authored directly in values. Each populated leaf +# becomes a stringData entry in the `default-website-theme` Secret, which +# the runtime uses as the fallback theme. Convenient for small tweaks +# without managing a separate Secret. +# +# `themeDataRefs` — references to external theme Secrets that already hold +# the assets. The chart makes them available to the runtime and auto- +# creates a SecretCopier when a ref's namespace differs from the release +# namespace. +websiteStyling: + inline: + workshopDashboard: + html: "" + script: "" + style: "" + workshopInstructions: + html: "" + script: "" + style: "" + workshopStarted: + html: "" + workshopFinished: + html: "" + trainingPortal: + html: "" + script: "" + style: "" + + # Name of the theme to use as default. Must match a key in `themeDataRefs`. + # Empty means "use the inline default theme (above)." + defaultTheme: "" + + # External theme Secrets to make available. Each ref points at a Secret + # holding theme assets. When `namespace` differs from the release namespace + # the chart auto-creates a SecretCopier. + themeDataRefs: [] + # - name: my-theme + # namespace: themes-source + + # Allowed parent frames for embedding workshop sessions (CSP + # frame-ancestors directive). + frameAncestors: [] + +# ============================================================================= +# Image pre-puller DaemonSet +# ============================================================================= + +# When enabled, runs an init-container per image in `images` (each running +# `/bin/true`) so the kubelet pre-pulls and caches them on every node ahead of +# time, plus a long-lived pause container to keep the DS alive. Useful for +# clusters where workshop session start time is dominated by image pull. +imagePrePuller: + enabled: false + # Pause image used as the long-lived "keepalive" container in the DaemonSet. + # Empty `repository` derives `{imageRegistry.host}/{imageRegistry.namespace}/educates-pause-container`. + # Empty `tag` falls through to `Chart.AppVersion`. + pauseImage: + repository: "" + tag: "" + pullPolicy: "" + # Full image references to pre-pull. Empty defaults to the v3-equivalent + # set -- training-portal + base-environment -- resolved through the + # imageVersions inventory, so registry relocation and per-name overrides + # are honoured. A non-empty list replaces the default verbatim (fully + # qualified refs only; short names are not resolved here). + images: [] + # - ghcr.io/educates/training-portal:4.0.0-alpha.1 + +# ============================================================================= +# Secret propagation +# ============================================================================= +# +# The session-manager runtime distributes pull secrets and website themes +# across workshop namespaces using SecretCopier and SecretInjector resources +# from secrets.educates.dev. +# +# Note: ingress TLS and CA propagation is auto-derived from +# `clusterIngress.tlsCertificateRef` and `clusterIngress.caCertificateRef` +# when those refs target a namespace other than the release namespace. There +# is no longer an explicit knob for it. + +secretPropagation: + # Names of image-pull Secrets that already exist in the release namespace + # and should be (a) propagated into every workshop-portal and + # workshop-environment namespace, and (b) injected into ServiceAccounts + # in those namespaces. + imagePullSecretNames: [] + # - my-registry-pull-secret + + upstream: + # External Secrets to copy INTO the release namespace before propagation. + imagePullSecrets: [] + # - { name: my-pull-secret, namespace: source-ns } + websiteThemes: [] + # - { name: my-theme, namespace: source-ns } + +# ============================================================================= +# Escape hatch +# ============================================================================= +# +# Opaque map deep-merged on top of the typed-values-derived +# `educates-operator-config.yaml` Secret content. Use only for runtime fields +# not yet promoted to typed values. Newly added fields should land here first +# and be promoted in a subsequent chart release. +config: {} diff --git a/carvel-packages/installer/bundle/.imgpkg/.gitkeep b/installer/charts/educates-training-platform/templates/.gitkeep similarity index 100% rename from carvel-packages/installer/bundle/.imgpkg/.gitkeep rename to installer/charts/educates-training-platform/templates/.gitkeep diff --git a/installer/charts/educates-training-platform/tests/.env.example b/installer/charts/educates-training-platform/tests/.env.example new file mode 100644 index 000000000..7dc5ccbef --- /dev/null +++ b/installer/charts/educates-training-platform/tests/.env.example @@ -0,0 +1,26 @@ +# Sample .env file for the test runner. +# +# Copy to `.env` (in this same directory) and edit to your environment. +# `.env` is gitignored. Anything you set here is exported into the +# runner's environment as a default; explicit `--flag` arguments and +# pre-set shell env vars override these. +# +# Bash sources this file directly, so: +# - `$HOME` and `~` are expanded. +# - Paths containing spaces must be quoted: `KEY="$HOME/With Spaces"`. +# - Comments start with `#`. + +# Wildcard ingress domain. The runner falls back to ".nip.io" +# from your first non-loopback IPv4 if unset. +# DOMAIN=educates.test + +# Pre-existing leaf cert + key for *.${DOMAIN}. Used as-is when present. +# TLS_CERT_PATH=/path/to/wildcard.crt +# TLS_KEY_PATH=/path/to/wildcard.key + +# Trusted CA cert + key. With both, scenario 02 signs a fresh wildcard +# leaf with this CA so browsers don't warn. The runner auto-detects the +# mkcert sibling key (rootCA.pem ↔ rootCA-key.pem) when CA_KEY_PATH is +# left unset. +# CA_CERT_PATH="$HOME/Library/Application Support/mkcert/rootCA.pem" +# CA_KEY_PATH="$HOME/Library/Application Support/mkcert/rootCA-key.pem" diff --git a/installer/charts/educates-training-platform/tests/.gitignore b/installer/charts/educates-training-platform/tests/.gitignore new file mode 100644 index 000000000..4c49bd78f --- /dev/null +++ b/installer/charts/educates-training-platform/tests/.gitignore @@ -0,0 +1 @@ +.env diff --git a/installer/charts/educates-training-platform/tests/README.md b/installer/charts/educates-training-platform/tests/README.md new file mode 100644 index 000000000..7e5bb03c3 --- /dev/null +++ b/installer/charts/educates-training-platform/tests/README.md @@ -0,0 +1,130 @@ +# Pre-phase chart validation scenarios + +End-to-end tests for the `educates-training-platform` Helm chart against +real kind clusters. Each scenario provisions the cluster (using the v3 +`educates` CLI to install Kubernetes prerequisites without the v3 +Educates package), then installs the v4 chart, deploys a sample +workshop, and verifies the runtime is functional. + +These tests prove the chart can replace the v3 carvel-based installer +for the runtime, which is the "Done when" criterion for the pre-phase +in `docs/architecture/educates-v4-development-plan.md`. + +## Layout + +``` +tests/ +├── README.md # This file (scenario index) +├── run-scenario.sh # Test runner (scenario name as $1) +└── scenarios/ + └── / + ├── description.md + ├── educates-config.yaml # consumed by `educates local cluster create --config` + ├── chart-values.yaml # consumed by `helm install -f` + ├── pre-install.sh # optional hook: after cluster create, before helm install + ├── post-install.sh # optional hook: after helm install + readiness, before portal create + ├── post-deploy.sh # optional hook: after workshop deploy, with PORTAL_URL exported + └── teardown.sh # optional hook: always runs in cleanup trap, before cluster delete +``` + +Hook scripts are executed when present and executable. A non-zero +exit from `pre-install.sh`, `post-install.sh`, or `post-deploy.sh` +fails the scenario. `teardown.sh` runs unconditionally and any error +it returns is logged but ignored. + +- **`pre-install.sh`** — stage external dependencies (Secrets in + foreign namespaces, generated certs, pre-staged registries). +- **`post-install.sh`** — assertions on what the chart rendered + (grep a Secret for a marker, wait for a SecretCopier to take + effect, etc.). Runs with `kubectl` already pointing at the + cluster, before any portal/workshop is created. +- **`post-deploy.sh`** — end-to-end runtime assertions. + `PORTAL_URL` is exported (resolved from + `trainingportal/educates-cli`'s `status.educates.url`) so the + hook can `curl` the live portal and validate that chart-driven + config actually reached the runtime. +- **`teardown.sh`** — clean up out-of-cluster resources created by + `pre-install.sh` (docker containers, tmp dirs). Runs always — + on success, on failure, on `--keep`. Should be idempotent. + +## Running a scenario + +```sh +./run-scenario.sh 01-local-http-nip-io +``` + +The runner prints status at each step. After deploying the workshop it +pauses with the portal URL and credentials, so you can browse and +exercise it. Press Enter (or send `--no-wait`) to proceed to the +teardown step. + +Pass `--keep` to skip the cluster-delete step (handy when iterating on +a fix). + +### Reusing settings via `.env` + +The runner sources `tests/.env` (gitignored) before reading flags. +Copy `tests/.env.example` to `tests/.env` and put your usual +`DOMAIN`, `CA_CERT_PATH`, etc. in it once — subsequent runs no longer +need the flags. Explicit flags and pre-set shell env vars still +override the file. + +### Domain and TLS material + +Scenarios are templated with `envsubst`; `${DOMAIN}` is the only +placeholder used today. The runner resolves it as follows: + +- `--domain ` flag (or `DOMAIN` env var) wins. +- Otherwise, the first non-loopback IPv4 of `en0`–`en4` is used to + build `.nip.io`, matching the educates CLI's + `GetHostIpAsDns()` default. Fails fast if no usable interface is + found — pass `--domain` explicitly when on a CI runner or VM. + +For TLS scenarios, you can pass trusted material so browsers don't +warn: + +- `--tls-cert ` and `--tls-key ` — a wildcard leaf cert and + its private key, valid for `*.`. +- `--ca-cert ` — a CA cert. When supplied alongside `--ca-key`, + the scenario signs a fresh wildcard leaf with it; when supplied + alongside `--tls-cert/--tls-key`, it's just published as the + `wildcard-ca` Secret so the runtime trusts the chain. +- `--ca-key ` — CA private key paired with `--ca-cert`. The + runner auto-detects the mkcert sibling (`rootCA.pem` ↔ + `rootCA-key.pem`) when `--ca-key` is omitted. + +If you already have a trusted CA set up via mkcert (per the +[educates docs](https://docs.educates.dev/en/stable/getting-started/local-environment.html#custom-ingress-domain)) +the simplest invocation is: + +```sh +./run-scenario.sh 02-kind-tls-wildcard \ + --ca-cert "$(mkcert -CAROOT)/rootCA.pem" +``` + +The runner picks up the matching `rootCA-key.pem` automatically and +the scenario signs a fresh wildcard leaf for the resolved `${DOMAIN}`. + +When all of `--tls-cert/--tls-key/--ca-cert/--ca-key` are omitted, the +scenario's `pre-install.sh` falls back to generating a self-signed CA ++ wildcard cert at runtime — browsers will warn. + +## Scenarios + +| ID | Description | TLS | Notes | +|---|---|---|---| +| `01-local-http-nip-io` | Local kind, HTTP, nip.io domain, no TLS, no CA, no lookup-service. | No | Smallest viable install. Exercises the chart's "everything optional is off" path. | +| `02-kind-tls-wildcard` | Local kind with Contour + Kyverno, offline-generated wildcard TLS Secret + CA copied via SecretCopier, HTTPS ingress. | Yes | Exercises the chart's TLS values shape and `secretPropagation.upstream.*`. cert-manager is not used for issuance. | +| `03-kind-cert-manager-issuer` | Local kind with cert-manager + certs + Contour + Kyverno; wildcard cert is *issued* by cert-manager from a user-provided CA. | Yes | Closest to the v4 operator's `Managed`-mode `BundledCertManager + CustomCA` shape. Pre-install hook stages the CA Secret in the layout cert-manager's `ca:` issuer expects. | +| `04-website-theme` | HTTP base + custom `session-manager.websiteTheme` value. | No | Asserts that the chart serialises the theme map into the `default-website-theme` Secret. | +| `05-image-pull-secrets` | HTTP base + session-manager pulls its image through an htpasswd-protected local registry. | No | Stands up an auth'd `registry:2` container, mirrors `educates-session-manager:3.7.1` into it, configures kind containerd, and stages the pull secret. `kubectl rollout status deployment/session-manager` is the real test — fails if any link in the chart's pull-secret chain breaks. `teardown.sh` removes the registry container. | +| `06-additional-kyverno-policies` | HTTP base + default-bundled v3 Kyverno policies + a user-supplied marker ClusterPolicy. | No | After workshop deploy, asserts `clusterpolicy/educates-environment-*` contains rules from the bundled baseline + operational set and from the user-supplied bucket. | +| `07-config-escape-hatch` | HTTP base + `session-manager.config` opaque overrides. | No | Asserts the escape hatch deep-merges on top of typed-derived values (`dockerDaemon.networkMTU` override wins) and passes unknown fields through (`experimental.markerKey`). | +| `08-node-ca-injector-image-pull` | TLS base + node-ca-injector; workshop user builds → pushes → deploys through the per-session registry. | Yes | The closing `kubectl rollout status` passes only if containerd on the kind node trusts the wildcard CA that fronts the registry — proving node-ca-injector wrote `/etc/containerd/certs.d/`. | +| `09-kind-all-options` | Kitchen sink: every subchart on (incl. lookup-service + remote-access) and every session-manager value block populated. | Yes | Asserts the full typed-values surface lands in the `educates-config` blob, all SecretCopier paths (TLS/CA, themes, pull secret), the optional subchart rollouts, and the external `defaultTheme` served by the portal. | + +## Adding a scenario + +Pick the next free ID (e.g. `03-...`), create a folder under `scenarios/` +with the three files (`description.md`, `educates-config.yaml`, +`chart-values.yaml`), and append a row to the table above. diff --git a/installer/charts/educates-training-platform/tests/run-scenario.sh b/installer/charts/educates-training-platform/tests/run-scenario.sh new file mode 100755 index 000000000..d5de04f30 --- /dev/null +++ b/installer/charts/educates-training-platform/tests/run-scenario.sh @@ -0,0 +1,351 @@ +#!/usr/bin/env bash +# End-to-end runner for an educates-training-platform chart scenario. +# +# Steps: +# 1a. educates local cluster create --cluster-only --config +# (kind cluster only, no platform install) +# 1b. (optional) /pre-install.sh — stage cluster-side fixtures +# (e.g., create TLS / CA Secrets in foreign namespaces) before the +# v3 installer runs. +# 1c. educates admin platform deploy --config +# (installs cluster prerequisites; v3 Educates package is disabled) +# 2. helm install ... -f (installs v4 runtime) +# 3. educates cluster portal create +# 4. educates deploy-workshop: +# - If /workshop/resources/workshop.yaml exists, the +# scenario-local workshop is published to localhost:5001 (the local +# registry that `educates local cluster create` stood up) and +# deployed from that path. +# - Otherwise the default WORKSHOP_URL is deployed. +# 5. Pause for manual / Playwright verification (URL printed) +# 6. educates local cluster delete +# +# Usage: +# ./run-scenario.sh [--keep] [--no-wait] \ +# [--domain ] \ +# [--tls-cert --tls-key ] \ +# [--ca-cert ] +# +# --keep Skip the cluster-delete step (keep cluster around for inspection). +# --no-wait Skip the interactive pause before teardown. +# --domain Wildcard ingress domain. Defaults to ".nip.io" +# using the first non-loopback IPv4 interface, matching the +# educates CLI's GetHostIpAsDns(). +# --tls-cert Path to PEM-encoded TLS leaf cert. Used by scenario +# pre-install hooks that need a wildcard cert; falls back +# to a self-signed cert generated at runtime when omitted. +# --tls-key Path to PEM-encoded TLS private key. Required when +# --tls-cert is set. +# --ca-cert Path to PEM-encoded CA cert that signed --tls-cert. When +# provided, scenarios use it instead of a self-signed CA; +# browsers that trust this CA will not warn. +# +# Templating: +# Scenario files (educates-config.yaml, chart-values.yaml, pre-install.sh) +# are passed through `envsubst` before use. Any `${DOMAIN}` token is +# substituted with the resolved domain. Other tokens +# (TLS_CERT_PATH, TLS_KEY_PATH, CA_CERT_PATH) are exported for use by +# pre-install.sh. + +set -Eeuo pipefail + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +CHART_DIR="$(cd "${SCRIPT_DIR}/.." && pwd)" + +# Load tests/.env first so its values become defaults that flags and any +# pre-set shell env vars can override. Each line is `KEY=VALUE` (with +# optional surrounding quotes); blank lines and `#` comments are +# ignored. Env vars already set in the calling shell are not overwritten +# — flags > shell env > .env > built-in defaults. +load_env_file() { + local f="$1" + [[ -f "$f" ]] || return 0 + echo "[runner] loading env file: $f" + + # Snapshot any vars listed in the file that are already set in the + # environment, so shell-set values win over .env-set values. Bash + # itself sources the file (handles $HOME, ~, quoted paths with + # spaces, etc.). + declare -A _preset=() + while IFS= read -r line || [[ -n "$line" ]]; do + [[ "$line" =~ ^[[:space:]]*# || -z "${line// }" ]] && continue + [[ "$line" =~ ^[[:space:]]*([A-Za-z_][A-Za-z0-9_]*)= ]] || continue + local k="${BASH_REMATCH[1]}" + if [[ -n "${!k:-}" ]]; then + _preset[$k]="${!k}" + fi + done < "$f" + + set -a + # shellcheck disable=SC1090 + source "$f" + set +a + + local k + for k in "${!_preset[@]}"; do + export "$k"="${_preset[$k]}" + done +} + +load_env_file "${SCRIPT_DIR}/.env" + +SCENARIO="" +KEEP=0 +NO_WAIT=0 +DOMAIN="${DOMAIN:-}" +TLS_CERT_PATH="${TLS_CERT_PATH:-}" +TLS_KEY_PATH="${TLS_KEY_PATH:-}" +CA_CERT_PATH="${CA_CERT_PATH:-}" +CA_KEY_PATH="${CA_KEY_PATH:-}" +WORKSHOP_URL="https://github.com/educates/lab-k8s-fundamentals/releases/download/8.4/workshop.yaml" + +while (( $# )); do + case "$1" in + --keep) KEEP=1 ;; + --no-wait) NO_WAIT=1 ;; + --domain) DOMAIN="$2"; shift ;; + --tls-cert) TLS_CERT_PATH="$2"; shift ;; + --tls-key) TLS_KEY_PATH="$2"; shift ;; + --ca-cert) CA_CERT_PATH="$2"; shift ;; + --ca-key) CA_KEY_PATH="$2"; shift ;; + -h|--help) + sed -n '2,/^set -Eeuo/p' "$0" | sed 's/^# \{0,1\}//' | head -n -1 + exit 0 + ;; + -*) + echo "unknown flag: $1" >&2; exit 2 ;; + *) + [[ -n "$SCENARIO" ]] && { echo "only one scenario id allowed" >&2; exit 2; } + SCENARIO="$1" + ;; + esac + shift +done + +if [[ -z "$SCENARIO" ]]; then + echo "usage: $0 [flags…]" >&2 + echo "available scenarios:" >&2 + ls "${SCRIPT_DIR}/scenarios" >&2 + exit 2 +fi + +SCEN_DIR="${SCRIPT_DIR}/scenarios/${SCENARIO}" +SRC_EDUCATES_CONFIG="${SCEN_DIR}/educates-config.yaml" +SRC_CHART_VALUES="${SCEN_DIR}/chart-values.yaml" + +if [[ ! -d "$SCEN_DIR" ]]; then + echo "scenario '$SCENARIO' not found at $SCEN_DIR" >&2 + exit 2 +fi +for f in "$SRC_EDUCATES_CONFIG" "$SRC_CHART_VALUES"; do + [[ -f "$f" ]] || { echo "missing: $f" >&2; exit 2; } +done + +# Cert-flag consistency. +if [[ -n "$TLS_CERT_PATH" || -n "$TLS_KEY_PATH" ]]; then + if [[ -z "$TLS_CERT_PATH" || -z "$TLS_KEY_PATH" ]]; then + echo "--tls-cert and --tls-key must be provided together" >&2; exit 2 + fi + [[ -f "$TLS_CERT_PATH" ]] || { echo "--tls-cert: file not found: $TLS_CERT_PATH" >&2; exit 2; } + [[ -f "$TLS_KEY_PATH" ]] || { echo "--tls-key: file not found: $TLS_KEY_PATH" >&2; exit 2; } +fi +if [[ -n "$CA_CERT_PATH" ]]; then + [[ -f "$CA_CERT_PATH" ]] || { echo "--ca-cert: file not found: $CA_CERT_PATH" >&2; exit 2; } + # Auto-derive the CA private key from the mkcert sibling convention + # (rootCA.pem ↔ rootCA-key.pem) when --ca-key wasn't passed explicitly. + if [[ -z "$CA_KEY_PATH" ]]; then + CANDIDATE="${CA_CERT_PATH%.pem}-key.pem" + if [[ -f "$CANDIDATE" ]]; then + CA_KEY_PATH="$CANDIDATE" + echo "[runner] auto-detected CA key (mkcert convention): $CA_KEY_PATH" + fi + fi +fi +if [[ -n "$CA_KEY_PATH" ]]; then + [[ -f "$CA_KEY_PATH" ]] || { echo "--ca-key: file not found: $CA_KEY_PATH" >&2; exit 2; } + [[ -n "$CA_CERT_PATH" ]] || { echo "--ca-key requires --ca-cert" >&2; exit 2; } +fi + +step() { printf '\n\033[1;36m== %s ==\033[0m\n' "$*"; } +ok() { printf '\033[1;32m[ok]\033[0m %s\n' "$*"; } +warn() { printf '\033[1;33m[warn]\033[0m %s\n' "$*" >&2; } +fail() { printf '\033[1;31m[fail]\033[0m %s\n' "$*" >&2; } + +# Resolve domain default if not provided. +if [[ -z "$DOMAIN" ]]; then + HOST_IP="" + for iface in en0 en1 en2 en3 en4; do + HOST_IP="$(ipconfig getifaddr "$iface" 2>/dev/null || true)" + [[ -n "$HOST_IP" ]] && break + done + if [[ -z "$HOST_IP" ]] && command -v hostname >/dev/null 2>&1; then + HOST_IP="$(hostname -I 2>/dev/null | awk '{print $1}' || true)" + fi + if [[ -z "$HOST_IP" || "$HOST_IP" == "127.0.0.1" ]]; then + fail "could not detect a non-loopback host IP. Pass --domain explicitly." + exit 2 + fi + DOMAIN="${HOST_IP}.nip.io" + echo "[runner] auto-detected domain: ${DOMAIN}" +fi + +export DOMAIN TLS_CERT_PATH TLS_KEY_PATH CA_CERT_PATH CA_KEY_PATH + +# Render templated scenario files into a tmp dir; envsubst replaces +# ${DOMAIN} (and any other exported $VARs the templates use). +RENDER_DIR="$(mktemp -d -t educates-scenario-render-XXXX)" +envsubst < "$SRC_EDUCATES_CONFIG" > "${RENDER_DIR}/educates-config.yaml" +envsubst < "$SRC_CHART_VALUES" > "${RENDER_DIR}/chart-values.yaml" +EDUCATES_CONFIG="${RENDER_DIR}/educates-config.yaml" +CHART_VALUES="${RENDER_DIR}/chart-values.yaml" + +# Always attempt to clean up the cluster on early exit unless --keep. +# Scenario `teardown.sh` (if present) runs first so it can drop docker +# containers / tmp dirs created by `pre-install.sh`, regardless of +# whether the scenario passed or failed. +cleanup() { + local rc=$? + if [[ -x "${SCEN_DIR:-}/teardown.sh" ]]; then + echo "[runner] scenario teardown" >&2 + "${SCEN_DIR}/teardown.sh" || true + fi + if [[ $rc -ne 0 && $KEEP -eq 0 ]]; then + warn "scenario failed (rc=$rc); deleting cluster" + educates local cluster delete >/dev/null 2>&1 || true + fi + return $rc +} +trap cleanup EXIT + +step "Scenario: ${SCENARIO}" +echo " domain: ${DOMAIN}" +echo " tls-cert: ${TLS_CERT_PATH:-(self-signed at runtime)}" +echo " tls-key: ${TLS_KEY_PATH:-}" +echo " ca-cert: ${CA_CERT_PATH:-(self-signed at runtime)}" +echo " ca-key: ${CA_KEY_PATH:-}" +echo " rendered: ${RENDER_DIR}" +echo +cat "${SCEN_DIR}/description.md" 2>/dev/null | sed 's/^/ /' || true + +step "1a/6 Create kind cluster (no platform install yet)" +educates local cluster create --cluster-only --config "$EDUCATES_CONFIG" +ok "cluster up" + +if [[ -x "${SCEN_DIR}/pre-install.sh" ]]; then + step "1b/6 Run scenario pre-install hook" + "${SCEN_DIR}/pre-install.sh" + ok "pre-install done" +fi + +step "1c/6 Install v3 prereqs (educates admin platform deploy)" +educates admin platform deploy --config "$EDUCATES_CONFIG" +ok "platform prereqs deployed" + +step "2/6 Install v4 runtime chart" +# No --wait here. The post-install hook may need to stage things in +# the operator namespace (e.g., a pull secret the session-manager Pod +# needs to start) before the Deployments become Ready. The +# rollout-status step below is the actual readiness gate. +helm upgrade --install educates-runtime "$CHART_DIR" \ + --namespace educates --create-namespace \ + -f "$CHART_VALUES" \ + --timeout 5m +ok "chart manifests applied" + +if [[ -x "${SCEN_DIR}/post-install.sh" ]]; then + step "2a/6 Run scenario post-install hook" + "${SCEN_DIR}/post-install.sh" + ok "post-install done" +fi + +step "2b/6 Wait for operators to be Ready" +kubectl -n educates rollout status deployment/session-manager --timeout=5m +kubectl -n educates rollout status deployment/secrets-manager --timeout=5m +ok "operators ready" + +step "3/6 Create training portal" +educates cluster portal create +ok "portal created" + +step "4/6 Deploy workshop" +# Per-scenario workshop discovery: if `/workshop/resources/workshop.yaml` +# exists, publish that scenario-local workshop to the local registry (which +# `educates local cluster create` stood up at localhost:5001) and deploy +# from that path. Otherwise fall back to the default WORKSHOP_URL. +SCEN_WORKSHOP_DIR="${SCEN_DIR}/workshop" +SCEN_WORKSHOP_YAML="${SCEN_WORKSHOP_DIR}/resources/workshop.yaml" +if [[ -f "$SCEN_WORKSHOP_YAML" ]]; then + echo "[runner] scenario-local workshop detected: ${SCEN_WORKSHOP_DIR}" + educates publish-workshop "$SCEN_WORKSHOP_DIR" + educates deploy-workshop -f "$SCEN_WORKSHOP_YAML" + ok "workshop published + deployed from $SCEN_WORKSHOP_DIR" +else + educates deploy-workshop -f "$WORKSHOP_URL" + ok "workshop deployed: $WORKSHOP_URL" +fi + +step "Resolving portal URL" +PORTAL_URL="" +for i in $(seq 1 30); do + PORTAL_URL="$(kubectl get trainingportal educates-cli -o jsonpath='{.status.educates.url}' 2>/dev/null || true)" + [[ -n "$PORTAL_URL" ]] && break + sleep 2 +done +if [[ -z "$PORTAL_URL" ]]; then + warn "could not resolve portal URL from trainingportal/educates-cli within 60s" +fi +export PORTAL_URL + +if [[ -x "${SCEN_DIR}/post-deploy.sh" ]]; then + step "4b/6 Run scenario post-deploy hook" + "${SCEN_DIR}/post-deploy.sh" + ok "post-deploy done" +fi + +step "5/6 Ready for manual verification" + +# Pure-bash percent-encoder (RFC 3986 unreserved set). Passwords from +# `educates cluster portal password` can contain `%`, `@`, `#`, `^`, +# etc., all of which break a raw query-string. +url_encode() { + local s="$1" out="" i c + for (( i=0; i<${#s}; i++ )); do + c="${s:i:1}" + case "$c" in + [-_.~A-Za-z0-9]) out+="$c" ;; + *) printf -v c '%%%02X' "'$c"; out+="$c" ;; + esac + done + printf '%s' "$out" +} + +if [[ -z "$PORTAL_URL" ]]; then + echo "Portal: (use 'educates cluster portal open' to launch the browser)" +else + PORTAL_PASS="$(educates cluster portal password 2>/dev/null | tr -d '[:space:]' || true)" + if [[ -n "$PORTAL_PASS" ]]; then + PORTAL_PASS_ENC="$(url_encode "$PORTAL_PASS")" + # The /workshops/access/ endpoint accepts ?password= for a + # one-click skip of the access-code prompt. + ACCESS_URL="${PORTAL_URL%/}/workshops/access/?password=${PORTAL_PASS_ENC}&redirect_url=%2F" + echo "Portal: $PORTAL_URL" + echo "Password: $PORTAL_PASS" + echo "Direct: $ACCESS_URL" + else + echo "Portal: $PORTAL_URL (could not resolve password — run 'educates cluster portal password')" + fi +fi +echo +if [[ $NO_WAIT -eq 0 ]]; then + read -r -p "Press Enter once verification is complete to proceed to teardown… " +fi + +if [[ $KEEP -eq 1 ]]; then + step "6/6 --keep set; leaving cluster running" +else + step "6/6 Delete cluster" + educates local cluster delete + ok "cluster deleted" +fi + +step "Result: PASS for scenario ${SCENARIO}" diff --git a/installer/charts/educates-training-platform/tests/scenarios/01-local-http-nip-io/chart-values.yaml b/installer/charts/educates-training-platform/tests/scenarios/01-local-http-nip-io/chart-values.yaml new file mode 100644 index 000000000..f3e788793 --- /dev/null +++ b/installer/charts/educates-training-platform/tests/scenarios/01-local-http-nip-io/chart-values.yaml @@ -0,0 +1,32 @@ +# Values for `helm install -f ` against the v4 chart. +# +# Local HTTP scenario — see description.md for context. + +# Subchart toggles. lookup-service and remote-access are not needed for +# a single-cluster local install. +lookup-service: + enabled: false +remote-access: + enabled: false + +# Cross-cutting globals propagate to every subchart. Defaults +# (imageRegistry: ghcr.io/educates, clusterSecurity: Kyverno) come from +# subchart-local values and don't need to be repeated here. +global: + clusterIngress: + domain: ${DOMAIN} + # protocol auto-derives to "http" because tlsCertificateRef.name is empty. + +session-manager: + trainingPortal: + credentials: + admin: + username: educates + password: educates + robot: + username: robot@educates + password: robot + clients: + robot: + id: robot-client-id + secret: robot-client-secret diff --git a/installer/charts/educates-training-platform/tests/scenarios/01-local-http-nip-io/description.md b/installer/charts/educates-training-platform/tests/scenarios/01-local-http-nip-io/description.md new file mode 100644 index 000000000..58f12d6ed --- /dev/null +++ b/installer/charts/educates-training-platform/tests/scenarios/01-local-http-nip-io/description.md @@ -0,0 +1,33 @@ +# Scenario 01 — Local HTTP, nip.io domain + +A minimal, certificate-free install for local-laptop iteration. + +- **Cluster:** kind, created by `educates local cluster create`. +- **Prerequisites installed by the v3 CLI:** Contour (ingress) and Kyverno + (policy engine). The v3 Educates package itself is **disabled** + (`clusterPackages.educates.enabled: false`) so the v4 chart can install + the runtime in its place. +- **Domain:** `127-0-0-1.nip.io` — the nip.io trick that resolves any + `*.127-0-0-1.nip.io` to `127.0.0.1`, where kind exposes its ingress. +- **TLS / CA:** none. Ingress runs on plain HTTP. +- **Subcharts enabled:** `secrets-manager`, `session-manager`. The + `lookup-service` and `remote-access` subcharts are disabled — they are + not exercised by a single-cluster local install. + +## What this proves + +- The chart renders and applies cleanly with all TLS/CA-related values + empty. +- The session-manager runtime config blob can drive the v3 runtime via + the `educates-config` Secret produced by the chart. +- A workshop session can be requested and reached through Contour over + plain HTTP, without any cert-manager involvement. + +## Known limitations + +- Image references are pinned to the v3 runtime tag (`3.7.1`) via + per-subchart `image.tag` overrides, because no `4.0.0-alpha.1` runtime + images exist yet. This is expected for the pre-phase. +- The session-manager `config` blob is set inline in `chart-values.yaml`. + In a v4 install the operator will derive these fields from the + SessionManager CR + EducatesClusterConfig.status. diff --git a/installer/charts/educates-training-platform/tests/scenarios/01-local-http-nip-io/educates-config.yaml b/installer/charts/educates-training-platform/tests/scenarios/01-local-http-nip-io/educates-config.yaml new file mode 100644 index 000000000..175e76ae0 --- /dev/null +++ b/installer/charts/educates-training-platform/tests/scenarios/01-local-http-nip-io/educates-config.yaml @@ -0,0 +1,29 @@ +# Config for `educates local cluster create --config `. +# +# Installs the Kubernetes prerequisites (Contour, Kyverno) but skips the +# Educates package itself, so the v4 Helm chart can install the runtime +# in its place. + +clusterInfrastructure: + provider: kind + +clusterSecurity: + policyEngine: kyverno + +clusterIngress: + domain: ${DOMAIN} + protocol: http + +clusterPackages: + contour: + enabled: true + kyverno: + enabled: true + cert-manager: + enabled: false + external-dns: + enabled: false + certs: + enabled: false + educates: + enabled: false diff --git a/installer/charts/educates-training-platform/tests/scenarios/02-kind-tls-wildcard/chart-values.yaml b/installer/charts/educates-training-platform/tests/scenarios/02-kind-tls-wildcard/chart-values.yaml new file mode 100644 index 000000000..7931e7a6f --- /dev/null +++ b/installer/charts/educates-training-platform/tests/scenarios/02-kind-tls-wildcard/chart-values.yaml @@ -0,0 +1,37 @@ +# Values for `helm install -f ` against the v4 chart. +# +# Kind + HTTPS scenario — see description.md for context. The wildcard +# TLS Secret and CA Secret are pre-created in the `educates-secrets` +# namespace by pre-install.sh; the chart auto-derives a SecretCopier from +# the cross-namespace `clusterIngress.{tls,ca}CertificateRef` so the +# runtime finds the Secrets locally. + +lookup-service: + enabled: false +remote-access: + enabled: false + +global: + clusterIngress: + domain: ${DOMAIN} + # protocol auto-derives to "https" because tlsCertificateRef.name is set. + tlsCertificateRef: + name: wildcard-tls + namespace: educates-secrets + caCertificateRef: + name: wildcard-ca + namespace: educates-secrets + +session-manager: + trainingPortal: + credentials: + admin: + username: educates + password: educates + robot: + username: robot@educates + password: robot + clients: + robot: + id: robot-client-id + secret: robot-client-secret diff --git a/installer/charts/educates-training-platform/tests/scenarios/02-kind-tls-wildcard/description.md b/installer/charts/educates-training-platform/tests/scenarios/02-kind-tls-wildcard/description.md new file mode 100644 index 000000000..8bee301cd --- /dev/null +++ b/installer/charts/educates-training-platform/tests/scenarios/02-kind-tls-wildcard/description.md @@ -0,0 +1,52 @@ +# Scenario 02 — Kind + Contour + Kyverno + wildcard TLS (offline-generated) + +A TLS-on scenario that exercises the chart's HTTPS values shape and +secret-propagation path without relying on cert-manager to issue the +wildcard cert. Cert-manager-as-issuer is intentionally out of scope here +— that's the v4 operator's job in Phase 2 of the development plan. + +## Layout of the test + +1. `educates local cluster create` provisions kind + Contour + Kyverno + only (no cert-manager, no certs package, no Educates package). +2. `pre-install.sh` runs between cluster-create and the chart install: + - Generates a self-signed root CA and a wildcard cert for + `*.127-0-0-1.nip.io` with `openssl`, into a tmp dir. + - Creates the namespace `educates-secrets`. + - `kubectl create secret tls wildcard-tls -n educates-secrets ...` + - `kubectl create secret generic wildcard-ca -n educates-secrets ...` +3. `helm install` lands the chart with `protocol: https` and + `secretPropagation.upstream.{ingressTLS,ingressCA}` pointing at those + Secrets. The session-manager's SecretCopier then copies them into + the operator namespace at runtime. + +## What this proves + +- The chart's TLS/CA values shape works end-to-end: ingress over HTTPS, + a wildcard cert wired into Contour, CA propagated to workshop + sessions. +- The `secretPropagation.upstream.*` copies actually work — Secrets + created in a foreign namespace are pulled into `educates` by the + SecretCopier resources the chart renders. +- The session-manager runtime correctly switches to HTTPS based on the + presence of `clusterIngress.tlsCertificateRef.name` in the config + blob. + +## Out of scope + +- Using cert-manager to issue the wildcard cert. A future scenario 03 + can exercise the v3 CLI's CA-injection point + cert-manager + certs + packages for that. +- Trusted CA chain in the host browser. The CA generated here is + self-signed; you'll get the usual "untrusted certificate" prompt when + opening the portal in a browser. Click through to verify the + workshop loads. + +## Notes for the runner + +- The CA + wildcard cert are generated fresh on each test run, into a + tmp directory printed by `pre-install.sh`. They are not committed to + the repo. +- The `pre-install.sh` hook is generic — `run-scenario.sh` invokes it + if present in the scenario folder. Future scenarios can drop one in + the same way. diff --git a/installer/charts/educates-training-platform/tests/scenarios/02-kind-tls-wildcard/educates-config.yaml b/installer/charts/educates-training-platform/tests/scenarios/02-kind-tls-wildcard/educates-config.yaml new file mode 100644 index 000000000..6e4f54bd6 --- /dev/null +++ b/installer/charts/educates-training-platform/tests/scenarios/02-kind-tls-wildcard/educates-config.yaml @@ -0,0 +1,28 @@ +# Config for `educates local cluster create --config `. +# +# Installs kind + Contour + Kyverno only. cert-manager is intentionally +# off — the wildcard cert for this scenario is generated offline by +# pre-install.sh and stamped into Secrets after cluster create. + +clusterInfrastructure: + provider: kind + +clusterSecurity: + policyEngine: kyverno + +clusterIngress: + domain: ${DOMAIN} + +clusterPackages: + contour: + enabled: true + kyverno: + enabled: true + cert-manager: + enabled: false + external-dns: + enabled: false + certs: + enabled: false + educates: + enabled: false diff --git a/installer/charts/educates-training-platform/tests/scenarios/02-kind-tls-wildcard/pre-install.sh b/installer/charts/educates-training-platform/tests/scenarios/02-kind-tls-wildcard/pre-install.sh new file mode 100755 index 000000000..e4d7895a1 --- /dev/null +++ b/installer/charts/educates-training-platform/tests/scenarios/02-kind-tls-wildcard/pre-install.sh @@ -0,0 +1,106 @@ +#!/usr/bin/env bash +# Materialises a wildcard TLS Secret and a CA Secret in the +# `educates-secrets` namespace, where the chart's +# `secretPropagation.upstream.{ingressTLS,ingressCA}` rules pull them +# into the operator namespace. Invoked by run-scenario.sh between +# cluster create and helm install. +# +# Inputs (provided by run-scenario.sh as env vars): +# DOMAIN required. Wildcard domain (e.g., "192.168.1.5.nip.io"). +# TLS_CERT_PATH optional. Pre-existing leaf cert. +# TLS_KEY_PATH optional. Pre-existing private key. Required when +# TLS_CERT_PATH is set. +# CA_CERT_PATH optional. CA cert PEM. +# CA_KEY_PATH optional. CA private key PEM. +# +# Resolution order (first match wins): +# 1. TLS_CERT_PATH + TLS_KEY_PATH given → use them as the leaf. +# 2. CA_CERT_PATH + CA_KEY_PATH given → generate a fresh wildcard +# leaf signed by that CA. +# 3. Otherwise → generate a self-signed CA + sign a fresh wildcard +# leaf with it. +# +# The CA Secret published to the cluster is whichever CA is actually +# in play (supplied or generated), so the runtime trusts the chain. + +set -Eeuo pipefail + +: "${DOMAIN:?DOMAIN env var must be set by the runner}" +SECRETS_NS="educates-secrets" +TLS_SECRET="wildcard-tls" +CA_SECRET="wildcard-ca" + +WORKDIR="$(mktemp -d -t educates-scenario-02-XXXX)" +echo "[pre-install] using workdir: $WORKDIR" + +if [[ -n "${TLS_CERT_PATH:-}" && -n "${TLS_KEY_PATH:-}" ]]; then + echo "[pre-install] using supplied leaf cert" + echo " cert: ${TLS_CERT_PATH}" + echo " key: ${TLS_KEY_PATH}" + cp "$TLS_CERT_PATH" "$WORKDIR/tls.crt" + cp "$TLS_KEY_PATH" "$WORKDIR/tls.key" + if [[ -n "${CA_CERT_PATH:-}" ]]; then + cp "$CA_CERT_PATH" "$WORKDIR/ca.crt" + echo "[pre-install] using supplied CA cert: ${CA_CERT_PATH}" + else + # No CA supplied; publish a copy of the leaf as the CA Secret so + # the runtime has *something* to read. Tools that strictly verify + # chain-of-trust may reject it, but the leaf is self-signed. + cp "$WORKDIR/tls.crt" "$WORKDIR/ca.crt" + fi +elif [[ -n "${CA_CERT_PATH:-}" && -n "${CA_KEY_PATH:-}" ]]; then + echo "[pre-install] signing fresh wildcard leaf for *.${DOMAIN} with supplied CA" + echo " ca-cert: ${CA_CERT_PATH}" + echo " ca-key: ${CA_KEY_PATH}" + cp "$CA_CERT_PATH" "$WORKDIR/ca.crt" + cp "$CA_KEY_PATH" "$WORKDIR/ca.key" + openssl req -nodes -newkey rsa:2048 \ + -subj "/CN=*.${DOMAIN}" \ + -keyout "$WORKDIR/tls.key" -out "$WORKDIR/tls.csr" \ + >/dev/null 2>&1 + cat >"$WORKDIR/tls.ext" </dev/null 2>&1 +elif [[ -n "${CA_CERT_PATH:-}" && -z "${CA_KEY_PATH:-}" ]]; then + echo "[pre-install] ERROR: --ca-cert was supplied but --ca-key is missing." >&2 + echo " Pass --ca-key , or omit --ca-cert to fall back to a self-signed CA." >&2 + echo " For mkcert, the key is typically at \$(mkcert -CAROOT)/rootCA-key.pem" >&2 + exit 2 +else + echo "[pre-install] generating self-signed CA + wildcard leaf for *.${DOMAIN}" + openssl req -x509 -nodes -newkey rsa:4096 -days 3650 \ + -subj "/CN=Educates Test Root CA" \ + -keyout "$WORKDIR/ca.key" -out "$WORKDIR/ca.crt" \ + >/dev/null 2>&1 + openssl req -nodes -newkey rsa:2048 \ + -subj "/CN=*.${DOMAIN}" \ + -keyout "$WORKDIR/tls.key" -out "$WORKDIR/tls.csr" \ + >/dev/null 2>&1 + cat >"$WORKDIR/tls.ext" </dev/null 2>&1 +fi + +kubectl create namespace "$SECRETS_NS" --dry-run=client -o yaml | kubectl apply -f - + +kubectl -n "$SECRETS_NS" create secret tls "$TLS_SECRET" \ + --cert="$WORKDIR/tls.crt" --key="$WORKDIR/tls.key" \ + --dry-run=client -o yaml | kubectl apply -f - + +kubectl -n "$SECRETS_NS" create secret generic "$CA_SECRET" \ + --from-file=ca.crt="$WORKDIR/ca.crt" \ + --dry-run=client -o yaml | kubectl apply -f - + +echo "[pre-install] secrets in ${SECRETS_NS}: ${TLS_SECRET}, ${CA_SECRET}" diff --git a/installer/charts/educates-training-platform/tests/scenarios/03-kind-cert-manager-issuer/chart-values.yaml b/installer/charts/educates-training-platform/tests/scenarios/03-kind-cert-manager-issuer/chart-values.yaml new file mode 100644 index 000000000..e3c06107b --- /dev/null +++ b/installer/charts/educates-training-platform/tests/scenarios/03-kind-cert-manager-issuer/chart-values.yaml @@ -0,0 +1,36 @@ +# Values for `helm install -f ` against the v4 chart. +# +# The wildcard TLS Secret was issued by cert-manager via the certs +# package and lands at `educates-secrets/educateswildcard`. The CA is +# at `educates-secrets/local-root-ca`. Cross-namespace ingress refs +# auto-derive the SecretCopier rules pulling both into the operator +# namespace. + +lookup-service: + enabled: false +remote-access: + enabled: false + +global: + clusterIngress: + domain: ${DOMAIN} + tlsCertificateRef: + name: educateswildcard + namespace: educates-secrets + caCertificateRef: + name: local-root-ca + namespace: educates-secrets + +session-manager: + trainingPortal: + credentials: + admin: + username: educates + password: educates + robot: + username: robot@educates + password: robot + clients: + robot: + id: robot-client-id + secret: robot-client-secret diff --git a/installer/charts/educates-training-platform/tests/scenarios/03-kind-cert-manager-issuer/description.md b/installer/charts/educates-training-platform/tests/scenarios/03-kind-cert-manager-issuer/description.md new file mode 100644 index 000000000..385cee8cf --- /dev/null +++ b/installer/charts/educates-training-platform/tests/scenarios/03-kind-cert-manager-issuer/description.md @@ -0,0 +1,59 @@ +# Scenario 03 — Kind + cert-manager as wildcard cert issuer + +Production-shaped install where cert-manager is the actual issuer of +the wildcard certificate, signed by a CA the user provides. This is +the closest pre-phase scenario to the v4 operator's `Managed` mode for +`EducatesClusterConfig.spec.certificates.provider: +BundledCertManager + issuerType: CustomCA`. + +## How it differs from scenario 02 + +Scenario 02 pre-generates the wildcard leaf in a shell script and +publishes both `wildcard-tls` and `wildcard-ca` Secrets directly, +bypassing cert-manager. Scenario 03 instead lets cert-manager do the +issuing — we only stage the CA — so we exercise the v3 installer's +`certs` package end-to-end (ClusterIssuer with `ca:` provider + +wildcard `Certificate` resource). + +## Layout of the test + +1. `educates local cluster create --cluster-only` provisions kind only. +2. `pre-install.sh` runs: + - Creates the `educates-secrets` namespace. + - Materialises the CA Secret `local-root-ca` in `educates-secrets` + with three keys: `tls.crt` + `tls.key` (consumed by cert-manager's + `ca:` issuer) and `ca.crt` (consumed by the v4 runtime for chain + trust). + - CA material comes from `--ca-cert/--ca-key` flags (or the mkcert + auto-detected sibling); falls back to a freshly-generated + self-signed CA when both are absent. +3. `educates admin platform deploy` installs cert-manager + certs + + Contour + Kyverno. The v3 kind overlay sees + `clusterInfrastructure.caCertificateRef` and wires: + - cert-manager with `clusterResourceNamespace: educates-secrets`. + - certs package with `local.caCertificateRef: local-root-ca` → + creates a `ClusterIssuer` named `educateswildcard` and a + `Certificate` that produces `educateswildcard` Secret in + `educates-secrets`. +4. `helm install` for the chart, referencing `educateswildcard` (TLS) + and `local-root-ca` (CA) for SecretCopier propagation into the + operator namespace. + +## What this proves + +- The v3 installer can be driven without the educates package, with + cert-manager + certs handling actual cert issuance from a + user-provided CA. +- Our chart's TLS values and `secretPropagation.upstream.*` shape + works against cert-manager-managed Secrets just as well as against + hand-rolled ones. +- A trusted CA passed via `--ca-cert/--ca-key` flows all the way + through to the workshop session pods (which need the CA to validate + TLS to the portal). + +## Out of scope + +- ACME-based issuance (Let's Encrypt). That's a separate scenario for + cloud installs and isn't applicable to local kind. +- Cert rotation testing. cert-manager will rotate, but the test + doesn't span long enough to observe it. diff --git a/installer/charts/educates-training-platform/tests/scenarios/03-kind-cert-manager-issuer/educates-config.yaml b/installer/charts/educates-training-platform/tests/scenarios/03-kind-cert-manager-issuer/educates-config.yaml new file mode 100644 index 000000000..03dd7a61b --- /dev/null +++ b/installer/charts/educates-training-platform/tests/scenarios/03-kind-cert-manager-issuer/educates-config.yaml @@ -0,0 +1,29 @@ +# Config for `educates local cluster create --cluster-only --config ` +# (cluster-only step) and `educates admin platform deploy --config ` +# (platform-deploy step). Both phases consume the same file. +# +# The kind overlay in the v3 installer auto-enables cert-manager + certs +# when `clusterInfrastructure.caCertificateRef` is set. We additionally +# disable the educates package so the v4 chart can install the runtime. + +clusterInfrastructure: + provider: kind + caCertificateRef: + name: local-root-ca + namespace: educates-secrets + +clusterSecurity: + policyEngine: kyverno + +clusterIngress: + domain: ${DOMAIN} + +clusterPackages: + contour: + enabled: true + kyverno: + enabled: true + external-dns: + enabled: false + educates: + enabled: false diff --git a/installer/charts/educates-training-platform/tests/scenarios/03-kind-cert-manager-issuer/pre-install.sh b/installer/charts/educates-training-platform/tests/scenarios/03-kind-cert-manager-issuer/pre-install.sh new file mode 100755 index 000000000..e1c93b2c0 --- /dev/null +++ b/installer/charts/educates-training-platform/tests/scenarios/03-kind-cert-manager-issuer/pre-install.sh @@ -0,0 +1,63 @@ +#!/usr/bin/env bash +# Stages the CA Secret that the v3 installer's certs package will use as +# its ClusterIssuer source. Invoked by run-scenario.sh between the +# cluster-only kind create and `educates admin platform deploy`. +# +# Inputs (provided by run-scenario.sh as env vars): +# DOMAIN required. +# CA_CERT_PATH optional. PEM CA cert. +# CA_KEY_PATH optional. PEM CA private key. The runner auto-detects +# the mkcert sibling (rootCA.pem ↔ rootCA-key.pem) when +# CA_KEY_PATH is left unset and CA_CERT_PATH is set. +# +# Resolution: +# - CA_CERT_PATH + CA_KEY_PATH given → publish them as the CA Secret. +# - Neither given → generate a self-signed CA + key on the fly. +# - Only one given → fail (the runner enforces this; double-checking +# here for defence in depth). + +set -Eeuo pipefail + +: "${DOMAIN:?DOMAIN env var must be set by the runner}" +SECRETS_NS="educates-secrets" +CA_SECRET="local-root-ca" + +WORKDIR="$(mktemp -d -t educates-scenario-03-XXXX)" +echo "[pre-install] using workdir: $WORKDIR" + +if [[ -n "${CA_CERT_PATH:-}" && -n "${CA_KEY_PATH:-}" ]]; then + echo "[pre-install] using supplied CA:" + echo " ca-cert: ${CA_CERT_PATH}" + echo " ca-key: ${CA_KEY_PATH}" + cp "$CA_CERT_PATH" "$WORKDIR/ca.crt" + cp "$CA_KEY_PATH" "$WORKDIR/ca.key" +elif [[ -n "${CA_CERT_PATH:-}" || -n "${CA_KEY_PATH:-}" ]]; then + echo "[pre-install] ERROR: both --ca-cert and --ca-key are required (got only one)." >&2 + exit 2 +else + echo "[pre-install] generating self-signed CA" + openssl req -x509 -nodes -newkey rsa:4096 -days 3650 \ + -subj "/CN=Educates Test Root CA" \ + -keyout "$WORKDIR/ca.key" -out "$WORKDIR/ca.crt" \ + >/dev/null 2>&1 +fi + +kubectl create namespace "$SECRETS_NS" --dry-run=client -o yaml | kubectl apply -f - + +# Single Secret with three keys: +# tls.crt + tls.key — consumed by cert-manager's `ca:` ClusterIssuer. +# ca.crt — consumed by the v4 runtime for chain trust. +# +# Note that the v3 ytt overlay-localca.yaml uses a different Secret +# layout when caCertificate is given inline (it stores the CA *key* in +# a field named `tls.crt`, which looks like a v3 quirk we don't want to +# replicate). When using caCertificateRef, the user owns the layout, so +# we use the canonical cert-manager + chain-trust shape. +kubectl -n "$SECRETS_NS" create secret generic "$CA_SECRET" \ + --type=kubernetes.io/tls \ + --from-file=tls.crt="$WORKDIR/ca.crt" \ + --from-file=tls.key="$WORKDIR/ca.key" \ + --from-file=ca.crt="$WORKDIR/ca.crt" \ + --dry-run=client -o yaml | kubectl apply -f - + +echo "[pre-install] CA Secret created: ${SECRETS_NS}/${CA_SECRET}" diff --git a/installer/charts/educates-training-platform/tests/scenarios/04-website-theme/chart-values.yaml b/installer/charts/educates-training-platform/tests/scenarios/04-website-theme/chart-values.yaml new file mode 100644 index 000000000..82bfe1eb1 --- /dev/null +++ b/installer/charts/educates-training-platform/tests/scenarios/04-website-theme/chart-values.yaml @@ -0,0 +1,45 @@ +# Same as scenario 01 + a custom default website theme. The content +# here is intentionally trivial — we only verify it lands in the +# `default-website-theme` Secret in the operator namespace, not that +# the portal renders it (a runtime concern). + +lookup-service: + enabled: false +remote-access: + enabled: false + +global: + clusterIngress: + domain: ${DOMAIN} + +session-manager: + trainingPortal: + credentials: + admin: + username: educates + password: educates + robot: + username: robot@educates + password: robot + clients: + robot: + id: robot-client-id + secret: robot-client-secret + + # The thing under test: a custom training-portal theme with unique + # markers that post-install.sh greps for in the rendered Secret. + # `script` -> training-portal.js, `style` -> training-portal.css, + # `html` -> training-portal.html (chart maps the structured triple + # to the flat secret keys the runtime expects). + websiteStyling: + inline: + trainingPortal: + html: | + + + Scenario 04 portal +

scenario-04-marker

+ + style: | + /* scenario-04-css-marker */ + body { font-family: monospace; } diff --git a/installer/charts/educates-training-platform/tests/scenarios/04-website-theme/description.md b/installer/charts/educates-training-platform/tests/scenarios/04-website-theme/description.md new file mode 100644 index 000000000..43b5a9deb --- /dev/null +++ b/installer/charts/educates-training-platform/tests/scenarios/04-website-theme/description.md @@ -0,0 +1,33 @@ +# Scenario 04 — Custom default website theme + +Validates the chart's `session-manager.websiteStyling.inline` block: +structured `{html,script,style}` triples that the chart maps to the +flat `: ` shape the runtime expects, written into +the `default-website-theme` Secret in the operator namespace. + +## What's tested + +End-to-end: the custom theme value must reach the live portal HTML +served by the training-portal pod. + +`post-deploy.sh` curls the portal URL (resolved from +`status.educates.url` on the TrainingPortal CR) and greps for a +unique marker that `chart-values.yaml` put into `training-portal.html`. +This exercises the whole chain — chart → `educates-config` Secret → +session-manager pickup → training-portal Deployment → HTTP response — +not just the chart's Secret-rendering. + +## Layout + +Same as scenario 01 (HTTP, nip.io domain, no TLS) — the website-theme +value is orthogonal to TLS, so we use the simplest base. The only +chart-values delta from 01 is the `websiteStyling.inline` block. + +## Out of scope + +- Custom themes propagated from a foreign namespace via + `secretPropagation.upstream.websiteThemes`. That requires a + Workshop/WorkshopEnvironment that references the theme by name and + is its own scenario. +- Browser-rendered DOM verification (we curl the raw HTML and grep — + enough to confirm session-manager applied the theme). diff --git a/installer/charts/educates-training-platform/tests/scenarios/04-website-theme/educates-config.yaml b/installer/charts/educates-training-platform/tests/scenarios/04-website-theme/educates-config.yaml new file mode 100644 index 000000000..175e76ae0 --- /dev/null +++ b/installer/charts/educates-training-platform/tests/scenarios/04-website-theme/educates-config.yaml @@ -0,0 +1,29 @@ +# Config for `educates local cluster create --config `. +# +# Installs the Kubernetes prerequisites (Contour, Kyverno) but skips the +# Educates package itself, so the v4 Helm chart can install the runtime +# in its place. + +clusterInfrastructure: + provider: kind + +clusterSecurity: + policyEngine: kyverno + +clusterIngress: + domain: ${DOMAIN} + protocol: http + +clusterPackages: + contour: + enabled: true + kyverno: + enabled: true + cert-manager: + enabled: false + external-dns: + enabled: false + certs: + enabled: false + educates: + enabled: false diff --git a/installer/charts/educates-training-platform/tests/scenarios/04-website-theme/post-deploy.sh b/installer/charts/educates-training-platform/tests/scenarios/04-website-theme/post-deploy.sh new file mode 100755 index 000000000..f7be3f4e5 --- /dev/null +++ b/installer/charts/educates-training-platform/tests/scenarios/04-website-theme/post-deploy.sh @@ -0,0 +1,35 @@ +#!/usr/bin/env bash +# End-to-end check: the custom websiteTheme must reach the live portal. +# Curls the resolved PORTAL_URL and looks for the marker that +# chart-values.yaml put into `training-portal.html`. This validates the +# whole chain — chart → educates-config Secret → session-manager +# pickup → training-portal pod → HTTP response. + +set -Eeuo pipefail + +: "${PORTAL_URL:?PORTAL_URL must be set by the runner}" +EXPECTED="scenario-04-marker" + +echo "[post-deploy] curling ${PORTAL_URL}" +HTML="" +# Retry — the portal Pod may still be coming up after deploy-workshop. +for i in $(seq 1 30); do + if HTML="$(curl -fsSL -k "$PORTAL_URL" 2>/dev/null)"; then + [[ -n "$HTML" ]] && break + fi + sleep 2 +done + +if [[ -z "$HTML" ]]; then + echo "[post-deploy] ✗ no response body from ${PORTAL_URL} after ~60s" >&2 + exit 1 +fi + +if grep -q "$EXPECTED" <<<"$HTML"; then + echo "[post-deploy] ✓ marker '${EXPECTED}' found in portal HTML" +else + echo "[post-deploy] ✗ marker '${EXPECTED}' NOT found in portal HTML" >&2 + echo "--- response (first 40 lines) ---" >&2 + head -40 <<<"$HTML" >&2 + exit 1 +fi diff --git a/installer/charts/educates-training-platform/tests/scenarios/05-image-pull-secrets/chart-values.yaml b/installer/charts/educates-training-platform/tests/scenarios/05-image-pull-secrets/chart-values.yaml new file mode 100644 index 000000000..9c23fd62f --- /dev/null +++ b/installer/charts/educates-training-platform/tests/scenarios/05-image-pull-secrets/chart-values.yaml @@ -0,0 +1,50 @@ +# Same as scenario 01 + session-manager pulls its image from a local, +# auth'd registry that pre-install.sh stood up. The pull-secret is +# pre-created in the operator namespace by pre-install.sh so the +# Deployment can pull at first reconciliation, before secrets-manager +# itself is up and processing the SecretCopier. + +lookup-service: + enabled: false +remote-access: + enabled: false + +global: + clusterIngress: + domain: ${DOMAIN} + +session-manager: + # Override the repository to point at the auth'd local registry. Tag + # inherits the chart default (= Chart.AppVersion = 3.7.1) — same as the + # upstream image we mirrored in. + image: + repository: educates-test-pull-registry:5000/educates/educates-session-manager + # Wire the pull secret into the Deployment's PodSpec. + imagePullSecrets: + - name: test-pull-secret + + trainingPortal: + credentials: + admin: + username: educates + password: educates + robot: + username: robot@educates + password: robot + clients: + robot: + id: robot-client-id + secret: robot-client-secret + + secretPropagation: + # Distribute this Secret name from operator NS to every portal / + # environment / session namespace, and inject it into the matching + # ServiceAccounts. + imagePullSecretNames: + - test-pull-secret + upstream: + # Keeps the operator-namespace copy of the Secret in sync with + # the source in `educates-secrets` after the initial bootstrap + # by pre-install.sh. + imagePullSecrets: + - { name: test-pull-secret, namespace: educates-secrets } diff --git a/installer/charts/educates-training-platform/tests/scenarios/05-image-pull-secrets/description.md b/installer/charts/educates-training-platform/tests/scenarios/05-image-pull-secrets/description.md new file mode 100644 index 000000000..6537df52a --- /dev/null +++ b/installer/charts/educates-training-platform/tests/scenarios/05-image-pull-secrets/description.md @@ -0,0 +1,69 @@ +# Scenario 05 — Image pull secret end-to-end with an auth'd local registry + +Validates the chart's `imagePullSecrets` plumbing by *actually pulling* +session-manager's image through an authenticated registry. If anything +in the chain (Secret name mismatch, wrong creds, Secret not in the +operator namespace, containerd not configured) is broken, +`session-manager` rollout fails and so does the scenario. No way to +silently pass. + +## What `pre-install.sh` does + +1. Creates a tmp dir with an `htpasswd` file (Apache MD5, + `educates-test:educates-test-pass`). +2. Runs `registry:2` as a container named `educates-test-pull-registry` + on the `educates` docker network with `REGISTRY_AUTH=htpasswd` + pointing at the file. Publishes container port 5000 to host + `localhost:5003` for the `docker login + push` step. +3. `docker login localhost:5003` and pushes + `educates-session-manager:3.7.1` into the registry under the path + `educates/educates-session-manager:3.7.1`. +4. Writes a `hosts.toml` into the kind control-plane's + `/etc/containerd/certs.d/educates-test-pull-registry:5000/` so + containerd will accept HTTP pulls from the registry hostname. + Modern containerd reloads `certs.d` dynamically — no restart needed. +5. Creates the `test-pull-secret` (`kubernetes.io/dockerconfigjson`) in + `educates-secrets` only — the source for the chart's upstream + SecretCopier rule. The in-operator-namespace copy is staged later + by `post-install.sh` (see below). + +## What `chart-values.yaml` does + +- Points `session-manager.image.repository` at + `educates-test-pull-registry:5000/educates/educates-session-manager`. +- Sets `session-manager.imagePullSecrets: [{name: test-pull-secret}]` + on the Deployment. +- Lists `test-pull-secret` in `secretPropagation.imagePullSecretNames` + for downstream propagation, and in + `secretPropagation.upstream.imagePullSecrets` so secrets-manager + keeps the operator-namespace copy in sync after the initial bootstrap + by `pre-install.sh`. + +## What `post-install.sh` does + +Runs immediately after helm has applied chart manifests, *before* +rollout-status. Creates the `test-pull-secret` in the `educates` +operator namespace so the session-manager Pod's pull retry can +succeed. We don't pre-create the operator namespace ourselves — helm +owns that — and we can't rely on secrets-manager to copy the Secret +upstream-from-source either, because secrets-manager itself isn't up +yet (its Pod also needs the pull secret). + +## What `post-deploy.sh` does + +Greps the session-manager Pod's events for `Successfully pulled image +educates-test-pull-registry:5000/...`. Failure means containerd didn't +actually pull from our registry — runs only after the runner's +`rollout status` and workshop deploy have already succeeded. + +## What `teardown.sh` does + +`docker rm -f educates-test-pull-registry` and removes the tmp dir. +Runs always (success or fail), before the cluster delete, via the +runner's cleanup trap. + +## Out of scope + +- secrets-manager's image is left at the public default, so its pull + doesn't go through the auth'd registry. Adding it would require the + same pre-stage step for *that* image too, with no extra signal. diff --git a/installer/charts/educates-training-platform/tests/scenarios/05-image-pull-secrets/educates-config.yaml b/installer/charts/educates-training-platform/tests/scenarios/05-image-pull-secrets/educates-config.yaml new file mode 100644 index 000000000..175e76ae0 --- /dev/null +++ b/installer/charts/educates-training-platform/tests/scenarios/05-image-pull-secrets/educates-config.yaml @@ -0,0 +1,29 @@ +# Config for `educates local cluster create --config `. +# +# Installs the Kubernetes prerequisites (Contour, Kyverno) but skips the +# Educates package itself, so the v4 Helm chart can install the runtime +# in its place. + +clusterInfrastructure: + provider: kind + +clusterSecurity: + policyEngine: kyverno + +clusterIngress: + domain: ${DOMAIN} + protocol: http + +clusterPackages: + contour: + enabled: true + kyverno: + enabled: true + cert-manager: + enabled: false + external-dns: + enabled: false + certs: + enabled: false + educates: + enabled: false diff --git a/installer/charts/educates-training-platform/tests/scenarios/05-image-pull-secrets/post-deploy.sh b/installer/charts/educates-training-platform/tests/scenarios/05-image-pull-secrets/post-deploy.sh new file mode 100755 index 000000000..21574408e --- /dev/null +++ b/installer/charts/educates-training-platform/tests/scenarios/05-image-pull-secrets/post-deploy.sh @@ -0,0 +1,30 @@ +#!/usr/bin/env bash +# Asserts the session-manager Pod actually pulled its image from the +# auth'd local registry. By the time this hook runs, rollout-status +# has already succeeded — so the Pod is up. Greps the Pod's events to +# confirm the pull came from our registry, not from a stale node cache +# or an unexpected fallback. + +set -Eeuo pipefail + +OP_NS="educates" +EXPECTED_REGISTRY="educates-test-pull-registry:5000" + +POD="$(kubectl -n "$OP_NS" get pod -l deployment=session-manager -o jsonpath='{.items[0].metadata.name}' 2>/dev/null || true)" +if [[ -z "$POD" ]]; then + echo "[post-deploy] ✗ no session-manager Pod found in ${OP_NS}" >&2 + exit 1 +fi + +EVENTS="$(kubectl -n "$OP_NS" describe pod "$POD" 2>/dev/null || true)" + +if grep -qE "Successfully pulled image .*${EXPECTED_REGISTRY}" <<<"$EVENTS"; then + echo "[post-deploy] ✓ session-manager pulled from ${EXPECTED_REGISTRY}" +elif grep -qE "Container image .*${EXPECTED_REGISTRY}.* already present" <<<"$EVENTS"; then + echo "[post-deploy] ✓ session-manager image (${EXPECTED_REGISTRY}) already cached on node" +else + echo "[post-deploy] ✗ no pull from ${EXPECTED_REGISTRY} observed for ${OP_NS}/${POD}" >&2 + echo "--- events tail ---" >&2 + echo "$EVENTS" | grep -A0 -E "Pulling|Pulled|Failed|ImagePull|ErrImagePull|BackOff" >&2 || true + exit 1 +fi diff --git a/installer/charts/educates-training-platform/tests/scenarios/05-image-pull-secrets/post-install.sh b/installer/charts/educates-training-platform/tests/scenarios/05-image-pull-secrets/post-install.sh new file mode 100755 index 000000000..cf702239d --- /dev/null +++ b/installer/charts/educates-training-platform/tests/scenarios/05-image-pull-secrets/post-install.sh @@ -0,0 +1,29 @@ +#!/usr/bin/env bash +# Stages the pull secret in the operator namespace immediately after +# helm has applied the chart manifests. The session-manager Deployment +# already exists at this point and its first Pod creation may have +# already failed to pull (ImagePullBackOff) — that's fine, the kubelet +# retries and the next attempt will succeed once this Secret is in +# place. +# +# secrets-manager will eventually take over keeping this Secret in +# sync (driven by the chart's secretPropagation.upstream.imagePullSecrets +# rule), but secrets-manager isn't necessarily Ready yet either, so +# we materialise the in-namespace copy directly here. + +set -Eeuo pipefail + +OP_NS="educates" +PULL_SECRET="test-pull-secret" +REGISTRY_INTERNAL_HOST="educates-test-pull-registry:5000" +REGISTRY_USER="educates-test" +REGISTRY_PASS="educates-test-pass" + +kubectl -n "$OP_NS" create secret docker-registry "$PULL_SECRET" \ + --docker-server="$REGISTRY_INTERNAL_HOST" \ + --docker-username="$REGISTRY_USER" \ + --docker-password="$REGISTRY_PASS" \ + --docker-email="test@invalid" \ + --dry-run=client -o yaml | kubectl apply -f - + +echo "[post-install] ${PULL_SECRET} created in ${OP_NS}" diff --git a/installer/charts/educates-training-platform/tests/scenarios/05-image-pull-secrets/pre-install.sh b/installer/charts/educates-training-platform/tests/scenarios/05-image-pull-secrets/pre-install.sh new file mode 100755 index 000000000..4e4dfcd49 --- /dev/null +++ b/installer/charts/educates-training-platform/tests/scenarios/05-image-pull-secrets/pre-install.sh @@ -0,0 +1,113 @@ +#!/usr/bin/env bash +# Stands up an htpasswd-protected docker registry on the educates docker +# network, mirrors educates-session-manager:3.7.1 into it, configures +# the kind control-plane node's containerd to accept it, and stages the +# pull secret in both `educates-secrets` and `educates` namespaces. +# +# Anything that fails here will fail the scenario early. The registry +# container and tmp dir are cleaned up by teardown.sh, which the runner +# calls in its cleanup trap regardless of outcome. + +set -Eeuo pipefail + +REGISTRY_NAME="educates-test-pull-registry" +REGISTRY_USER="educates-test" +REGISTRY_PASS="educates-test-pass" +REGISTRY_HOST_PORT="5003" +REGISTRY_INNER_PORT="5000" +REGISTRY_INTERNAL_HOST="${REGISTRY_NAME}:${REGISTRY_INNER_PORT}" +REGISTRY_LOGIN_HOST="localhost:${REGISTRY_HOST_PORT}" +DOCKER_NET="educates" +KIND_CONTROL_PLANE="educates-control-plane" + +UPSTREAM_IMAGE="ghcr.io/educates/educates-session-manager:3.7.1" +LOCAL_PATH="educates/educates-session-manager:3.7.1" +LOGIN_REF="${REGISTRY_LOGIN_HOST}/${LOCAL_PATH}" +INTERNAL_REF="${REGISTRY_INTERNAL_HOST}/${LOCAL_PATH}" + +PULL_SECRET="test-pull-secret" +SECRETS_NS="educates-secrets" +OP_NS="educates" + +WORKDIR="$(mktemp -d -t educates-scenario-05-XXXX)" +echo "$WORKDIR" > /tmp/educates-scenario-05.workdir +echo "[pre-install] using workdir: $WORKDIR" + +# 1. htpasswd file. registry:2's htpasswd auth backend only accepts +# bcrypt-hashed entries (Apache MD5 / SHA-1 / plain are rejected with +# 401). macOS doesn't ship the `htpasswd` binary, so we run it from a +# throwaway httpd:2 container. +docker run --rm httpd:2 htpasswd -Bbn "$REGISTRY_USER" "$REGISTRY_PASS" \ + > "$WORKDIR/htpasswd" + +# 2. Run the auth'd registry on the educates docker network. +docker rm -f "$REGISTRY_NAME" >/dev/null 2>&1 || true +docker network inspect "$DOCKER_NET" >/dev/null 2>&1 || docker network create "$DOCKER_NET" >/dev/null +docker run -d \ + --name "$REGISTRY_NAME" \ + --network "$DOCKER_NET" \ + -p "127.0.0.1:${REGISTRY_HOST_PORT}:${REGISTRY_INNER_PORT}" \ + -v "$WORKDIR/htpasswd:/auth/htpasswd:ro" \ + -e "REGISTRY_AUTH=htpasswd" \ + -e "REGISTRY_AUTH_HTPASSWD_REALM=Educates Test Realm" \ + -e "REGISTRY_AUTH_HTPASSWD_PATH=/auth/htpasswd" \ + registry:2 >/dev/null + +# Also attach the registry to every network the kind control-plane +# container is on, so containerd inside the node can resolve us by +# container name through that network's DNS. Mirrors what the v3 +# educates CLI does for its own registry (dual-attaches to `educates` +# and `kind`). +KIND_NETWORKS="$(docker inspect "$KIND_CONTROL_PLANE" --format '{{range $k,$v := .NetworkSettings.Networks}}{{$k}}{{"\n"}}{{end}}' 2>/dev/null | sed '/^$/d')" +if [[ -z "$KIND_NETWORKS" ]]; then + echo "[pre-install] could not enumerate networks for ${KIND_CONTROL_PLANE}" >&2 + exit 1 +fi +while IFS= read -r net; do + [[ "$net" == "$DOCKER_NET" ]] && continue + docker network connect "$net" "$REGISTRY_NAME" >/dev/null 2>&1 || true + echo "[pre-install] attached registry to docker network: $net" +done <<<"$KIND_NETWORKS" + +for i in $(seq 1 20); do + if curl -sSf "http://${REGISTRY_LOGIN_HOST}/v2/" -u "${REGISTRY_USER}:${REGISTRY_PASS}" >/dev/null 2>&1; then + break + fi + sleep 1 +done +echo "[pre-install] registry up at ${REGISTRY_LOGIN_HOST}" + +# 3. Mirror the upstream image. Use a tmp Docker config so we don't +# pollute the user's ~/.docker/config.json. +DOCKER_CONFIG="$WORKDIR/dockercfg" +mkdir -p "$DOCKER_CONFIG" +export DOCKER_CONFIG +echo "$REGISTRY_PASS" | docker --config "$DOCKER_CONFIG" login "$REGISTRY_LOGIN_HOST" -u "$REGISTRY_USER" --password-stdin >/dev/null +docker pull "$UPSTREAM_IMAGE" >/dev/null +docker tag "$UPSTREAM_IMAGE" "$LOGIN_REF" +docker --config "$DOCKER_CONFIG" push "$LOGIN_REF" >/dev/null +echo "[pre-install] mirrored ${UPSTREAM_IMAGE} → ${LOGIN_REF}" + +# 4. Configure containerd in the kind control-plane to accept the +# registry over plain HTTP under the *internal* hostname. Modern +# containerd reloads certs.d dynamically. +HOSTS_TOML="[host.\"http://${REGISTRY_INTERNAL_HOST}\"] + capabilities = [\"pull\", \"resolve\"] +" +docker exec "$KIND_CONTROL_PLANE" mkdir -p "/etc/containerd/certs.d/${REGISTRY_INTERNAL_HOST}" +printf '%s' "$HOSTS_TOML" \ + | docker exec -i "$KIND_CONTROL_PLANE" tee "/etc/containerd/certs.d/${REGISTRY_INTERNAL_HOST}/hosts.toml" >/dev/null +echo "[pre-install] containerd certs.d configured for ${REGISTRY_INTERNAL_HOST}" + +# 5. Stage the pull secret in `educates-secrets` only. The operator +# namespace is created by helm install (not pre-creating it avoids +# ordering quirks); post-install.sh creates the in-namespace copy +# *after* helm has applied the chart manifests. +kubectl create namespace "$SECRETS_NS" --dry-run=client -o yaml | kubectl apply -f - +kubectl -n "$SECRETS_NS" create secret docker-registry "$PULL_SECRET" \ + --docker-server="$REGISTRY_INTERNAL_HOST" \ + --docker-username="$REGISTRY_USER" \ + --docker-password="$REGISTRY_PASS" \ + --docker-email="test@invalid" \ + --dry-run=client -o yaml | kubectl apply -f - +echo "[pre-install] ${PULL_SECRET} staged in ${SECRETS_NS}" diff --git a/installer/charts/educates-training-platform/tests/scenarios/05-image-pull-secrets/teardown.sh b/installer/charts/educates-training-platform/tests/scenarios/05-image-pull-secrets/teardown.sh new file mode 100755 index 000000000..9580531df --- /dev/null +++ b/installer/charts/educates-training-platform/tests/scenarios/05-image-pull-secrets/teardown.sh @@ -0,0 +1,20 @@ +#!/usr/bin/env bash +# Always-runs cleanup for scenario 05. Removes the docker registry +# container and the tmp dir pre-install.sh stashed its path into. +# Idempotent — invoked by run-scenario.sh from its EXIT trap regardless +# of whether the scenario passed or failed. + +set -u +REGISTRY_NAME="educates-test-pull-registry" + +docker rm -f "$REGISTRY_NAME" >/dev/null 2>&1 || true + +if [[ -f /tmp/educates-scenario-05.workdir ]]; then + WORKDIR="$(cat /tmp/educates-scenario-05.workdir 2>/dev/null || true)" + if [[ -n "$WORKDIR" && -d "$WORKDIR" && "$WORKDIR" == /var/folders/* || "$WORKDIR" == /tmp/* ]]; then + rm -rf "$WORKDIR" + fi + rm -f /tmp/educates-scenario-05.workdir +fi + +echo "[teardown] scenario 05 cleanup complete" diff --git a/installer/charts/educates-training-platform/tests/scenarios/06-additional-kyverno-policies/chart-values.yaml b/installer/charts/educates-training-platform/tests/scenarios/06-additional-kyverno-policies/chart-values.yaml new file mode 100644 index 000000000..c85d30326 --- /dev/null +++ b/installer/charts/educates-training-platform/tests/scenarios/06-additional-kyverno-policies/chart-values.yaml @@ -0,0 +1,78 @@ +# Same as scenario 01 plus user-supplied Kyverno ClusterPolicy +# extras on both paths (cluster-wide via clusterSecurity, per-workshop +# via workshopSecurity), on top of the chart-bundled baseline + ops +# set. The post-deploy hook asserts both that the per-environment +# ClusterPolicy the runtime spawns contains rules from the bundle, and +# that the user-supplied marker rule is among them. + +lookup-service: + enabled: false +remote-access: + enabled: false + +global: + clusterIngress: + domain: ${DOMAIN} + +session-manager: + trainingPortal: + credentials: + admin: + username: educates + password: educates + robot: + username: robot@educates + password: robot + clients: + robot: + id: robot-client-id + secret: robot-client-secret + + # Cluster-wide policy enforcement via Kyverno (the chart default). + # The chart applies the bundled cluster-policies (PSS baseline + + # restricted) plus the user-supplied marker ClusterPolicy below. + clusterSecurity: + additionalKyvernoPolicies: + - apiVersion: kyverno.io/v1 + kind: ClusterPolicy + metadata: + name: scenario-06-cluster-marker + spec: + validationFailureAction: Audit + background: true + rules: + - name: scenario-06-cluster-marker + match: + any: + - resources: + kinds: [Pod] + validate: + message: "scenario-06 cluster placeholder — never matches" + cel: + expressions: + - expression: "true" + + # Per-workshop rules via Kyverno (the chart default). The chart appends + # the user marker to the bundled workshop-policies feed; session-manager + # clones the combined set per-environment and the post-deploy hook + # asserts the marker rule appears on `educates-environment-`. + workshopSecurity: + additionalKyvernoPolicies: + - apiVersion: kyverno.io/v1 + kind: ClusterPolicy + metadata: + name: scenario-06-workshop-marker + spec: + validationFailureAction: Audit + background: true + rules: + - name: scenario-06-workshop-marker + match: + any: + - resources: + kinds: [Pod] + validate: + message: "scenario-06 workshop placeholder — never matches" + cel: + expressions: + - expression: "true" diff --git a/installer/charts/educates-training-platform/tests/scenarios/06-additional-kyverno-policies/description.md b/installer/charts/educates-training-platform/tests/scenarios/06-additional-kyverno-policies/description.md new file mode 100644 index 000000000..23698d40a --- /dev/null +++ b/installer/charts/educates-training-platform/tests/scenarios/06-additional-kyverno-policies/description.md @@ -0,0 +1,60 @@ +# Scenario 06 — Bundled + user Kyverno policies, end-to-end + +Validates both Kyverno-policy paths the chart supports: cluster-wide +ClusterPolicies installed directly, and the per-workshop +`educates-environment-` ClusterPolicy session-manager spawns from +the `kyverno-policies.yaml` Secret feed. + +## What's tested + +Two independent paths land in the cluster: + +- **Cluster-wide path** — `clusterSecurity.policyEngine: Kyverno` + causes the chart to apply both Pod Security Standards profiles + (baseline + restricted) as cluster-wide ClusterPolicy resources. +- **Per-workshop path** — `workshopSecurity.rulesEngine: Kyverno` + writes the operational policies + the Educates-internal + `require-ingress-session-name` into the `kyverno-policies.yaml` + Secret feed. session-manager reads it and spawns one + `educates-environment-` ClusterPolicy per workshop, cloning + each rule with a namespace selector. + +User-supplied extras travel on both paths through +`clusterSecurity.additionalKyvernoPolicies` (installed directly) and +`workshopSecurity.additionalKyvernoPolicies` (appended to the Secret +feed). + +The `post-deploy.sh` hook asserts: + +- Cluster-wide ClusterPolicies present: + - `disallow-privileged-containers` (bundled baseline) + - `require-run-as-nonroot` (bundled restricted) + - `scenario-06-cluster-marker` (user-supplied via + `clusterSecurity.additionalKyvernoPolicies`) +- Per-environment `educates-environment-*` ClusterPolicy present with + rules: + - `no-loadbalancer-service` (bundled operational — the + `restrict-loadbalancer.yaml` file's ClusterPolicy is named + `no-loadbalancer-service` upstream; session-manager preserves + that name when cloning the single-rule policy) + - `require-ingress-session-name` (bundled Educates-internal) + - `scenario-06-workshop-marker` (user-supplied via + `workshopSecurity.additionalKyvernoPolicies`) + +## Layout + +Same as scenario 01 (HTTP, nip.io domain). The user-supplied marker +policies are CEL ClusterPolicies that always evaluate `true` (never +deny anything) — they exist only to be detectable by name. + +## Out of scope + +- Verifying that the policies actually deny anything in practice — + that would require crafting offending Pod specs and checking + Kyverno violation events. The chart-side wiring (rule names reach + the per-env policy and ClusterPolicies appear cluster-wide) is + what's under test here, not Kyverno itself. +- Toggle-off coverage for the bundles. With the typed-values shape, + toggling off is `clusterSecurity.policyEngine: None` / + `workshopSecurity.rulesEngine: None`. Add a sibling scenario for + the disabled case if needed. diff --git a/installer/charts/educates-training-platform/tests/scenarios/06-additional-kyverno-policies/educates-config.yaml b/installer/charts/educates-training-platform/tests/scenarios/06-additional-kyverno-policies/educates-config.yaml new file mode 100644 index 000000000..175e76ae0 --- /dev/null +++ b/installer/charts/educates-training-platform/tests/scenarios/06-additional-kyverno-policies/educates-config.yaml @@ -0,0 +1,29 @@ +# Config for `educates local cluster create --config `. +# +# Installs the Kubernetes prerequisites (Contour, Kyverno) but skips the +# Educates package itself, so the v4 Helm chart can install the runtime +# in its place. + +clusterInfrastructure: + provider: kind + +clusterSecurity: + policyEngine: kyverno + +clusterIngress: + domain: ${DOMAIN} + protocol: http + +clusterPackages: + contour: + enabled: true + kyverno: + enabled: true + cert-manager: + enabled: false + external-dns: + enabled: false + certs: + enabled: false + educates: + enabled: false diff --git a/installer/charts/educates-training-platform/tests/scenarios/06-additional-kyverno-policies/post-deploy.sh b/installer/charts/educates-training-platform/tests/scenarios/06-additional-kyverno-policies/post-deploy.sh new file mode 100755 index 000000000..3b5e4b04a --- /dev/null +++ b/installer/charts/educates-training-platform/tests/scenarios/06-additional-kyverno-policies/post-deploy.sh @@ -0,0 +1,64 @@ +#!/usr/bin/env bash +# End-to-end check that bundled + user-supplied Kyverno policies reach +# the cluster on both paths: +# +# 1. Cluster-wide path — bundled (baseline + restricted) AND +# user-supplied via clusterSecurity.additionalKyvernoPolicies are +# installed as cluster-wide ClusterPolicy resources directly by the +# chart. +# 2. Per-workshop path — operational + the internal +# require-ingress-session-name + user-supplied via +# workshopSecurity.additionalKyvernoPolicies are bundled into the +# `kyverno-policies.yaml` Secret feed and re-emitted by +# session-manager as `educates-environment-` ClusterPolicy +# rules. + +set -Eeuo pipefail + +EXPECTED_BASELINE_CP="disallow-privileged-containers" +EXPECTED_RESTRICTED_CP="require-run-as-nonroot" +EXPECTED_USER_CLUSTER_CP="scenario-06-cluster-marker" +EXPECTED_OPS_RULE="no-loadbalancer-service" +EXPECTED_INTERNAL_RULE="require-ingress-session-name" +EXPECTED_USER_WORKSHOP_RULE="scenario-06-workshop-marker" + +fail=0 + +# 1. Cluster-wide ClusterPolicies — bundled + user-supplied. +for cp in "$EXPECTED_BASELINE_CP" "$EXPECTED_RESTRICTED_CP" "$EXPECTED_USER_CLUSTER_CP"; do + if kubectl get clusterpolicy "$cp" >/dev/null 2>&1; then + echo "[post-deploy] ✓ cluster-wide ClusterPolicy present: $cp" + else + echo "[post-deploy] ✗ cluster-wide ClusterPolicy missing: $cp" >&2 + fail=1 + fi +done + +# 2. Per-environment ClusterPolicy (workshopSecurity bundle + user). +POLICY="" +for i in $(seq 1 30); do + POLICY="$(kubectl get clusterpolicy -o name 2>/dev/null | grep '^clusterpolicy.kyverno.io/educates-environment-' | head -1 || true)" + [[ -n "$POLICY" ]] && break + sleep 2 +done +if [[ -z "$POLICY" ]]; then + echo "[post-deploy] ✗ no educates-environment-* ClusterPolicy appeared within 60s" >&2 + echo "ClusterPolicies in cluster:" >&2 + kubectl get clusterpolicy >&2 || true + exit 1 +fi +echo "[post-deploy] ✓ runtime spawned ${POLICY}" + +RULES="$(kubectl get "$POLICY" -o jsonpath='{.spec.rules[*].name}')" +echo "[post-deploy] rules: $RULES" + +for rule in "$EXPECTED_OPS_RULE" "$EXPECTED_INTERNAL_RULE" "$EXPECTED_USER_WORKSHOP_RULE"; do + if grep -qE "(^| )${rule}($| )" <<<"$RULES"; then + echo "[post-deploy] ✓ per-env rule present: ${rule}" + else + echo "[post-deploy] ✗ per-env rule missing: ${rule}" >&2 + fail=1 + fi +done + +exit "$fail" diff --git a/installer/charts/educates-training-platform/tests/scenarios/07-config-escape-hatch/chart-values.yaml b/installer/charts/educates-training-platform/tests/scenarios/07-config-escape-hatch/chart-values.yaml new file mode 100644 index 000000000..c57c75d1a --- /dev/null +++ b/installer/charts/educates-training-platform/tests/scenarios/07-config-escape-hatch/chart-values.yaml @@ -0,0 +1,40 @@ +# Same as scenario 01 + uses the `config:` opaque escape hatch to: +# 1. Override a typed value (`dockerDaemon.networkMTU`) — proves +# `config:` deep-merges on top of typed-derived values, with +# `config:` winning on conflict. +# 2. Add an arbitrary runtime field not represented in the typed +# surface (`experimental.markerKey`) — proves the chart passes +# unknown fields through untouched, which is the whole point of +# the escape hatch (newly-added runtime fields land here first). +# +# The post-deploy hook reads the live `educates-config` Secret in the +# operator namespace and asserts both effects. + +lookup-service: + enabled: false +remote-access: + enabled: false + +global: + clusterIngress: + domain: ${DOMAIN} + +session-manager: + trainingPortal: + credentials: + admin: + username: educates + password: educates + robot: + username: robot@educates + password: robot + clients: + robot: + id: robot-client-id + secret: robot-client-secret + + config: + dockerDaemon: + networkMTU: 1450 + experimental: + markerKey: scenario-07-marker diff --git a/installer/charts/educates-training-platform/tests/scenarios/07-config-escape-hatch/description.md b/installer/charts/educates-training-platform/tests/scenarios/07-config-escape-hatch/description.md new file mode 100644 index 000000000..fd2ff51e9 --- /dev/null +++ b/installer/charts/educates-training-platform/tests/scenarios/07-config-escape-hatch/description.md @@ -0,0 +1,40 @@ +# Scenario 07 — `config:` escape-hatch deep-merge + +Validates the chart's `session-manager.config` opaque map: a deep-merge +applied on top of the typed-derived `educates-operator-config.yaml` +content, with `config:` winning on conflict. + +## What's tested + +The rendered `educates-config` Secret in the operator namespace must +contain: + +1. `dockerDaemon.networkMTU: 1450` — the chart-default for this typed + field is `1400`. The escape hatch sets `1450` and must win. +2. `experimental.markerKey: scenario-07-marker` — an arbitrary key + under an arbitrary block not in the typed surface, passed through + untouched. + +`post-deploy.sh` decodes the Secret and greps for both. + +## Layout + +Same as scenario 01 (HTTP, nip.io domain, no TLS) — the escape hatch +is orthogonal to TLS, so we use the simplest base. The only delta from +01 is the added `config:` block. + +## Why this scenario exists + +The typed-values refactor promoted ~15 well-known fields out of the +opaque `config:` map. `config:` survives as an escape hatch for runtime +fields that aren't yet typed. This scenario locks in the merge +semantics so future typed-promotion changes can't silently break the +override path. + +## Out of scope + +- The runtime *honouring* the escape-hatch values. The runtime knows + about `dockerDaemon.networkMTU` (typed before this refactor), so + setting it works end-to-end — but `experimental.markerKey` is not a + real runtime field and is only checked at the Secret level. We + validate the chart's behaviour, not the runtime's. diff --git a/installer/charts/educates-training-platform/tests/scenarios/07-config-escape-hatch/educates-config.yaml b/installer/charts/educates-training-platform/tests/scenarios/07-config-escape-hatch/educates-config.yaml new file mode 100644 index 000000000..6ee0beaf1 --- /dev/null +++ b/installer/charts/educates-training-platform/tests/scenarios/07-config-escape-hatch/educates-config.yaml @@ -0,0 +1,28 @@ +# Config for `educates local cluster create --config `. +# +# Same prerequisites as scenario 01 — only the chart's runtime-config +# escape hatch differs. + +clusterInfrastructure: + provider: kind + +clusterSecurity: + policyEngine: kyverno + +clusterIngress: + domain: ${DOMAIN} + protocol: http + +clusterPackages: + contour: + enabled: true + kyverno: + enabled: true + cert-manager: + enabled: false + external-dns: + enabled: false + certs: + enabled: false + educates: + enabled: false diff --git a/installer/charts/educates-training-platform/tests/scenarios/07-config-escape-hatch/post-deploy.sh b/installer/charts/educates-training-platform/tests/scenarios/07-config-escape-hatch/post-deploy.sh new file mode 100755 index 000000000..b43ddd45a --- /dev/null +++ b/installer/charts/educates-training-platform/tests/scenarios/07-config-escape-hatch/post-deploy.sh @@ -0,0 +1,43 @@ +#!/usr/bin/env bash +# Asserts the chart's `session-manager.config` escape hatch deep-merges +# correctly on top of the typed-derived runtime config: +# +# 1. `dockerDaemon.networkMTU: 1450` overrides the typed default of 1400. +# 2. `experimental.markerKey: scenario-07-marker` is passed through +# untouched (a key not in the typed surface). +# +# Reads the live `educates-config` Secret in the operator namespace. + +set -Eeuo pipefail + +NS="${OPERATOR_NAMESPACE:-educates}" + +echo "[post-deploy] reading educates-operator-config.yaml from secret/educates-config in ${NS}" +CFG="$(kubectl -n "$NS" get secret educates-config -o jsonpath='{.data.educates-operator-config\.yaml}' | base64 -d)" + +if [[ -z "$CFG" ]]; then + echo "[post-deploy] ✗ secret content empty" >&2 + exit 1 +fi + +fail=0 + +if grep -qE '^[[:space:]]*networkMTU:[[:space:]]*1450[[:space:]]*$' <<<"$CFG"; then + echo "[post-deploy] ✓ dockerDaemon.networkMTU override (1400 → 1450) honoured" +else + echo "[post-deploy] ✗ dockerDaemon.networkMTU not 1450" >&2 + fail=1 +fi + +if grep -qE '^[[:space:]]*markerKey:[[:space:]]*scenario-07-marker[[:space:]]*$' <<<"$CFG"; then + echo "[post-deploy] ✓ experimental.markerKey passed through" +else + echo "[post-deploy] ✗ experimental.markerKey not found" >&2 + fail=1 +fi + +if (( fail )); then + echo "--- educates-operator-config.yaml ---" >&2 + cat <<<"$CFG" >&2 + exit 1 +fi diff --git a/installer/charts/educates-training-platform/tests/scenarios/08-node-ca-injector-image-pull/chart-values.yaml b/installer/charts/educates-training-platform/tests/scenarios/08-node-ca-injector-image-pull/chart-values.yaml new file mode 100644 index 000000000..63f599619 --- /dev/null +++ b/installer/charts/educates-training-platform/tests/scenarios/08-node-ca-injector-image-pull/chart-values.yaml @@ -0,0 +1,43 @@ +# Scenario 08 — node-ca-injector image-pull validation. +# +# Same TLS+CA setup as scenario 02 (wildcard cert + CA in `educates-secrets`, +# auto-derived SecretCopier + ca-trust-store init container in chart pods), +# plus the `node-ca-injector` subchart enabled. The scenario-local workshop +# under `./workshop/` exercises the per-session registry: build a tiny +# image, push to the registry (HTTPS via the wildcard cert), then create a +# Deployment that pulls from that registry. The deployment's rollout +# completes only if containerd on the kind node trusts the wildcard CA — +# i.e., node-ca-injector wired things up. + +lookup-service: + enabled: false +remote-access: + enabled: false + +global: + clusterIngress: + domain: ${DOMAIN} + tlsCertificateRef: + name: wildcard-tls + namespace: educates-secrets + caCertificateRef: + name: wildcard-ca + namespace: educates-secrets + +# Subject under test. +node-ca-injector: + enabled: true + +session-manager: + trainingPortal: + credentials: + admin: + username: educates + password: educates + robot: + username: robot@educates + password: robot + clients: + robot: + id: robot-client-id + secret: robot-client-secret diff --git a/installer/charts/educates-training-platform/tests/scenarios/08-node-ca-injector-image-pull/description.md b/installer/charts/educates-training-platform/tests/scenarios/08-node-ca-injector-image-pull/description.md new file mode 100644 index 000000000..11083fc06 --- /dev/null +++ b/installer/charts/educates-training-platform/tests/scenarios/08-node-ca-injector-image-pull/description.md @@ -0,0 +1,47 @@ +# Scenario 08 — node-ca-injector image-pull validation + +End-to-end test that the cluster's containerd trusts the wildcard CA, by +having the workshop user build → push → deploy a container image through +the per-session registry (which is fronted by the wildcard cert). + +## What's tested + +- The full chain from chart → operator config → session-manager spawning + a workshop session → docker daemon trusting the registry → containerd + on the kind node trusting the registry → Deployment rollout succeeding. +- The decisive step is the `kubectl rollout status` at the end: it + passes only if containerd on the node successfully pulled the image + from the per-session registry. Without node-ca-injector writing the + CA into `/etc/containerd/certs.d/`, the pull would fail with a TLS + verification error and the rollout would hang in `ImagePullBackOff`. + +## Layout + +Same TLS+CA setup as scenario 02 (wildcard cert + CA in +`educates-secrets`, auto-derived SecretCopier, ca-trust-store init +container in session-manager and lookup-service Deployments), plus +`node-ca-injector.enabled: true` at the umbrella so the subchart's +controller Deployment + privileged DaemonSet render and run. + +The workshop is scenario-local — `./workshop/` is published to the +local registry by the runner via `educates publish-workshop` and +deployed with `educates deploy-workshop -f ./workshop/resources/workshop.yaml`. + +## Verification + +Interactive — the runner pauses at step 5/6 with the portal URL printed. +Open the workshop in the browser and step through the instructions; the +workshop's final page asserts the Deployment rollout completes. The +runner's exit code is independent of that assertion (the workshop UI is +the test surface). + +## Out of scope + +- Build-time CA-trust at the docker daemon level. That's exercised + implicitly when `docker push` succeeds inside the workshop session, + but the runtime overlay that wires it lives in + `session-manager/handlers/workshopsession.py` and isn't part of this + chart-level test. +- Multi-node CA propagation. kind clusters typically run a single node; + the DaemonSet's per-host fan-out is observable but not fundamentally + multi-node-tested here. diff --git a/installer/charts/educates-training-platform/tests/scenarios/08-node-ca-injector-image-pull/educates-config.yaml b/installer/charts/educates-training-platform/tests/scenarios/08-node-ca-injector-image-pull/educates-config.yaml new file mode 100644 index 000000000..6e4f54bd6 --- /dev/null +++ b/installer/charts/educates-training-platform/tests/scenarios/08-node-ca-injector-image-pull/educates-config.yaml @@ -0,0 +1,28 @@ +# Config for `educates local cluster create --config `. +# +# Installs kind + Contour + Kyverno only. cert-manager is intentionally +# off — the wildcard cert for this scenario is generated offline by +# pre-install.sh and stamped into Secrets after cluster create. + +clusterInfrastructure: + provider: kind + +clusterSecurity: + policyEngine: kyverno + +clusterIngress: + domain: ${DOMAIN} + +clusterPackages: + contour: + enabled: true + kyverno: + enabled: true + cert-manager: + enabled: false + external-dns: + enabled: false + certs: + enabled: false + educates: + enabled: false diff --git a/installer/charts/educates-training-platform/tests/scenarios/08-node-ca-injector-image-pull/pre-install.sh b/installer/charts/educates-training-platform/tests/scenarios/08-node-ca-injector-image-pull/pre-install.sh new file mode 100755 index 000000000..e4d7895a1 --- /dev/null +++ b/installer/charts/educates-training-platform/tests/scenarios/08-node-ca-injector-image-pull/pre-install.sh @@ -0,0 +1,106 @@ +#!/usr/bin/env bash +# Materialises a wildcard TLS Secret and a CA Secret in the +# `educates-secrets` namespace, where the chart's +# `secretPropagation.upstream.{ingressTLS,ingressCA}` rules pull them +# into the operator namespace. Invoked by run-scenario.sh between +# cluster create and helm install. +# +# Inputs (provided by run-scenario.sh as env vars): +# DOMAIN required. Wildcard domain (e.g., "192.168.1.5.nip.io"). +# TLS_CERT_PATH optional. Pre-existing leaf cert. +# TLS_KEY_PATH optional. Pre-existing private key. Required when +# TLS_CERT_PATH is set. +# CA_CERT_PATH optional. CA cert PEM. +# CA_KEY_PATH optional. CA private key PEM. +# +# Resolution order (first match wins): +# 1. TLS_CERT_PATH + TLS_KEY_PATH given → use them as the leaf. +# 2. CA_CERT_PATH + CA_KEY_PATH given → generate a fresh wildcard +# leaf signed by that CA. +# 3. Otherwise → generate a self-signed CA + sign a fresh wildcard +# leaf with it. +# +# The CA Secret published to the cluster is whichever CA is actually +# in play (supplied or generated), so the runtime trusts the chain. + +set -Eeuo pipefail + +: "${DOMAIN:?DOMAIN env var must be set by the runner}" +SECRETS_NS="educates-secrets" +TLS_SECRET="wildcard-tls" +CA_SECRET="wildcard-ca" + +WORKDIR="$(mktemp -d -t educates-scenario-02-XXXX)" +echo "[pre-install] using workdir: $WORKDIR" + +if [[ -n "${TLS_CERT_PATH:-}" && -n "${TLS_KEY_PATH:-}" ]]; then + echo "[pre-install] using supplied leaf cert" + echo " cert: ${TLS_CERT_PATH}" + echo " key: ${TLS_KEY_PATH}" + cp "$TLS_CERT_PATH" "$WORKDIR/tls.crt" + cp "$TLS_KEY_PATH" "$WORKDIR/tls.key" + if [[ -n "${CA_CERT_PATH:-}" ]]; then + cp "$CA_CERT_PATH" "$WORKDIR/ca.crt" + echo "[pre-install] using supplied CA cert: ${CA_CERT_PATH}" + else + # No CA supplied; publish a copy of the leaf as the CA Secret so + # the runtime has *something* to read. Tools that strictly verify + # chain-of-trust may reject it, but the leaf is self-signed. + cp "$WORKDIR/tls.crt" "$WORKDIR/ca.crt" + fi +elif [[ -n "${CA_CERT_PATH:-}" && -n "${CA_KEY_PATH:-}" ]]; then + echo "[pre-install] signing fresh wildcard leaf for *.${DOMAIN} with supplied CA" + echo " ca-cert: ${CA_CERT_PATH}" + echo " ca-key: ${CA_KEY_PATH}" + cp "$CA_CERT_PATH" "$WORKDIR/ca.crt" + cp "$CA_KEY_PATH" "$WORKDIR/ca.key" + openssl req -nodes -newkey rsa:2048 \ + -subj "/CN=*.${DOMAIN}" \ + -keyout "$WORKDIR/tls.key" -out "$WORKDIR/tls.csr" \ + >/dev/null 2>&1 + cat >"$WORKDIR/tls.ext" </dev/null 2>&1 +elif [[ -n "${CA_CERT_PATH:-}" && -z "${CA_KEY_PATH:-}" ]]; then + echo "[pre-install] ERROR: --ca-cert was supplied but --ca-key is missing." >&2 + echo " Pass --ca-key , or omit --ca-cert to fall back to a self-signed CA." >&2 + echo " For mkcert, the key is typically at \$(mkcert -CAROOT)/rootCA-key.pem" >&2 + exit 2 +else + echo "[pre-install] generating self-signed CA + wildcard leaf for *.${DOMAIN}" + openssl req -x509 -nodes -newkey rsa:4096 -days 3650 \ + -subj "/CN=Educates Test Root CA" \ + -keyout "$WORKDIR/ca.key" -out "$WORKDIR/ca.crt" \ + >/dev/null 2>&1 + openssl req -nodes -newkey rsa:2048 \ + -subj "/CN=*.${DOMAIN}" \ + -keyout "$WORKDIR/tls.key" -out "$WORKDIR/tls.csr" \ + >/dev/null 2>&1 + cat >"$WORKDIR/tls.ext" </dev/null 2>&1 +fi + +kubectl create namespace "$SECRETS_NS" --dry-run=client -o yaml | kubectl apply -f - + +kubectl -n "$SECRETS_NS" create secret tls "$TLS_SECRET" \ + --cert="$WORKDIR/tls.crt" --key="$WORKDIR/tls.key" \ + --dry-run=client -o yaml | kubectl apply -f - + +kubectl -n "$SECRETS_NS" create secret generic "$CA_SECRET" \ + --from-file=ca.crt="$WORKDIR/ca.crt" \ + --dry-run=client -o yaml | kubectl apply -f - + +echo "[pre-install] secrets in ${SECRETS_NS}: ${TLS_SECRET}, ${CA_SECRET}" diff --git a/installer/charts/educates-training-platform/tests/scenarios/08-node-ca-injector-image-pull/workshop/README.md b/installer/charts/educates-training-platform/tests/scenarios/08-node-ca-injector-image-pull/workshop/README.md new file mode 100644 index 000000000..7ae7ba829 --- /dev/null +++ b/installer/charts/educates-training-platform/tests/scenarios/08-node-ca-injector-image-pull/workshop/README.md @@ -0,0 +1,6 @@ +# Lab — node-ca-injector image pull + +Verify that the cluster's containerd trusts the cluster's wildcard CA by +building, pushing, and deploying a container image through the workshop +session's private OCI registry. If the deployment rolls out, the CA is +present in the node's containerd trust configuration. diff --git a/installer/charts/educates-training-platform/tests/scenarios/08-node-ca-injector-image-pull/workshop/exercises/README.md b/installer/charts/educates-training-platform/tests/scenarios/08-node-ca-injector-image-pull/workshop/exercises/README.md new file mode 100644 index 000000000..fafa0b25e --- /dev/null +++ b/installer/charts/educates-training-platform/tests/scenarios/08-node-ca-injector-image-pull/workshop/exercises/README.md @@ -0,0 +1,3 @@ +Exercise files for the node-ca-injector image-pull workshop. + +Files written under `~/exercises` during the workshop end up here. diff --git a/installer/charts/educates-training-platform/tests/scenarios/08-node-ca-injector-image-pull/workshop/resources/workshop.yaml b/installer/charts/educates-training-platform/tests/scenarios/08-node-ca-injector-image-pull/workshop/resources/workshop.yaml new file mode 100644 index 000000000..62ff3b926 --- /dev/null +++ b/installer/charts/educates-training-platform/tests/scenarios/08-node-ca-injector-image-pull/workshop/resources/workshop.yaml @@ -0,0 +1,40 @@ +apiVersion: training.educates.dev/v1beta1 +kind: Workshop +metadata: + name: lab-node-ca-pull +spec: + title: Node CA injection — image pull + description: Verify the cluster's containerd trusts the workshop wildcard CA by building, pushing, and deploying an image through the per-session registry. + duration: 10m + difficulty: beginner + publish: + image: "$(image_repository)/lab-node-ca-pull-files:$(workshop_version)" + files: + - directory: + path: . + includePaths: + - /workshop/** + - /exercises/** + - /README.md + workshop: + files: + - image: + url: "$(image_repository)/lab-node-ca-pull-files:$(workshop_version)" + session: + namespaces: + budget: medium + security: + # Workshop uses kubectl to create the Deployment that pulls from the + # per-session registry — Kubernetes access is the whole test surface. + token: + enabled: true + applications: + terminal: + enabled: true + layout: split + editor: + enabled: true + docker: + enabled: true + registry: + enabled: true diff --git a/installer/charts/educates-training-platform/tests/scenarios/08-node-ca-injector-image-pull/workshop/workshop/content/00-workshop-overview.md b/installer/charts/educates-training-platform/tests/scenarios/08-node-ca-injector-image-pull/workshop/workshop/content/00-workshop-overview.md new file mode 100644 index 000000000..5907ad155 --- /dev/null +++ b/installer/charts/educates-training-platform/tests/scenarios/08-node-ca-injector-image-pull/workshop/workshop/content/00-workshop-overview.md @@ -0,0 +1,32 @@ +--- +title: Overview +--- + +This workshop verifies that the cluster's container runtime (containerd) +trusts the cluster's wildcard CA. It does so by walking through a +realistic image-build pipeline: write a small Dockerfile, build it, +push it to the workshop session's private registry, and create a +Kubernetes Deployment that pulls the image from that registry. + +The session registry is an HTTPS endpoint at a subdomain of the cluster +ingress, fronted by the same wildcard certificate the workshop's portal +uses. The certificate is signed by a private CA that is **not** in any +public trust store. For the Deployment's image pull to succeed, the +node's containerd needs that CA in its per-registry trust +configuration. + +## What you will do + +1. Write a trivial `Dockerfile` and build a small image inside the + workshop session's docker daemon. +2. Tag the image for the per-session registry and push it. +3. Create a Kubernetes Deployment that pulls the image you just pushed. +4. Watch the rollout complete — or hang in `ImagePullBackOff` if the CA + trust is missing. + +## What success looks like + +`kubectl rollout status` returns `successfully rolled out` within a +handful of seconds. That confirms containerd on every node carrying +this Deployment's pod can speak HTTPS to the per-session registry and +verify the certificate against the cluster CA. diff --git a/installer/charts/educates-training-platform/tests/scenarios/08-node-ca-injector-image-pull/workshop/workshop/content/01-build-and-push.md b/installer/charts/educates-training-platform/tests/scenarios/08-node-ca-injector-image-pull/workshop/workshop/content/01-build-and-push.md new file mode 100644 index 000000000..50bd9f60c --- /dev/null +++ b/installer/charts/educates-training-platform/tests/scenarios/08-node-ca-injector-image-pull/workshop/workshop/content/01-build-and-push.md @@ -0,0 +1,49 @@ +--- +title: Build and push the image +--- + +Start by creating a minimal Dockerfile. The image just needs something +that keeps a process alive long enough for the rollout to settle. + +```editor:create-file +file: ~/exercises/Dockerfile +text: | + FROM busybox:1.36 + CMD ["sh", "-c", "echo node-ca-pull-test ready; sleep 3600"] +``` + +Build the image inside the workshop session's docker daemon. The +session uses its own daemon, isolated from the host. + +```terminal:execute +command: |- + docker build -t node-ca-pull-test:1 ~/exercises +``` + +The next step uses two environment variables that Educates pre-sets in +the terminal: `REGISTRY_HOST` (the per-session registry hostname, +under the cluster ingress wildcard) and `REGISTRY_USERNAME` / +`REGISTRY_PASSWORD` (per-session credentials). Take a quick look so the +following commands make sense. + +```terminal:execute +command: |- + echo "REGISTRY_HOST=${REGISTRY_HOST}" +``` + +Tag the freshly built image for the per-session registry, then push. +Educates has already populated `~/.docker/config.json` with the +registry credentials, so `docker push` authenticates without a manual +`docker login`. + +```terminal:execute +command: |- + docker tag node-ca-pull-test:1 ${REGISTRY_HOST}/node-ca-pull-test:1 + docker push ${REGISTRY_HOST}/node-ca-pull-test:1 +``` + +If the push completed without TLS errors, the workshop session's docker +daemon trusts the wildcard CA — that's the runtime-side overlay +(`session-manager/handlers/workshopsession.py`) doing its job. The next +page is the part this scenario actually targets: containerd on the +node. diff --git a/installer/charts/educates-training-platform/tests/scenarios/08-node-ca-injector-image-pull/workshop/workshop/content/02-deploy-and-pull.md b/installer/charts/educates-training-platform/tests/scenarios/08-node-ca-injector-image-pull/workshop/workshop/content/02-deploy-and-pull.md new file mode 100644 index 000000000..492fe033d --- /dev/null +++ b/installer/charts/educates-training-platform/tests/scenarios/08-node-ca-injector-image-pull/workshop/workshop/content/02-deploy-and-pull.md @@ -0,0 +1,79 @@ +--- +title: Deploy and watch the rollout +--- + +The image is now sitting in the per-session registry at +`${REGISTRY_HOST}/node-ca-pull-test:1`. Create a Kubernetes Deployment +that pulls from there and runs in the workshop's session namespace. + +The session namespace already has a `kubernetes.io/dockerconfigjson` +secret named via `${REGISTRY_SECRET}` attached to the `default` +ServiceAccount, so authentication on pull is handled. What's *not* +handled by Educates' own machinery is the TLS trust on the node — that +is what node-ca-injector is responsible for. + +```editor:create-file +file: ~/exercises/deployment.yaml +text: | + apiVersion: apps/v1 + kind: Deployment + metadata: + name: node-ca-pull-test + spec: + replicas: 1 + selector: + matchLabels: + app: node-ca-pull-test + template: + metadata: + labels: + app: node-ca-pull-test + spec: + containers: + - name: app + image: REGISTRY_HOST_PLACEHOLDER/node-ca-pull-test:1 + command: ["sh", "-c", "echo node-ca-pull-test ready; sleep 3600"] +``` + +Substitute the per-session registry hostname into the manifest, then +apply it. + +```terminal:execute +command: |- + sed -i "s|REGISTRY_HOST_PLACEHOLDER|${REGISTRY_HOST}|" ~/exercises/deployment.yaml + kubectl -n {{< param session_namespace >}} apply -f ~/exercises/deployment.yaml +``` + +Watch the rollout. The status command blocks until the Deployment +reports `successfully rolled out`, or until it times out — which is +what would happen if containerd couldn't pull the image because of an +untrusted certificate. + +```terminal:execute +command: |- + kubectl -n {{< param session_namespace >}} rollout status deployment/node-ca-pull-test --timeout=120s +``` + +If the previous command printed `deployment "node-ca-pull-test" +successfully rolled out`, **you've just observed node-ca-injector +working end-to-end**: the image came back over HTTPS from the +per-session registry, the wildcard cert verified against the CA that +node-ca-injector installed under `/etc/containerd/certs.d/`, and the +pod started. + +{{< note >}} +If the rollout instead times out, the Pod will be in +`ImagePullBackOff`. Run `kubectl -n {{< param session_namespace >}} +describe deployment node-ca-pull-test` and check the events on the +underlying ReplicaSet's Pods — a TLS verification error in the events +indicates the node-level CA trust is missing. +{{< /note >}} + +For a quick sanity check that the pod is alive, look at its log: + +```terminal:execute +command: |- + kubectl -n {{< param session_namespace >}} logs deployment/node-ca-pull-test +``` + +The expected output is `node-ca-pull-test ready`. diff --git a/installer/charts/educates-training-platform/tests/scenarios/08-node-ca-injector-image-pull/workshop/workshop/content/99-workshop-summary.md b/installer/charts/educates-training-platform/tests/scenarios/08-node-ca-injector-image-pull/workshop/workshop/content/99-workshop-summary.md new file mode 100644 index 000000000..bb652c47a --- /dev/null +++ b/installer/charts/educates-training-platform/tests/scenarios/08-node-ca-injector-image-pull/workshop/workshop/content/99-workshop-summary.md @@ -0,0 +1,31 @@ +--- +title: Summary +--- + +You just exercised the full image-pull path through a private CA: + +1. The per-session OCI registry is published at a subdomain of the + cluster ingress, served over HTTPS with a wildcard certificate + signed by a private CA. +2. The workshop session's docker daemon trusted that CA, so `docker + push` from the session worked without `--insecure-registry`. +3. The `default` ServiceAccount in the session namespace had registry + credentials attached, so the Pod's image pull authenticated. +4. **The node's containerd trusted the same CA** — without that trust, + the Pod would still be in `ImagePullBackOff` regardless of points 1 + through 3. + +Point 4 is the bit this workshop tests. The trust is wired by the +`node-ca-injector` subchart: a privileged DaemonSet on every node +writes per-host CA configuration into `/etc/containerd/certs.d/`, +keyed off the same `clusterIngress.caCertificateRef` Secret the chart +distributes via SecretCopier. + +If you saw the Deployment roll out successfully, this scenario passed. + +You can clean up the deployment if you like, then close the session. + +```terminal:execute +command: |- + kubectl -n {{< param session_namespace >}} delete -f ~/exercises/deployment.yaml +``` diff --git a/installer/charts/educates-training-platform/tests/scenarios/09-kind-all-options/chart-values.yaml b/installer/charts/educates-training-platform/tests/scenarios/09-kind-all-options/chart-values.yaml new file mode 100644 index 000000000..941804306 --- /dev/null +++ b/installer/charts/educates-training-platform/tests/scenarios/09-kind-all-options/chart-values.yaml @@ -0,0 +1,195 @@ +# Values for `helm install -f ` against the v4 chart. +# +# Kitchen-sink scenario — every subchart enabled and every +# session-manager value block populated. See description.md for what +# each block's assertion is. Secrets referenced from `educates-secrets` +# are created by pre-install.sh; the chart auto-derives SecretCopiers +# for the cross-namespace refs. +# +# NOT the full chart surface: this file covers the *functional* value +# blocks. Each subchart also exposes per-pod operational knobs that are +# deliberately left at their defaults here (an e2e scenario gains +# nothing from overriding them, and image overrides would point the +# test away from the released refs). They are set the same way as the +# blocks below — nested under the subchart's key: +# +# - `.image.{repository,tag,pullPolicy}` — per-component +# image override (secrets-manager, lookup-service, session-manager, +# node-ca-injector). +# - `.imagePullSecrets` — pull secrets for the component's +# own pod (distinct from session-manager.secretPropagation, which +# feeds workshop namespaces). +# - `.resources` — pod resource requests/limits +# (node-ca-injector splits this into `controller.resources` and +# `sync.resources`). +# - `global.development.imageRegistry.{host,namespace}` — local-dev +# redirect of every Educates image ref (e.g. localhost:5001 builds); +# also exists per-subchart as `.development.imageRegistry`. +# - `secrets-manager.logLevel`, `lookup-service.ingress.className`, +# `lookup-service.remoteAccessTokenMount.enabled`. +# - session-manager extras left default or documented as out of scope +# in description.md: `clusterRuntime.class`, `clusterStorage.class` +# / `clusterStorage.user`, `dockerDaemon.proxyCache.{username, +# password}`, `imagePrePuller.{pauseImage,images}`, and the +# remaining `websiteStyling.inline.*` blocks (workshopDashboard, +# workshopInstructions, workshopStarted, workshopFinished). +# +# The authoritative list is each subchart's values.yaml +# (installer/charts/educates-training-platform/charts//), or +# `helm show values ./installer/charts/educates-training-platform`. + +lookup-service: + enabled: true + ingress: + host: lookup.${DOMAIN} + +remote-access: + enabled: true + +node-ca-injector: + enabled: true + +global: + clusterIngress: + domain: ${DOMAIN} + # protocol auto-derives to "https" because tlsCertificateRef.name is set. + tlsCertificateRef: + name: wildcard-tls + namespace: educates-secrets + caCertificateRef: + name: wildcard-ca + namespace: educates-secrets + clusterSecurity: + policyEngine: Kyverno + +session-manager: + trainingPortal: + credentials: + admin: + username: educates + password: educates + robot: + username: robot@educates + password: robot + clients: + robot: + id: robot-client-id + secret: robot-client-secret + + # Grant the session-manager SA cluster-admin (chart default is false; + # this is the v3-default behaviour, exercised here). + clusterAdmin: true + + clusterSecurity: + additionalKyvernoPolicies: + - apiVersion: kyverno.io/v1 + kind: ClusterPolicy + metadata: + name: scenario-09-cluster-marker + spec: + validationFailureAction: Audit + background: true + rules: + - name: scenario-09-cluster-marker + match: + any: + - resources: + kinds: [Pod] + validate: + message: "scenario-09 cluster placeholder — never matches" + cel: + expressions: + - expression: "true" + + workshopSecurity: + additionalKyvernoPolicies: + - apiVersion: kyverno.io/v1 + kind: ClusterPolicy + metadata: + name: scenario-09-workshop-marker + spec: + validationFailureAction: Audit + background: true + rules: + - name: scenario-09-workshop-marker + match: + any: + - resources: + kinds: [Pod] + validate: + message: "scenario-09 workshop placeholder — never matches" + cel: + expressions: + - expression: "true" + + # Appended to the chart's default image inventory (name not in the + # default list) — asserted in the rendered config blob, never pulled. + imageVersions: + - name: scenario-09-extra-image + image: ghcr.io/educates/scenario-09-extra:0.0.1 + + sessionCookies: + domain: ${DOMAIN} + + clusterStorage: + # class empty → cluster default StorageClass (kind's standard). + # user stays null — chowning is for NFS-backed classes and + # conflicts with pod security enforcement. + group: 1 + + # clusterRuntime.class left unset — kind has no alternative runtime + # class installed. + + clusterNetwork: + blockCIDRs: + - "169.254.169.254/32" + - "fd00:ec2::254/128" + + dockerDaemon: + networkMTU: 1450 + proxyCache: + remoteURL: "https://registry-1.docker.io" + + workshopAnalytics: + google: + trackingId: G-SCENARIO09 + clarity: + trackingId: clarity-scenario-09 + amplitude: + trackingId: amp-scenario-09 + webhook: + url: https://analytics.example.com/scenario-09 + + websiteStyling: + inline: + trainingPortal: + html: '
' + # The external theme wins as portal default; the inline assets are + # asserted at the default-website-theme Secret level. + defaultTheme: scenario-theme + themeDataRefs: + - name: scenario-theme + namespace: educates-secrets + frameAncestors: + - https://embed.example.com + + imagePrePuller: + enabled: true + # images empty → chart derives the v3-equivalent default + # (training-portal + base-environment), which the test workshop + # needs anyway. + + secretPropagation: + imagePullSecretNames: + - scenario-pull-secret + upstream: + imagePullSecrets: + - name: scenario-pull-secret + namespace: educates-secrets + websiteThemes: + - name: extra-theme + namespace: educates-secrets + + config: + experimental: + markerKey: scenario-09-marker diff --git a/installer/charts/educates-training-platform/tests/scenarios/09-kind-all-options/description.md b/installer/charts/educates-training-platform/tests/scenarios/09-kind-all-options/description.md new file mode 100644 index 000000000..0445ff11a --- /dev/null +++ b/installer/charts/educates-training-platform/tests/scenarios/09-kind-all-options/description.md @@ -0,0 +1,76 @@ +# Scenario 09 — kitchen sink: every subchart on, every value block set + +The "complete install" scenario: all five subcharts enabled (including +lookup-service and remote-access, which no other scenario turns on) and +every session-manager value block populated. One run validates that the +chart's full typed-values surface serialises into the runtime config and +that the optional subcharts coexist on a single kind cluster. + +## Layout of the test + +1. `educates local cluster create` provisions kind + Contour + Kyverno + (no cert-manager — TLS material is generated offline, as in 02). +2. `pre-install.sh`: + - Generates (or reuses, via the runner's `--tls-*`/`--ca-*` flags) a + CA + wildcard leaf for `*.${DOMAIN}` and publishes them as + `wildcard-tls` / `wildcard-ca` in `educates-secrets` (same as 02). + - Creates two website-theme Secrets in `educates-secrets`: + `scenario-theme` (referenced via `websiteStyling.themeDataRefs` and + set as `defaultTheme`) and `extra-theme` (copied via + `secretPropagation.upstream.websiteThemes`). + - Creates a dummy docker-registry Secret `scenario-pull-secret` in + `educates-secrets` (copied in via `secretPropagation.upstream. + imagePullSecrets`, then propagated by name). +3. `helm install` lands the chart with everything enabled. +4. `post-deploy.sh` asserts the full chain (see below). + +## What this proves + +- **Subchart coexistence** — lookup-service (with its Ingress at + `lookup.${DOMAIN}`), remote-access, node-ca-injector, and the + image-puller DaemonSet all deploy alongside session-manager and + secrets-manager in one release. +- **Typed-values serialisation** — `post-deploy.sh` reads the live + `educates-config` Secret and asserts every populated block landed: + sessionCookies, clusterNetwork.blockCIDRs, dockerDaemon (MTU + + proxyCache), all four workshopAnalytics providers, websiteStyling + (defaultTheme + frameAncestors), the appended `imageVersions` entry, + and the `config:` escape-hatch marker. +- **Secret plumbing** — the cross-namespace TLS/CA refs, both theme + Secrets, and the pull Secret are all copied into the release + namespace by the SecretCopiers the chart renders. +- **Theme end-to-end** — `defaultTheme` points at the external + `scenario-theme` Secret; the portal HTML must serve its marker. The + inline theme assets are asserted at the `default-website-theme` + Secret level. +- **Kyverno extras on both paths** — cluster-wide and per-workshop + marker policies (same shape as scenario 06; asserted at the + ClusterPolicy level only, 06 owns the deep per-environment checks). + +## Out of scope + +- Per-pod operational knobs — `image.{repository,tag,pullPolicy}`, + `imagePullSecrets`, and `resources` on each subchart, plus + `development.imageRegistry`. Left at defaults so the test runs the + released image refs; the header comment in `chart-values.yaml` lists + them and how to set them. +- `clusterRuntime.class` — left unset; kind has no alternative runtime + class (e.g., kata) installed. +- `clusterStorage.user` — left null; chowning volumes to a UID is for + NFS-backed classes and conflicts with pod security enforcement. +- `development.imageRegistry` and per-pod `image:` overrides — these + point the install at locally-built images; the scenario tests the + released refs. +- Workshop-level pulls through `scenario-pull-secret` — the secret + carries dummy credentials; only its copy/propagation is asserted + (scenario 05 proves real authenticated pulls). +- Deep per-environment Kyverno assertions (scenario 06) and real + containerd CA pulls through node-ca-injector (scenario 08). + +## Notes for the runner + +- TLS resolution order and flags are identical to scenario 02 (supply + `--ca-cert`/`--ca-key` from mkcert for a browser-trusted run). +- `remoteAccessTokenMount` is on by default in lookup-service, and + remote-access is enabled, so the token Secret the Deployment mounts + exists — don't disable one without the other. diff --git a/installer/charts/educates-training-platform/tests/scenarios/09-kind-all-options/educates-config.yaml b/installer/charts/educates-training-platform/tests/scenarios/09-kind-all-options/educates-config.yaml new file mode 100644 index 000000000..6e4f54bd6 --- /dev/null +++ b/installer/charts/educates-training-platform/tests/scenarios/09-kind-all-options/educates-config.yaml @@ -0,0 +1,28 @@ +# Config for `educates local cluster create --config `. +# +# Installs kind + Contour + Kyverno only. cert-manager is intentionally +# off — the wildcard cert for this scenario is generated offline by +# pre-install.sh and stamped into Secrets after cluster create. + +clusterInfrastructure: + provider: kind + +clusterSecurity: + policyEngine: kyverno + +clusterIngress: + domain: ${DOMAIN} + +clusterPackages: + contour: + enabled: true + kyverno: + enabled: true + cert-manager: + enabled: false + external-dns: + enabled: false + certs: + enabled: false + educates: + enabled: false diff --git a/installer/charts/educates-training-platform/tests/scenarios/09-kind-all-options/post-deploy.sh b/installer/charts/educates-training-platform/tests/scenarios/09-kind-all-options/post-deploy.sh new file mode 100755 index 000000000..7e3ec5b88 --- /dev/null +++ b/installer/charts/educates-training-platform/tests/scenarios/09-kind-all-options/post-deploy.sh @@ -0,0 +1,142 @@ +#!/usr/bin/env bash +# Kitchen-sink assertions, in four groups: +# +# 1. Typed-values serialisation — every populated session-manager +# value block must appear in the rendered `educates-config` +# Secret (the runtime config blob). +# 2. Secret plumbing — both theme Secrets and the pull Secret must +# have been copied into the release namespace by the chart's +# SecretCopiers; the inline theme assets must be in the +# `default-website-theme` Secret. +# 3. Optional subcharts — lookup-service, remote-access, +# node-ca-injector, and the image-puller DaemonSet are all live. +# 4. Theme end-to-end — the portal serves the external +# `scenario-theme` marker (defaultTheme points at it). + +set -Eeuo pipefail + +: "${PORTAL_URL:?PORTAL_URL must be set by the runner}" +NS="${OPERATOR_NAMESPACE:-educates}" +fail=0 + +# --- 1. Typed-values serialisation ------------------------------------ + +echo "[post-deploy] reading educates-operator-config.yaml from secret/educates-config in ${NS}" +CFG="$(kubectl -n "$NS" get secret educates-config -o jsonpath='{.data.educates-operator-config\.yaml}' | base64 -d)" +if [[ -z "$CFG" ]]; then + echo "[post-deploy] ✗ secret content empty" >&2 + exit 1 +fi + +assert_cfg() { #