#!/usr/bin/env bash set -Eeuo pipefail ROOT="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")/../.." && pwd -P)" RENDERER="$ROOT/scripts/validate/render-observability-access.sh" # The renderer is intentionally sourced: these tests exercise the same parser and # manifest assertions used by executable rendering, without downloading charts or # contacting a Kubernetes API server. source "$RENDERER" ASSERTIONS=0 WORK='' PUBLISH_ROOTS=() cleanup() { local rc=$? trap - EXIT HUP INT TERM if [[ -n "$WORK" && "$WORK" == /tmp/platform-observability-access-test.* && -d "$WORK" && ! -L "$WORK" ]]; then rm -rf -- "$WORK" fi local publish_root for publish_root in "${PUBLISH_ROOTS[@]}"; do if [[ "$publish_root" == /tmp/platform-observability-metrics.?????? && -d "$publish_root" && ! -L "$publish_root" ]]; then rm -rf -- "$publish_root" fi done exit "$rc" } trap cleanup EXIT HUP INT TERM pass() { ASSERTIONS=$((ASSERTIONS + 1)) printf 'PASS: %s\n' "$1" } expect_pass() { local label="$1" shift if "$@" >/dev/null 2>&1; then pass "$label" else printf 'FAIL: expected success: %s\n' "$label" >&2 exit 1 fi } expect_fail() { local label="$1" shift if "$@" >/dev/null 2>&1; then printf 'FAIL: expected rejection: %s\n' "$label" >&2 exit 1 fi pass "$label" } expect_output() { local label="$1" expected="$2" shift 2 local actual actual="$($@)" || { printf 'FAIL: output command failed: %s\n' "$label" >&2 exit 1 } if [[ "$actual" != "$expected" ]]; then printf 'FAIL: unexpected output: %s\nexpected:\n%s\nactual:\n%s\n' \ "$label" "$expected" "$actual" >&2 exit 1 fi pass "$label" } mutate_yaml() { local source="$1" destination="$2" mutation="$3" python3 - "$source" "$destination" "$mutation" <<'PY' import sys import yaml class FixtureLoader(yaml.SafeLoader): pass FixtureLoader.add_constructor( "tag:yaml.org,2002:value", lambda loader, node: loader.construct_scalar(node), ) source, destination, mutation = sys.argv[1:] with open(source, "r", encoding="utf-8") as stream: items = [item for item in yaml.load_all(stream, Loader=FixtureLoader) if item is not None] def object_named(kind, name): matches = [ item for item in items if item.get("kind") == kind and (item.get("metadata") or {}).get("name") == name ] if len(matches) != 1: raise SystemExit(f"fixture object is not exact: {kind}/{name}") return matches[0] if mutation == "grafana-public-service": object_named("Service", "grafana")["spec"]["type"] = "LoadBalancer" elif mutation == "grafana-missing-class": object_named("Ingress", "grafana")["spec"].pop("ingressClassName", None) elif mutation == "grafana-main-token": deployment = object_named("Deployment", "grafana") main = next(c for c in deployment["spec"]["template"]["spec"]["containers"] if c["name"] == "grafana") main.setdefault("volumeMounts", []).append({ "name": "dashboard-sidecar-api-access", "mountPath": "/var/run/secrets/kubernetes.io/serviceaccount", "readOnly": True, }) elif mutation == "grafana-cluster-role": role = object_named("Role", "grafana-dashboard-sidecar") role["kind"] = "ClusterRole" role["metadata"].pop("namespace", None) elif mutation == "oidc-viewer-fallback": config = object_named("ConfigMap", "grafana") config["data"]["grafana.ini"] = config["data"]["grafana.ini"].replace("|| null", "|| 'Viewer'") elif mutation == "oidc-editor": config = object_named("ConfigMap", "grafana") config["data"]["grafana.ini"] = config["data"]["grafana.ini"].replace("&& 'Viewer'", "&& 'Editor'") elif mutation == "oidc-grafana-admin": config = object_named("ConfigMap", "grafana") config["data"]["grafana.ini"] = config["data"]["grafana.ini"].replace( "allow_assign_grafana_admin = false", "allow_assign_grafana_admin = true" ) elif mutation == "oidc-group-missing": config = object_named("ConfigMap", "grafana") config["data"]["grafana.ini"] = config["data"]["grafana.ini"].replace( "/platform-observability-viewers", "/not-authorized" ) elif mutation == "blackbox-arbitrary-target": probe = object_named("Probe", "platform-public-edge") probe["spec"]["targets"]["staticConfig"]["static"].append("https://example.invalid/") elif mutation == "blackbox-public-service": object_named("Service", "blackbox-exporter")["spec"]["type"] = "NodePort" elif mutation == "missing-instance-label": object_named("Probe", "platform-public-edge")["metadata"]["labels"].pop( "observability.hyeonworks.com/instance", None ) elif mutation == "outside-target": items.append({ "apiVersion": "monitoring.coreos.com/v1", "kind": "ServiceMonitor", "metadata": { "name": "rabbitmq", "namespace": "messaging", "labels": {"observability.hyeonworks.com/instance": "home"}, }, "spec": {"selector": {"matchLabels": {"app": "rabbitmq"}}, "endpoints": [{"port": "metrics"}]}, }) elif mutation == "forbidden-product": items.append({ "apiVersion": "monitoring.coreos.com/v1", "kind": "PrometheusRule", "metadata": { "name": "platform-jvm", "namespace": "observability", "labels": {"observability.hyeonworks.com/instance": "home"}, }, "spec": {"groups": [{"name": "jvm", "rules": [{"alert": "JVMHeapHigh", "expr": "vector(0)"}]}]}, }) elif mutation == "alertmanager-inline-secret": items.append({ "apiVersion": "v1", "kind": "Secret", "metadata": {"name": "inline-fixture", "namespace": "observability"}, "type": "Opaque", "stringData": {"password": "forbidden-fixture-value"}, }) elif mutation == "alertmanager-missing-title": config = object_named("AlertmanagerConfig", "platform-alertmanager") receiver = next( receiver for receiver in config["spec"]["receivers"] if receiver["name"] == "platform-slack" ) receiver["slackConfigs"][0].pop("title") elif mutation == "dns-public-address": config = object_named("ConfigMap", "coredns-custom") config["data"]["learn-hyeonworks.server"] = config["data"]["learn-hyeonworks.server"].replace( "192.168.0.107 grafana.learn.hyeonworks.com", "203.0.113.10 grafana.learn.hyeonworks.com", ) elif mutation == "grafana-broad-policy": policy = object_named("NetworkPolicy", "observability-allow-grafana-ingress") policy["spec"] = {"podSelector": {}, "policyTypes": ["Ingress"], "ingress": [{}]} elif mutation == "blackbox-broad-egress": policy = object_named("NetworkPolicy", "observability-allow-blackbox-egress") policy["spec"] = {"podSelector": {}, "policyTypes": ["Egress"], "egress": [{}]} elif mutation == "targets-broad-egress": policy = object_named("NetworkPolicy", "observability-allow-prometheus-platform-targets") policy["spec"] = {"podSelector": {}, "policyTypes": ["Egress"], "egress": [{}]} elif mutation == "grafana-extra-allow-all": items.append({ "apiVersion": "networking.k8s.io/v1", "kind": "NetworkPolicy", "metadata": {"name": "observability-extra-grafana-allow-all", "namespace": "observability"}, "spec": { "podSelector": {"matchLabels": { "app.kubernetes.io/name": "grafana", "app.kubernetes.io/instance": "grafana", }}, "policyTypes": ["Ingress", "Egress"], "ingress": [{}], "egress": [{}], }, }) elif mutation == "blackbox-extra-allow-all": items.append({ "apiVersion": "networking.k8s.io/v1", "kind": "NetworkPolicy", "metadata": {"name": "observability-extra-blackbox-allow-all", "namespace": "observability"}, "spec": { "podSelector": {"matchLabels": { "app.kubernetes.io/name": "prometheus-blackbox-exporter", "app.kubernetes.io/instance": "blackbox-exporter", }}, "policyTypes": ["Ingress", "Egress"], "ingress": [{}], "egress": [{}], }, }) elif mutation == "targets-extra-allow-all": items.append({ "apiVersion": "networking.k8s.io/v1", "kind": "NetworkPolicy", "metadata": {"name": "observability-extra-prometheus-allow-all", "namespace": "observability"}, "spec": { "podSelector": {"matchLabels": { "app.kubernetes.io/name": "prometheus", "app.kubernetes.io/instance": "observability-core-kube-pr-prometheus", }}, "policyTypes": ["Egress"], "egress": [{}], }, }) elif mutation == "alertmanager-extra-allow-all": items.append({ "apiVersion": "networking.k8s.io/v1", "kind": "NetworkPolicy", "metadata": {"name": "observability-extra-alertmanager-allow-all", "namespace": "observability"}, "spec": { "podSelector": {"matchLabels": { "app.kubernetes.io/name": "alertmanager", "app.kubernetes.io/instance": "observability-core-kube-pr-alertmanager", }}, "policyTypes": ["Egress"], "egress": [{}], }, }) else: raise SystemExit(f"unknown mutation: {mutation}") with open(destination, "w", encoding="utf-8") as stream: yaml.safe_dump_all(items, stream, explicit_start=True, sort_keys=False) PY } write_inventory_phase() { local root="$1" phase="$2" pool="$3" provenance="$4" metric="$5" local directory="$root/$phase" hash mkdir -m 0700 -- "$directory" printf '%s\n' \ '{' \ ' "schema": "platform-observability-metric-inventory/v1",' \ " \"phase\": \"$phase\"," \ ' "captured_at_utc": "2026-08-12T00:00:00Z",' \ ' "context": "default",' \ ' "api_server": "https://127.0.0.1:6443",' \ ' "prometheus": "observability/observability-core-kube-pr-prometheus",' \ ' "preexisting_verify_only": ["grafana"],' \ ' "targets": [' \ ' {' \ " \"scrape_pool\": \"$pool\"," \ ' "scrape_url": "http://127.0.0.1:9090/metrics",' \ ' "health": "up",' \ ' "last_error": "",' \ " \"provenance\": \"$provenance\"," \ " \"metrics\": [{\"name\": \"$metric\", \"label_names\": [\"__name__\", \"instance\", \"namespace\"]}]" \ ' }' \ ' ]' \ '}' >"$directory/inventory.json" chmod 0600 "$directory/inventory.json" hash="$(sha256sum "$directory/inventory.json" | awk '{print $1}')" printf '%s inventory.json\n' "$hash" >"$directory/inventory.sha256" chmod 0600 "$directory/inventory.sha256" } make_publish_root() { local root root="$(mktemp -d /tmp/platform-observability-metrics.XXXXXX)" chmod 0700 "$root" PUBLISH_ROOTS+=("$root") write_inventory_phase "$root" target-initial \ serviceMonitor/observability/grafana/0 preexisting-verify-only up write_inventory_phase "$root" post-substrate \ probe/observability/platform-public-edge substrate-owned probe_success PUBLISH_ROOT=$root } publication_tree_fingerprint() { local root=$1 python3 - "$root" <<'PY' import hashlib import os import stat import sys root = sys.argv[1] records = [] def record(path, relative): metadata = os.lstat(path) content_hash = "-" if stat.S_ISREG(metadata.st_mode): descriptor = os.open(path, os.O_RDONLY | os.O_NOFOLLOW) try: digest = hashlib.sha256() while True: chunk = os.read(descriptor, 1024 * 1024) if not chunk: break digest.update(chunk) content_hash = digest.hexdigest() finally: os.close(descriptor) records.append("|".join(( relative, str(metadata.st_dev), str(metadata.st_ino), oct(stat.S_IFMT(metadata.st_mode)), oct(stat.S_IMODE(metadata.st_mode)), str(metadata.st_uid), str(metadata.st_gid), str(metadata.st_nlink), str(metadata.st_size), str(metadata.st_mtime_ns), str(metadata.st_ctime_ns), content_hash, ))) if stat.S_ISDIR(metadata.st_mode): with os.scandir(path) as entries: for entry in sorted(entries, key=lambda item: item.name): child_relative = entry.name if relative == "." else f"{relative}/{entry.name}" record(entry.path, child_relative) record(root, ".") print(hashlib.sha256("\0".join(records).encode()).hexdigest()) PY } make_inventory_only_clone() { local source=$1 root phase name root="$(mktemp -d /tmp/platform-observability-metrics.XXXXXX)" chmod 0700 "$root" PUBLISH_ROOTS+=("$root") for phase in target-initial post-substrate; do mkdir -m 0700 -- "$root/$phase" for name in inventory.json inventory.sha256; do cp --no-dereference --reflink=never -- \ "$source/$phase/$name" "$root/$phase/$name" chmod 0600 "$root/$phase/$name" done done PUBLISH_ROOT=$root } inventory_clone_matches_source() { local source=$1 clone=$2 phase name uid uid=$(id -u) for phase in target-initial post-substrate; do [[ -d "$source/$phase" && ! -L "$source/$phase" ]] || return 1 [[ -d "$clone/$phase" && ! -L "$clone/$phase" ]] || return 1 [[ "$(stat -c '%u|%a' -- "$source/$phase")" == "$uid|700" ]] || return 1 [[ "$(stat -c '%u|%a' -- "$clone/$phase")" == "$uid|700" ]] || return 1 for name in inventory.json inventory.sha256; do [[ -f "$source/$phase/$name" && ! -L "$source/$phase/$name" ]] || return 1 [[ -f "$clone/$phase/$name" && ! -L "$clone/$phase/$name" ]] || return 1 [[ "$(stat -c '%u|%a|%h' -- "$source/$phase/$name")" == "$uid|600|1" ]] || return 1 [[ "$(stat -c '%u|%a|%h' -- "$clone/$phase/$name")" == "$uid|600|1" ]] || return 1 cmp -s "$source/$phase/$name" "$clone/$phase/$name" || return 1 done done } published_complete_exact() { local root=$1 source=$2 name uid local expected_root expected_source expected_root=$'alertmanager.yaml\nblackbox.yaml\ndashboards.yaml\ngrafana.yaml\npost-substrate\nprivate-dns.yaml\nrules.yaml\ntarget-initial\ntargets.yaml' expected_source=$'alertmanager.yaml\nblackbox.yaml\ndashboards.yaml\ngrafana.yaml\nprivate-dns.yaml\nrules.yaml\ntargets.yaml' [[ "$(find "$root" -mindepth 1 -maxdepth 1 -printf '%f\n' | sort)" == "$expected_root" ]] || return 1 [[ "$(find "$source" -mindepth 1 -maxdepth 1 -printf '%f\n' | sort)" == "$expected_source" ]] || return 1 uid=$(id -u) for name in \ grafana.yaml blackbox.yaml targets.yaml dashboards.yaml rules.yaml alertmanager.yaml private-dns.yaml; do [[ -f "$source/$name" && ! -L "$source/$name" ]] || return 1 [[ -f "$root/$name" && ! -L "$root/$name" ]] || return 1 [[ "$(stat -c '%u|%a|%h' -- "$source/$name")" == "$uid|600|1" ]] || return 1 [[ "$(stat -c '%u|%a|%h' -- "$root/$name")" == "$uid|600|1" ]] || return 1 cmp -s "$source/$name" "$root/$name" || return 1 done } published_rules_alerts_exact() { local root=$1 source=$2 name local expected=$'alertmanager.yaml\ndashboards.yaml\npost-substrate\nrules.yaml\ntarget-initial' [[ "$(find "$root" -mindepth 1 -maxdepth 1 -printf '%f\n' | sort)" == "$expected" ]] || return 1 for name in dashboards.yaml rules.yaml alertmanager.yaml; do [[ -f "$root/$name" && ! -L "$root/$name" && "$(stat -c %a -- "$root/$name")" == 600 ]] || return 1 cmp -s "$source/$name" "$root/$name" || return 1 done } collision_left_no_partial_publish() { local root=$1 [[ -f "$root/rules.yaml" && ! -e "$root/dashboards.yaml" && ! -e "$root/alertmanager.yaml" ]] || return 1 } complete_collision_left_no_partial() { local root=$1 uid expected expected=$'post-substrate\nprivate-dns.yaml\ntarget-initial' [[ "$(find "$root" -mindepth 1 -maxdepth 1 -printf '%f\n' | sort)" == "$expected" ]] || return 1 [[ -f "$root/private-dns.yaml" && ! -L "$root/private-dns.yaml" ]] || return 1 uid=$(id -u) [[ "$(stat -c '%u|%a|%h' -- "$root/private-dns.yaml")" == "$uid|600|1" ]] || return 1 [[ "$(<"$root/private-dns.yaml")" == 'preexisting complete collision' ]] } secure_render_context_creates_private_files() { local directory=$1 ( access_secure_render_context printf '%s\n' rendered >"$directory/rendered.yaml" ) || return 1 [[ "$(stat -c %a -- "$directory/rendered.yaml")" == 600 ]] } WORK="$(mktemp -d /tmp/platform-observability-access-test.XXXXXX)" chmod 0700 "$WORK" grafana="$WORK/grafana.yaml" cat >"$grafana" <<'YAML' apiVersion: rbac.authorization.k8s.io/v1 kind: Role metadata: name: grafana-dashboard-sidecar namespace: observability rules: - apiGroups: [""] resources: [configmaps] verbs: [list, watch] --- apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: name: grafana-dashboard-sidecar namespace: observability roleRef: apiGroup: rbac.authorization.k8s.io kind: Role name: grafana-dashboard-sidecar subjects: - kind: ServiceAccount name: grafana namespace: observability --- apiVersion: v1 kind: ConfigMap metadata: name: grafana namespace: observability data: grafana.ini: | [auth] login_maximum_lifetime_duration = 8h login_maximum_inactive_lifetime_duration = 30m [auth.anonymous] enabled = false [auth.generic_oauth] enabled = true scopes = openid profile email groups_attribute_path = groups allowed_groups = /platform-observability-admins /platform-observability-viewers role_attribute_strict = true allow_assign_grafana_admin = false role_attribute_path = contains(groups[*], '/platform-observability-admins') && 'Admin' || contains(groups[*], '/platform-observability-viewers') && 'Viewer' || null auth_url = https://id.learn.hyeonworks.com/realms/hyeonworks/protocol/openid-connect/auth token_url = https://id.learn.hyeonworks.com/realms/hyeonworks/protocol/openid-connect/token api_url = https://id.learn.hyeonworks.com/realms/hyeonworks/protocol/openid-connect/userinfo signout_redirect_url = https://id.learn.hyeonworks.com/realms/hyeonworks/protocol/openid-connect/logout --- apiVersion: v1 kind: Service metadata: name: grafana namespace: observability spec: type: ClusterIP selector: app.kubernetes.io/name: grafana app.kubernetes.io/instance: grafana ports: - name: service port: 80 targetPort: grafana --- apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: grafana namespace: observability spec: ingressClassName: traefik rules: - host: grafana.learn.hyeonworks.com http: paths: - path: / pathType: Prefix backend: service: name: grafana port: number: 80 --- apiVersion: apps/v1 kind: Deployment metadata: name: grafana namespace: observability spec: strategy: type: Recreate template: metadata: labels: app.kubernetes.io/name: grafana app.kubernetes.io/instance: grafana spec: automountServiceAccountToken: false serviceAccountName: grafana containers: - name: grafana-sc-dashboard image: quay.io/kiwigrid/k8s-sidecar:2.10.0@sha256:129877c81acf2bc8c3fa000e89a62e020eb89d41ceb94767c657aef5bb0cc0d3 volumeMounts: - name: dashboard-sidecar-api-access mountPath: /var/run/secrets/kubernetes.io/serviceaccount readOnly: true - name: grafana image: docker.io/grafana/grafana:13.1.1@sha256:f33c692ba1a5ee15724cf6b22db65e9de39dde14d80f7d73a9546e3fc917270b env: - name: GF_SECURITY_ADMIN_PASSWORD valueFrom: secretKeyRef: name: grafana-admin key: admin-password - name: GF_AUTH_GENERIC_OAUTH_CLIENT_SECRET valueFrom: secretKeyRef: name: grafana-keycloak-oidc key: client-secret volumes: - name: dashboard-sidecar-api-access projected: defaultMode: 420 sources: - serviceAccountToken: expirationSeconds: 3600 path: token - configMap: name: kube-root-ca.crt items: - key: ca.crt path: ca.crt - downwardAPI: items: - path: namespace fieldRef: apiVersion: v1 fieldPath: metadata.namespace --- apiVersion: monitoring.coreos.com/v1 kind: ServiceMonitor metadata: name: grafana namespace: observability labels: observability.hyeonworks.com/instance: home spec: selector: matchLabels: app.kubernetes.io/name: grafana app.kubernetes.io/instance: grafana endpoints: - port: service path: /metrics YAML kubectl kustomize "$ROOT/services/observability/network-policies" >"$WORK/core-policies.yaml" blackbox="$WORK/blackbox.yaml" cat >"$blackbox" <<'YAML' apiVersion: v1 kind: Service metadata: name: blackbox-exporter namespace: observability spec: type: ClusterIP selector: app.kubernetes.io/name: prometheus-blackbox-exporter app.kubernetes.io/instance: blackbox-exporter ports: - name: http port: 9115 --- apiVersion: apps/v1 kind: Deployment metadata: name: blackbox-exporter namespace: observability spec: strategy: type: Recreate template: metadata: labels: app.kubernetes.io/name: prometheus-blackbox-exporter app.kubernetes.io/instance: blackbox-exporter spec: automountServiceAccountToken: false containers: - name: blackbox-exporter image: quay.io/prometheus/blackbox-exporter:v0.28.0@sha256:43027b43fb785b7c5adc53bd3b5dbc1a258270a2e8aff24f477b45c4e38dac68 --- apiVersion: monitoring.coreos.com/v1 kind: ServiceMonitor metadata: name: blackbox-exporter namespace: observability labels: observability.hyeonworks.com/instance: home spec: selector: matchLabels: app.kubernetes.io/name: prometheus-blackbox-exporter app.kubernetes.io/instance: blackbox-exporter endpoints: - port: http path: /metrics --- apiVersion: monitoring.coreos.com/v1 kind: Probe metadata: name: platform-public-edge namespace: observability labels: observability.hyeonworks.com/instance: home spec: jobName: blackbox-public-edge module: http_2xx prober: url: blackbox-exporter.observability.svc.cluster.local:9115 scheme: http path: /probe proxyFromEnvironment: false targets: staticConfig: labels: observability.hyeonworks.com/probe-group: public-edge static: - https://git.learn.hyeonworks.com/api/healthz - https://id.learn.hyeonworks.com/realms/hyeonworks/.well-known/openid-configuration --- apiVersion: monitoring.coreos.com/v1 kind: Probe metadata: name: platform-private-edge namespace: observability labels: observability.hyeonworks.com/instance: home spec: jobName: blackbox-private-edge module: http_private_edge_403 prober: url: blackbox-exporter.observability.svc.cluster.local:9115 scheme: http path: /probe proxyFromEnvironment: false targets: staticConfig: labels: observability.hyeonworks.com/probe-group: private-edge static: - https://grafana.learn.hyeonworks.com/ - https://storage-admin.learn.hyeonworks.com/ - https://db-admin.learn.hyeonworks.com/ --- apiVersion: monitoring.coreos.com/v1 kind: Probe metadata: name: platform-private-internal namespace: observability labels: observability.hyeonworks.com/instance: home spec: jobName: blackbox-private-internal module: http_private_internal_200 prober: url: blackbox-exporter.observability.svc.cluster.local:9115 scheme: http path: /probe proxyFromEnvironment: false targets: staticConfig: labels: observability.hyeonworks.com/probe-group: private-internal static: - http://grafana.observability.svc.cluster.local/api/health - http://pgadmin.platform-admin.svc.cluster.local/misc/ping - http://minio-aistor-console.object-storage.svc.cluster.local:9090/ relabelingConfigs: - sourceLabels: [__param_target] regex: http://grafana[.]observability[.]svc[.]cluster[.]local/api/health targetLabel: __param_hostname replacement: grafana.learn.hyeonworks.com - sourceLabels: [__param_target] regex: http://pgadmin[.]platform-admin[.]svc[.]cluster[.]local/misc/ping targetLabel: __param_hostname replacement: db-admin.learn.hyeonworks.com - sourceLabels: [__param_target] regex: http://minio-aistor-console[.]object-storage[.]svc[.]cluster[.]local:9090/ targetLabel: __param_hostname replacement: storage-admin.learn.hyeonworks.com --- apiVersion: networking.k8s.io/v1 kind: NetworkPolicy metadata: name: observability-allow-prometheus-to-blackbox namespace: observability spec: podSelector: matchLabels: app.kubernetes.io/name: prometheus-blackbox-exporter app.kubernetes.io/instance: blackbox-exporter policyTypes: [Ingress] ingress: - from: - podSelector: matchLabels: app.kubernetes.io/name: prometheus app.kubernetes.io/instance: observability-core-kube-pr-prometheus ports: - protocol: TCP port: 9115 --- apiVersion: networking.k8s.io/v1 kind: NetworkPolicy metadata: name: observability-allow-blackbox-egress namespace: observability spec: podSelector: matchLabels: app.kubernetes.io/name: prometheus-blackbox-exporter app.kubernetes.io/instance: blackbox-exporter policyTypes: [Egress] egress: - to: - namespaceSelector: matchLabels: kubernetes.io/metadata.name: kube-system podSelector: matchLabels: k8s-app: kube-dns ports: - {protocol: UDP, port: 53} - {protocol: TCP, port: 53} - to: - ipBlock: {cidr: 192.168.0.107/32} ports: - {protocol: TCP, port: 443} - to: - podSelector: matchLabels: app.kubernetes.io/name: grafana app.kubernetes.io/instance: grafana ports: - {protocol: TCP, port: 3000} - to: - namespaceSelector: matchLabels: kubernetes.io/metadata.name: platform-admin podSelector: matchLabels: app.kubernetes.io/name: pgadmin4 app.kubernetes.io/instance: pgadmin ports: - {protocol: TCP, port: 5050} - to: - namespaceSelector: matchLabels: kubernetes.io/metadata.name: object-storage podSelector: matchLabels: aistor.min.io/objectStore: minio-aistor ports: - {protocol: TCP, port: 9090} YAML kubectl kustomize "$ROOT/services/observability/targets" >"$WORK/targets.yaml" kubectl kustomize "$ROOT/services/observability/dashboards/platform" >"$WORK/dashboards.yaml" kubectl kustomize "$ROOT/services/observability/rules/platform" >"$WORK/rules.yaml" cat >"$WORK/alertmanager-base.yaml" <<'YAML' apiVersion: monitoring.coreos.com/v1 kind: Alertmanager metadata: name: observability-core-kube-pr-alertmanager namespace: observability spec: alertmanagerConfiguration: name: platform-alertmanager YAML kubectl kustomize "$ROOT/services/observability/alerting" >"$WORK/alerting.yaml" python3 - "$WORK/alertmanager-base.yaml" "$WORK/alerting.yaml" "$WORK/alertmanager.yaml" <<'PY' import sys import yaml class FixtureLoader(yaml.SafeLoader): pass FixtureLoader.add_constructor( "tag:yaml.org,2002:value", lambda loader, node: loader.construct_scalar(node), ) items = [] for path in sys.argv[1:3]: with open(path, "r", encoding="utf-8") as stream: items.extend(item for item in yaml.load_all(stream, Loader=FixtureLoader) if item is not None) with open(sys.argv[3], "w", encoding="utf-8") as stream: yaml.safe_dump_all(items, stream, explicit_start=True, sort_keys=False) PY kubectl kustomize "$ROOT/infrastructure/networking/private-dns/kubernetes" >"$WORK/private-dns.yaml" kubectl kustomize "$ROOT/infrastructure/networking/traefik/overlays/trust" >"$WORK/traefik-trust.yaml" kubectl kustomize "$ROOT/infrastructure/networking/traefik/overlays/observe" >"$WORK/traefik-observe.yaml" expected_complete=$'grafana.yaml\nblackbox.yaml\ntargets.yaml\ndashboards.yaml\nrules.yaml\nalertmanager.yaml\nprivate-dns.yaml' expect_output 'complete mode has the exact seven access artifacts' "$expected_complete" access_output_names complete expect_output 'grafana mode has one artifact' 'grafana.yaml' access_output_names grafana expect_output 'blackbox mode has one artifact' 'blackbox.yaml' access_output_names blackbox expect_output 'targets mode has one artifact' 'targets.yaml' access_output_names targets expect_output 'rules-alerts mode has three artifacts' $'dashboards.yaml\nrules.yaml\nalertmanager.yaml' access_output_names rules-alerts expect_fail 'unknown component is rejected' access_output_names arbitrary expect_pass 'Grafana private access contract' assert_access_grafana_contract "$grafana" "$WORK/core-policies.yaml" expect_pass 'Grafana and sidecar images are digest pinned' assert_pinned_images "$grafana" mutate_yaml "$WORK/core-policies.yaml" "$WORK/grafana-broad-policy.yaml" grafana-broad-policy expect_fail 'broad Grafana ingress NetworkPolicy is rejected' \ assert_access_grafana_contract "$grafana" "$WORK/grafana-broad-policy.yaml" mutate_yaml "$WORK/core-policies.yaml" "$WORK/grafana-extra-policy.yaml" grafana-extra-allow-all expect_fail 'an extra Grafana allow-all NetworkPolicy is rejected' \ assert_access_grafana_contract "$grafana" "$WORK/grafana-extra-policy.yaml" mutate_yaml "$grafana" "$WORK/grafana-public-service.yaml" grafana-public-service expect_fail 'Grafana public Service is rejected' assert_access_grafana_contract "$WORK/grafana-public-service.yaml" "$WORK/core-policies.yaml" mutate_yaml "$grafana" "$WORK/grafana-missing-class.yaml" grafana-missing-class expect_fail 'Grafana missing ingressClass is rejected' assert_access_grafana_contract "$WORK/grafana-missing-class.yaml" "$WORK/core-policies.yaml" mutate_yaml "$grafana" "$WORK/grafana-main-token.yaml" grafana-main-token expect_fail 'Grafana main container token mount is rejected' assert_access_grafana_contract "$WORK/grafana-main-token.yaml" "$WORK/core-policies.yaml" mutate_yaml "$grafana" "$WORK/grafana-cluster-role.yaml" grafana-cluster-role expect_fail 'cluster-wide dashboard ConfigMap RBAC is rejected' assert_access_grafana_contract "$WORK/grafana-cluster-role.yaml" "$WORK/core-policies.yaml" for mutation in oidc-viewer-fallback oidc-editor oidc-grafana-admin oidc-group-missing; do mutate_yaml "$grafana" "$WORK/$mutation.yaml" "$mutation" expect_fail "Grafana OIDC regression $mutation is rejected" \ assert_access_grafana_contract "$WORK/$mutation.yaml" "$WORK/core-policies.yaml" done sed 's/@sha256:[0-9a-f]\{64\}//g' "$grafana" >"$WORK/grafana-tag-only.yaml" expect_fail 'tag-only Grafana and sidecar images are rejected' assert_pinned_images "$WORK/grafana-tag-only.yaml" expect_pass 'Blackbox fixed target and network contract' assert_access_blackbox_contract "$blackbox" expect_pass 'Blackbox image is digest pinned' assert_pinned_images "$blackbox" mutate_yaml "$blackbox" "$WORK/blackbox-broad-egress.yaml" blackbox-broad-egress expect_fail 'broad Blackbox egress NetworkPolicy is rejected' \ assert_access_blackbox_contract "$WORK/blackbox-broad-egress.yaml" mutate_yaml "$blackbox" "$WORK/blackbox-extra-policy.yaml" blackbox-extra-allow-all expect_fail 'an extra Blackbox allow-all NetworkPolicy is rejected' \ assert_access_blackbox_contract "$WORK/blackbox-extra-policy.yaml" mutate_yaml "$blackbox" "$WORK/blackbox-arbitrary.yaml" blackbox-arbitrary-target expect_fail 'arbitrary Blackbox target is rejected' assert_access_blackbox_contract "$WORK/blackbox-arbitrary.yaml" mutate_yaml "$blackbox" "$WORK/blackbox-public.yaml" blackbox-public-service expect_fail 'public Blackbox Service is rejected' assert_access_blackbox_contract "$WORK/blackbox-public.yaml" sed 's/@sha256:[0-9a-f]\{64\}//g' "$blackbox" >"$WORK/blackbox-tag-only.yaml" expect_fail 'tag-only Blackbox image is rejected' assert_pinned_images "$WORK/blackbox-tag-only.yaml" expect_pass 'target object set and target scope contract' assert_access_targets_contract "$WORK/targets.yaml" mutate_yaml "$WORK/targets.yaml" "$WORK/targets-broad-egress.yaml" targets-broad-egress expect_fail 'broad Prometheus target egress NetworkPolicy is rejected' \ assert_access_targets_contract "$WORK/targets-broad-egress.yaml" mutate_yaml "$WORK/targets.yaml" "$WORK/targets-extra-policy.yaml" targets-extra-allow-all expect_fail 'an extra Prometheus allow-all NetworkPolicy is rejected' \ assert_access_targets_contract "$WORK/targets-extra-policy.yaml" expect_pass 'dashboard/rule/alertmanager contract' assert_access_rules_alerts_contract \ "$WORK/dashboards.yaml" "$WORK/rules.yaml" "$WORK/alertmanager.yaml" alertmanager_source_before="$(publication_tree_fingerprint "$WORK/alertmanager.yaml")" mutate_yaml "$WORK/alertmanager.yaml" "$WORK/alertmanager-missing-title.yaml" alertmanager-missing-title expect_fail 'Alertmanager Slack config without title is rejected' \ assert_access_rules_alerts_contract \ "$WORK/dashboards.yaml" "$WORK/rules.yaml" "$WORK/alertmanager-missing-title.yaml" expect_output 'rejected Alertmanager handoff preserves its canonical source exactly' \ "$alertmanager_source_before" publication_tree_fingerprint "$WORK/alertmanager.yaml" mutate_yaml "$WORK/alertmanager.yaml" "$WORK/alertmanager-extra-policy.yaml" alertmanager-extra-allow-all expect_fail 'an extra Alertmanager allow-all NetworkPolicy is rejected' \ assert_access_rules_alerts_contract \ "$WORK/dashboards.yaml" "$WORK/rules.yaml" "$WORK/alertmanager-extra-policy.yaml" expect_pass 'all monitor/rule instance labels are scoped' assert_access_scope_contract \ "$blackbox" "$WORK/targets.yaml" "$WORK/rules.yaml" mutate_yaml "$blackbox" "$WORK/missing-instance.yaml" missing-instance-label expect_fail 'missing Probe instance label is rejected' assert_access_scope_contract "$WORK/missing-instance.yaml" mutate_yaml "$blackbox" "$WORK/outside-target.yaml" outside-target expect_fail 'out-of-scope platform target is rejected' assert_access_scope_contract "$WORK/outside-target.yaml" mutate_yaml "$WORK/rules.yaml" "$WORK/forbidden-product.yaml" forbidden-product expect_fail 'Spring/JVM/Kafka/batch/backup scope is rejected' assert_access_scope_contract "$WORK/forbidden-product.yaml" mutate_yaml "$WORK/alertmanager.yaml" "$WORK/inline-secret.yaml" alertmanager-inline-secret expect_fail 'inline credential Secret is rejected' assert_no_credentials "$WORK/inline-secret.yaml" expect_pass 'private DNS is exact and private-only' assert_access_private_dns_contract \ "$WORK/private-dns.yaml" \ "$ROOT/infrastructure/networking/private-dns/host/dnsmasq-lan.conf" \ "$ROOT/infrastructure/networking/private-dns/host/dnsmasq-tailscale.conf" mutate_yaml "$WORK/private-dns.yaml" "$WORK/private-dns-public.yaml" dns-public-address expect_fail 'public Grafana DNS address assumption is rejected' assert_access_private_dns_contract \ "$WORK/private-dns-public.yaml" \ "$ROOT/infrastructure/networking/private-dns/host/dnsmasq-lan.conf" \ "$ROOT/infrastructure/networking/private-dns/host/dnsmasq-tailscale.conf" expect_pass 'Traefik trust overlay render is accepted' assert_access_traefik_trust_contract "$WORK/traefik-trust.yaml" expect_fail 'Traefik observe overlay render is rejected' assert_access_traefik_trust_contract "$WORK/traefik-observe.yaml" make_publish_root inventory_root=$PUBLISH_ROOT expect_pass 'both verified inventory phases are accepted' validate_access_inventory_root "$inventory_root" make_publish_root inventory_unsafe_root=$PUBLISH_ROOT chmod 0777 "$inventory_unsafe_root" expect_fail 'world-writable inventory root is rejected' validate_access_inventory_root "$inventory_unsafe_root" make_publish_root inventory_unsafe_phase=$PUBLISH_ROOT chmod 0755 "$inventory_unsafe_phase/post-substrate" expect_fail 'group-readable inventory phase is rejected' validate_access_inventory_root "$inventory_unsafe_phase" make_publish_root inventory_unsafe_file=$PUBLISH_ROOT chmod 0644 "$inventory_unsafe_file/post-substrate/inventory.json" expect_fail 'group-readable inventory file is rejected' validate_access_inventory_root "$inventory_unsafe_file" make_publish_root inventory_hardlink_file=$PUBLISH_ROOT mv -T "$inventory_hardlink_file/post-substrate/inventory.json" "$WORK/shared-inventory.json" ln "$WORK/shared-inventory.json" "$inventory_hardlink_file/post-substrate/inventory.json" expect_fail 'hard-linked inventory file is rejected' validate_access_inventory_root "$inventory_hardlink_file" make_publish_root inventory_bad_checksum=$PUBLISH_ROOT printf '%064d inventory.json\n' 0 >"$inventory_bad_checksum/post-substrate/inventory.sha256" chmod 0600 "$inventory_bad_checksum/post-substrate/inventory.sha256" expect_fail 'inventory checksum drift is rejected' validate_access_inventory_root "$inventory_bad_checksum" make_publish_root inventory_missing_phase=$PUBLISH_ROOT mv -T "$inventory_missing_phase/post-substrate" "$WORK/inventory-missing-phase-saved" expect_fail 'missing post-substrate phase is rejected' validate_access_inventory_root "$inventory_missing_phase" expect_pass 'rules-alerts component requires inventories' access_component_requires_inventory rules-alerts expect_pass 'complete component requires inventories' access_component_requires_inventory complete expect_fail 'grafana component does not accept inventory as a substitute for its source' access_component_requires_inventory grafana expect_pass 'render context creates private files by default' \ secure_render_context_creates_private_files "$WORK" publish_source="$WORK/publish-source" mkdir -m 0700 -- "$publish_source" printf '%s\n' 'kind: ConfigMap' >"$publish_source/dashboards.yaml" printf '%s\n' 'kind: PrometheusRule' >"$publish_source/rules.yaml" printf '%s\n' 'kind: AlertmanagerConfig' >"$publish_source/alertmanager.yaml" chmod 0600 "$publish_source"/*.yaml make_publish_root publish_success_root=$PUBLISH_ROOT expect_pass 'rules-alerts publication is complete and exact' \ publish_access_outputs "$publish_success_root" "$publish_source" rules-alerts expect_pass 'rules-alerts publication preserves exact bytes and modes' \ published_rules_alerts_exact "$publish_success_root" "$publish_source" complete_publish_source="$WORK/complete-publish-source" mkdir -m 0700 -- "$complete_publish_source" for complete_name in \ grafana.yaml blackbox.yaml targets.yaml dashboards.yaml rules.yaml alertmanager.yaml private-dns.yaml; do cp --no-dereference --reflink=never -- \ "$WORK/$complete_name" "$complete_publish_source/$complete_name" done chmod 0600 "$complete_publish_source"/*.yaml published_root_before="$(publication_tree_fingerprint "$publish_success_root")" complete_source_before="$(publication_tree_fingerprint "$complete_publish_source")" expect_fail 'a rules-alerts-published root rejects later complete publication' \ publish_access_outputs "$publish_success_root" "$complete_publish_source" complete expect_output 'rejected complete publication preserves the published root exactly' \ "$published_root_before" publication_tree_fingerprint "$publish_success_root" expect_output 'rejected complete publication preserves all complete sources exactly' \ "$complete_source_before" publication_tree_fingerprint "$complete_publish_source" make_inventory_only_clone "$publish_success_root" complete_publish_root=$PUBLISH_ROOT target_inventory_before="$(publication_tree_fingerprint "$complete_publish_root/target-initial")" post_inventory_before="$(publication_tree_fingerprint "$complete_publish_root/post-substrate")" expect_pass 'the inventory-only clone exactly copies the four published inventory files' \ inventory_clone_matches_source "$publish_success_root" "$complete_publish_root" expect_pass 'an inventory-only clone passes inventory validation' \ validate_access_inventory_root "$complete_publish_root" expect_pass 'an inventory-only clone accepts complete publication' \ publish_access_outputs "$complete_publish_root" "$complete_publish_source" complete expect_pass 'complete publication has the exact nine-entry topology and seven secure YAML files' \ published_complete_exact "$complete_publish_root" "$complete_publish_source" expect_output 'complete publication preserves target-initial inventory exactly' \ "$target_inventory_before" publication_tree_fingerprint "$complete_publish_root/target-initial" expect_output 'complete publication preserves post-substrate inventory exactly' \ "$post_inventory_before" publication_tree_fingerprint "$complete_publish_root/post-substrate" expect_output 'complete publication preserves the rules-alerts source root exactly' \ "$published_root_before" publication_tree_fingerprint "$publish_success_root" expect_output 'complete publication preserves all complete sources exactly' \ "$complete_source_before" publication_tree_fingerprint "$complete_publish_source" make_inventory_only_clone "$publish_success_root" complete_collision_root=$PUBLISH_ROOT printf '%s\n' 'preexisting complete collision' >"$complete_collision_root/private-dns.yaml" chmod 0600 "$complete_collision_root/private-dns.yaml" complete_collision_before="$(publication_tree_fingerprint "$complete_collision_root")" expect_fail 'a last-name collision rejects complete publication before any output is added' \ publish_access_outputs "$complete_collision_root" "$complete_publish_source" complete expect_pass 'a complete last-name collision leaves no partial publication' \ complete_collision_left_no_partial "$complete_collision_root" expect_output 'a rejected complete collision preserves its destination tree exactly' \ "$complete_collision_before" publication_tree_fingerprint "$complete_collision_root" expect_output 'a rejected complete collision preserves the rules-alerts source root exactly' \ "$published_root_before" publication_tree_fingerprint "$publish_success_root" expect_output 'a rejected complete collision preserves all complete sources exactly' \ "$complete_source_before" publication_tree_fingerprint "$complete_publish_source" make_publish_root publish_collision_root=$PUBLISH_ROOT printf '%s\n' 'preexisting' >"$publish_collision_root/rules.yaml" chmod 0600 "$publish_collision_root/rules.yaml" expect_fail 'a later-name collision rejects the whole publication' \ publish_access_outputs "$publish_collision_root" "$publish_source" rules-alerts expect_pass 'a later-name collision leaves no partial publication' \ collision_left_no_partial_publish "$publish_collision_root" printf 'Assertions: %d\n' "$ASSERTIONS" printf 'OBSERVABILITY ACCESS RENDER ASSERTION TEST PASS\n'