Skip to content

Commit 62bddfa

Browse files
committed
🧪 test-suite for registry mirroring and proxying
1 parent bf239b1 commit 62bddfa

13 files changed

Lines changed: 612 additions & 17 deletions

tests/e2e/README.md

Lines changed: 53 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,9 @@ End-to-end tests that deploy the Mondoo operator to a real GKE cluster and verif
66

77
- **Fresh Deploy** (`run-fresh-deploy.sh`): Builds the operator from the current branch, deploys to a GKE cluster, configures scanning, and verifies everything works.
88
- **Upgrade** (`run-upgrade.sh`): Installs a released baseline version first, verifies it, then upgrades to the current branch and verifies again.
9+
- **Registry Mirroring & Proxy** (`run-registry-mirroring.sh`): Deploys with an Artifact Registry mirror repo and optional Squid proxy. Verifies image references are rewritten, `imagePullSecrets` are propagated, and proxy env vars are set.
910

10-
Both tests pause for manual verification at each verify step (check Mondoo console for assets/scan results). Press Enter to continue or Ctrl+C to abort.
11+
All tests pause for manual verification at each verify step (check Mondoo console for assets/scan results). Press Enter to continue or Ctrl+C to abort.
1112

1213
## Prerequisites
1314

@@ -17,6 +18,8 @@ Both tests pause for manual verification at each verify step (check Mondoo conso
1718
- `docker`
1819
- `kubectl`
1920
- Go toolchain (for building the operator)
21+
- `jq` (for registry mirroring test verification)
22+
- `crane` CLI (for registry mirroring test): `go install github.com/google/go-containerregistry/cmd/crane@latest`
2023

2124
### Mondoo credentials
2225

@@ -57,6 +60,8 @@ terraform apply \
5760
| `mondoo_org_id` | yes | - | Mondoo organization ID |
5861
| `region` | no | `europe-west3` | GCP region |
5962
| `autopilot` | no | `true` | `true` for Autopilot, `false` for Standard cluster |
63+
| `enable_mirror_test` | no | `false` | Create a mirror AR repo for registry mirroring/imagePullSecrets tests |
64+
| `enable_proxy_test` | no | `false` | Provision a Squid proxy VM for proxy tests (requires `enable_mirror_test`) |
6065

6166
You can also set these in a `terraform.tfvars` file.
6267

@@ -94,6 +99,32 @@ What it does:
9499
6. Upgrades to the current branch image via local Helm chart
95100
7. Waits, verifies again, pauses for manual check
96101

102+
### Registry Mirroring & Proxy
103+
104+
```bash
105+
# Provision infrastructure with mirror AR repo (and optional proxy VM)
106+
cd tests/e2e/terraform
107+
terraform apply -var="project_id=MY_PROJECT" -var="mondoo_org_id=MY_ORG" \
108+
-var="enable_mirror_test=true" -var="enable_proxy_test=true"
109+
110+
# Run the test
111+
cd tests/e2e
112+
./run-registry-mirroring.sh
113+
```
114+
115+
What it does:
116+
1. Loads Terraform outputs (including mirror AR repo and proxy IP if enabled)
117+
2. Builds the operator image and pushes to Artifact Registry
118+
3. Creates `imagePullSecret` from the mirror repo's GCP service account key
119+
4. Uses `crane` to copy cnspec image from ghcr.io into the mirror AR repo
120+
5. Deploys an nginx test workload
121+
6. Helm installs the operator with `registryMirrors`, `imagePullSecrets`, and proxy `--values`
122+
7. Applies MondooAuditConfig, waits 90s for reconciliation
123+
8. Runs standard verification checks
124+
9. Runs mirroring-specific checks: image refs rewritten, pull secrets propagated, proxy env vars set
125+
10. Checks Squid proxy access logs (if proxy enabled)
126+
11. Pauses for manual verification in the Mondoo console
127+
97128
## Cleanup
98129

99130
Remove all test resources from the cluster (everything except Terraform infra):
@@ -115,23 +146,29 @@ terraform destroy -var="project_id=MY_PROJECT" -var="mondoo_org_id=MY_ORG"
115146
```
116147
tests/e2e/
117148
├── README.md
118-
├── run-fresh-deploy.sh # Fresh deploy test orchestrator
119-
├── run-upgrade.sh # Upgrade test orchestrator
149+
├── run-fresh-deploy.sh # Fresh deploy test orchestrator
150+
├── run-upgrade.sh # Upgrade test orchestrator
151+
├── run-registry-mirroring.sh # Registry mirroring & proxy test orchestrator
120152
├── terraform/
121-
│ ├── versions.tf # Provider requirements
122-
│ ├── variables.tf # Input variables
123-
│ ├── main.tf # GKE cluster + Artifact Registry
124-
│ ├── mondoo.tf # Mondoo space + service account
125-
│ └── outputs.tf # Outputs consumed by scripts
153+
│ ├── versions.tf # Provider requirements
154+
│ ├── variables.tf # Input variables
155+
│ ├── main.tf # GKE cluster + Artifact Registry
156+
│ ├── mondoo.tf # Mondoo space + service account
157+
│ ├── proxy.tf # Squid proxy VM (optional)
158+
│ └── outputs.tf # Outputs consumed by scripts
126159
├── scripts/
127-
│ ├── common.sh # Logging, TF output loading, wait helpers
128-
│ ├── build-and-push.sh # Build operator image, push to AR
129-
│ ├── deploy-operator.sh # Helm install from local chart
130-
│ ├── deploy-baseline.sh # Helm install released version
131-
│ ├── deploy-test-workload.sh # Deploy nginx for scanning
132-
│ ├── apply-mondoo-config.sh # Create secret + apply MondooAuditConfig
133-
│ ├── verify.sh # Automated checks + manual verification pause
134-
│ └── cleanup.sh # Remove all test resources from cluster
160+
│ ├── common.sh # Logging, TF output loading, wait helpers
161+
│ ├── build-and-push.sh # Build operator image, push to AR
162+
│ ├── deploy-operator.sh # Helm install from local chart
163+
│ ├── deploy-operator-mirroring.sh # Helm install with mirror/proxy values
164+
│ ├── deploy-baseline.sh # Helm install released version
165+
│ ├── deploy-test-workload.sh # Deploy nginx for scanning
166+
│ ├── apply-mondoo-config.sh # Create secret + apply MondooAuditConfig
167+
│ ├── setup-mirror-registry.sh # Create imagePullSecret for mirror AR repo
168+
│ ├── populate-mirror-registry.sh # Copy cnspec image into mirror AR repo via crane
169+
│ ├── verify.sh # Automated checks + manual verification pause
170+
│ ├── verify-mirroring.sh # Mirroring/proxy-specific verification
171+
│ └── cleanup.sh # Remove all test resources from cluster
135172
└── manifests/
136173
├── mondoo-audit-config.yaml.tpl # Standard cluster config (nodes enabled)
137174
├── mondoo-audit-config-autopilot.yaml.tpl # Autopilot config (nodes disabled)
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
#!/usr/bin/env bash
2+
# Copyright Mondoo, Inc. 2026
3+
# SPDX-License-Identifier: BUSL-1.1
4+
5+
# Test: Registry Mirroring, imagePullSecrets & Proxy
6+
# Builds operator, deploys with AR-based mirror registry and optional proxy,
7+
# verifies image references, pull secrets, and proxy configuration.
8+
#
9+
# Prerequisites:
10+
# - Terraform infrastructure provisioned with enable_mirror_test=true
11+
# - crane CLI installed (go install github.com/google/go-containerregistry/cmd/crane@latest)
12+
# - gcloud authenticated, docker, helm, kubectl available
13+
# - For proxy testing: also set enable_proxy_test=true in terraform
14+
#
15+
# Usage:
16+
# ./run-registry-mirroring.sh
17+
18+
set -euo pipefail
19+
20+
E2E_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
21+
source "${E2E_ROOT}/scripts/common.sh"
22+
23+
info "=========================================="
24+
info " Test: Registry Mirroring & Proxy"
25+
info "=========================================="
26+
27+
# Step 1: Load Terraform outputs (includes mirror and proxy outputs)
28+
load_tf_outputs
29+
30+
# Validate that mirror test infra is provisioned
31+
if [[ "${ENABLE_MIRROR_TEST}" != "true" ]]; then
32+
die "This test requires enable_mirror_test=true in Terraform. Run: terraform apply -var='enable_mirror_test=true'"
33+
fi
34+
35+
# Step 2: Build and push operator image
36+
info "--- Step: Build and Push ---"
37+
source "${E2E_ROOT}/scripts/build-and-push.sh"
38+
39+
# Step 3: Create imagePullSecret for mirror AR repo
40+
info "--- Step: Setup Mirror Registry Credentials ---"
41+
source "${E2E_ROOT}/scripts/setup-mirror-registry.sh"
42+
43+
# Step 4: Populate mirror AR repo with cnspec image
44+
info "--- Step: Populate Mirror Registry ---"
45+
source "${E2E_ROOT}/scripts/populate-mirror-registry.sh"
46+
47+
# Step 5: Deploy test workload
48+
info "--- Step: Deploy Test Workload ---"
49+
source "${E2E_ROOT}/scripts/deploy-test-workload.sh"
50+
51+
# Step 6: Set proxy env vars from Terraform if enabled
52+
if [[ "${ENABLE_PROXY_TEST}" == "true" ]]; then
53+
info "Proxy testing enabled — Squid proxy at ${SQUID_PROXY_IP}"
54+
else
55+
info "Proxy testing disabled — skipping proxy configuration"
56+
fi
57+
58+
# Step 7: Deploy operator with mirroring/proxy configuration
59+
info "--- Step: Deploy Operator with Mirroring ---"
60+
source "${E2E_ROOT}/scripts/deploy-operator-mirroring.sh"
61+
62+
# Step 8: Apply MondooAuditConfig
63+
info "--- Step: Apply Mondoo Config ---"
64+
source "${E2E_ROOT}/scripts/apply-mondoo-config.sh"
65+
66+
# Step 9: Wait for operator to reconcile
67+
info "Waiting 90s for operator to reconcile with mirrored images..."
68+
sleep 90
69+
70+
# Step 10: Standard verification
71+
info "--- Step: Standard Verify ---"
72+
source "${E2E_ROOT}/scripts/verify.sh"
73+
74+
# Step 11: Mirroring-specific verification
75+
info "--- Step: Verify Mirroring & Proxy ---"
76+
source "${E2E_ROOT}/scripts/verify-mirroring.sh"
77+
78+
info ""
79+
info "=========================================="
80+
info " Test: Registry Mirroring & Proxy - COMPLETE"
81+
info "=========================================="

tests/e2e/scripts/cleanup.sh

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,4 +66,8 @@ fi
6666
info "Removing mondoo Helm repo..."
6767
helm repo remove mondoo 2>/dev/null || true
6868

69+
# Mirror registry resources (from registry mirroring tests)
70+
info "Deleting mirror-registry-creds secret..."
71+
kubectl delete secret mirror-registry-creds -n "${NAMESPACE}" --ignore-not-found
72+
6973
info "=== Cleanup complete ==="

tests/e2e/scripts/common.sh

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,17 @@ load_tf_outputs() {
4343
export TARGET_KUBECONFIG_PATH="$(cd "${TF_DIR}" && realpath "$(terraform output -raw target_kubeconfig_path)")"
4444
fi
4545

46+
export ENABLE_MIRROR_TEST="$(terraform output -raw enable_mirror_test 2>/dev/null || echo "false")"
47+
if [[ "${ENABLE_MIRROR_TEST}" == "true" ]]; then
48+
export MIRROR_REGISTRY="$(terraform output -raw mirror_registry_repo)"
49+
export MIRROR_SA_KEY_B64="$(terraform output -raw mirror_sa_key_b64)"
50+
fi
51+
52+
export ENABLE_PROXY_TEST="$(terraform output -raw enable_proxy_test 2>/dev/null || echo "false")"
53+
if [[ "${ENABLE_PROXY_TEST}" == "true" ]]; then
54+
export SQUID_PROXY_IP="$(terraform output -raw squid_proxy_ip)"
55+
fi
56+
4657
cd ->/dev/null
4758

4859
# Use gcloud to get cluster credentials (auto-refreshing auth)
Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
#!/usr/bin/env bash
2+
# Copyright Mondoo, Inc. 2026
3+
# SPDX-License-Identifier: BUSL-1.1
4+
5+
# Deploy the operator from the local Helm chart with mirror/proxy configuration
6+
# Uses a values-override file to avoid Helm --set escaping issues with dots in keys
7+
8+
set -euo pipefail
9+
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
10+
source "${SCRIPT_DIR}/common.sh"
11+
12+
: "${IMAGE_REPO:?IMAGE_REPO must be set}"
13+
: "${IMAGE_TAG:?IMAGE_TAG must be set}"
14+
: "${NAMESPACE:?NAMESPACE must be set}"
15+
: "${MIRROR_REGISTRY:?MIRROR_REGISTRY must be set}"
16+
17+
# Proxy settings (optional)
18+
SQUID_PROXY_IP="${SQUID_PROXY_IP:-}"
19+
20+
info "Deploying operator with mirroring configuration..."
21+
info " Mirror registry: ${MIRROR_REGISTRY}"
22+
if [[ -n "${SQUID_PROXY_IP}" ]]; then
23+
info " Proxy: http://${SQUID_PROXY_IP}:3128"
24+
fi
25+
26+
# Build proxy values
27+
PROXY_HTTP=""
28+
PROXY_HTTPS=""
29+
PROXY_NO=""
30+
PROXY_CONTAINER=""
31+
if [[ -n "${SQUID_PROXY_IP}" ]]; then
32+
PROXY_HTTP="http://${SQUID_PROXY_IP}:3128"
33+
PROXY_HTTPS="http://${SQUID_PROXY_IP}:3128"
34+
PROXY_CONTAINER="http://${SQUID_PROXY_IP}:3128"
35+
36+
# Get both the external and in-cluster Kubernetes API server IPs.
37+
# External: from kubeconfig (used by kubectl from outside)
38+
# Internal: the kubernetes.default ClusterIP (used by pods via KUBERNETES_SERVICE_HOST)
39+
K8S_API_EXTERNAL=$(kubectl config view --minify -o jsonpath='{.clusters[0].cluster.server}' | sed -E 's|https?://||;s|:[0-9]+$||')
40+
K8S_API_INTERNAL=$(kubectl get svc kubernetes -n default -o jsonpath='{.spec.clusterIP}')
41+
info "Kubernetes API server IPs: external=${K8S_API_EXTERNAL}, internal=${K8S_API_INTERNAL}"
42+
PROXY_NO="10.0.0.0/8,172.16.0.0/12,.cluster.local,.svc,localhost,127.0.0.1,${K8S_API_EXTERNAL},${K8S_API_INTERNAL}"
43+
fi
44+
45+
# Generate values override file
46+
# Using a file avoids Helm --set escaping issues with dots in registry mirror keys
47+
VALUES_FILE=$(mktemp /tmp/mondoo-mirror-values-XXXXXX.yaml)
48+
trap "rm -f ${VALUES_FILE}" EXIT
49+
50+
cat > "${VALUES_FILE}" <<EOF
51+
operator:
52+
skipContainerResolution: true
53+
registryMirrors:
54+
ghcr.io: "${MIRROR_REGISTRY}"
55+
imagePullSecrets:
56+
- name: mirror-registry-creds
57+
httpProxy: "${PROXY_HTTP}"
58+
httpsProxy: "${PROXY_HTTPS}"
59+
noProxy: "${PROXY_NO}"
60+
containerProxy: "${PROXY_CONTAINER}"
61+
EOF
62+
63+
info "Generated values override:"
64+
cat "${VALUES_FILE}"
65+
66+
# Adopt any existing Mondoo CRDs so Helm can manage them
67+
for crd in $(kubectl get crds -o name 2>/dev/null | grep mondoo || true); do
68+
info "Adopting existing CRD for Helm: ${crd}"
69+
kubectl label "${crd}" app.kubernetes.io/managed-by=Helm --overwrite
70+
kubectl annotate "${crd}" meta.helm.sh/release-name=mondoo-operator meta.helm.sh/release-namespace="${NAMESPACE}" --overwrite
71+
done
72+
73+
helm upgrade --install mondoo-operator "${REPO_ROOT}/charts/mondoo-operator" \
74+
--namespace "${NAMESPACE}" --create-namespace \
75+
--set controllerManager.manager.image.repository="${IMAGE_REPO}" \
76+
--set controllerManager.manager.image.tag="${IMAGE_TAG}" \
77+
--set controllerManager.manager.imagePullPolicy=Always \
78+
--values "${VALUES_FILE}" \
79+
--wait --timeout 5m
80+
81+
wait_for_deployment "${NAMESPACE}" "mondoo-operator-controller-manager"
82+
83+
info "Operator deployed with mirroring configuration."
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
#!/usr/bin/env bash
2+
# Copyright Mondoo, Inc. 2026
3+
# SPDX-License-Identifier: BUSL-1.1
4+
5+
# Copy cnspec image from ghcr.io into the mirror Artifact Registry repo.
6+
# Uses crane locally with gcloud auth (caller is already authenticated to GCP).
7+
#
8+
# The operator image is pulled directly from the main AR repo (set via Helm
9+
# --set values) and does NOT go through the mirror. Only images the operator
10+
# spawns (cnspec) get resolved through registryMirrors.
11+
12+
set -euo pipefail
13+
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
14+
source "${SCRIPT_DIR}/common.sh"
15+
16+
: "${MIRROR_REGISTRY:?MIRROR_REGISTRY must be set}"
17+
: "${REGION:?REGION must be set}"
18+
19+
# cnspec image constants (must match pkg/utils/mondoo/container_image_resolver.go)
20+
CNSPEC_IMAGE="ghcr.io/mondoohq/mondoo-operator/cnspec"
21+
CNSPEC_TAG="12-rootless"
22+
23+
CNSPEC_SRC="${CNSPEC_IMAGE}:${CNSPEC_TAG}"
24+
# Mirror path preserves the ghcr.io path structure so registryMirrors mapping works:
25+
# ghcr.io/mondoohq/mondoo-operator/cnspec:tag -> MIRROR_REGISTRY/mondoohq/mondoo-operator/cnspec:tag
26+
CNSPEC_MIRROR="${MIRROR_REGISTRY}/mondoohq/mondoo-operator/cnspec:${CNSPEC_TAG}"
27+
28+
info "Populating mirror registry..."
29+
info " cnspec: ${CNSPEC_SRC} -> ${CNSPEC_MIRROR}"
30+
31+
# Verify crane is available
32+
if ! command -v crane &>/dev/null; then
33+
die "crane CLI is required. Install with: go install github.com/google/go-containerregistry/cmd/crane@latest"
34+
fi
35+
36+
# Configure crane auth for the mirror AR repo (uses gcloud credentials)
37+
info "Configuring crane auth for Artifact Registry..."
38+
crane auth login "${REGION}-docker.pkg.dev" -u oauth2accesstoken -p "$(gcloud auth print-access-token)"
39+
40+
# Copy cnspec image from ghcr.io (public) to mirror AR repo
41+
info "Copying cnspec image to mirror..."
42+
crane copy "${CNSPEC_SRC}" "${CNSPEC_MIRROR}"
43+
44+
info "Mirror registry populated successfully."
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
#!/usr/bin/env bash
2+
# Copyright Mondoo, Inc. 2026
3+
# SPDX-License-Identifier: BUSL-1.1
4+
5+
# Create the imagePullSecret for the mirror Artifact Registry repo.
6+
# The mirror AR repo and a read-only service account are provisioned by Terraform.
7+
8+
set -euo pipefail
9+
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
10+
source "${SCRIPT_DIR}/common.sh"
11+
12+
: "${NAMESPACE:?NAMESPACE must be set}"
13+
: "${MIRROR_REGISTRY:?MIRROR_REGISTRY must be set}"
14+
: "${MIRROR_SA_KEY_B64:?MIRROR_SA_KEY_B64 must be set}"
15+
: "${REGION:?REGION must be set}"
16+
17+
info "Setting up mirror registry credentials..."
18+
19+
# The mirror AR repo URL is REGION-docker.pkg.dev, extract the server
20+
MIRROR_SERVER="${REGION}-docker.pkg.dev"
21+
22+
# Decode the GCP SA key (Terraform outputs it as base64)
23+
SA_KEY_JSON=$(echo "${MIRROR_SA_KEY_B64}" | base64 -d)
24+
25+
# Create docker-registry secret in operator namespace for imagePullSecrets
26+
info "Creating mirror-registry-creds secret in ${NAMESPACE}..."
27+
kubectl create namespace "${NAMESPACE}" --dry-run=client -o yaml | kubectl apply -f -
28+
kubectl create secret docker-registry mirror-registry-creds \
29+
--namespace "${NAMESPACE}" \
30+
--docker-server="${MIRROR_SERVER}" \
31+
--docker-username="_json_key" \
32+
--docker-password="${SA_KEY_JSON}" \
33+
--dry-run=client -o yaml | kubectl apply -f -
34+
35+
info "Mirror registry credentials created for ${MIRROR_SERVER}"

0 commit comments

Comments
 (0)