"""Offline invariants for manifests rendered by real Ansible/Jinja.""" import json from pathlib import Path import yaml from kubernetes_validate import validate def docs(name): return [doc for doc in yaml.safe_load_all(Path(f"/tmp/www-test-{name}.yml").read_text()) if doc] def find(objects, kind, name): return next(obj for obj in objects if obj["kind"] == kind and obj["metadata"]["name"] == name) def pod_checks(pod, external=False): assert pod["automountServiceAccountToken"] is False assert pod["securityContext"]["runAsNonRoot"] is True container = pod["containers"][0] assert container["securityContext"]["readOnlyRootFilesystem"] is True assert container["securityContext"]["capabilities"]["drop"] == ["ALL"] assert container["envFrom"] == [{"configMapRef": {"name": "membership-config"}}, {"secretRef": {"name": "membership"}}] assert not container.get("env") assert container["resources"]["limits"]["memory"] assert any(mount["mountPath"] == "/etc/membership/tiers" and mount["readOnly"] for mount in container["volumeMounts"]) if external: assert pod["imagePullSecrets"] == [{"name": "registry-pull"}] assert any(volume.get("secret", {}).get("secretName") == "private-ca" for volume in pod["volumes"]) assert any(mount["mountPath"] == "/etc/membership/ca" and mount["readOnly"] for mount in container["volumeMounts"]) all_objects = [] for name in ["website", "membership-config", "membership-postgres", "membership-migrate", "membership-workloads"]: all_objects.extend(docs(name)) for path in Path('/tmp').glob('www-test-*.yml'): for obj in yaml.safe_load_all(path.read_text()): if obj and obj['kind'] != 'OnionService': validate(obj, desired_version='1.31.0', strict=True) assert all(obj["metadata"]["namespace"] == "www" for obj in all_objects) assert len({(obj["kind"], obj["metadata"]["name"]) for obj in all_objects}) == len(all_objects) config = find(all_objects, "ConfigMap", "membership-config")["data"] assert all(isinstance(value, str) for value in config.values()) assert config["MEMBERSHIP_PUBLIC_URL"] == "https://www.eom.dev" assert config["LDAP_ALLOW_INSECURE"] == "0" assert config["LDAP_URL"].startswith("ldaps://") plaintext_config = find(docs("plaintext-membership-config"), "ConfigMap", "membership-config")["data"] assert plaintext_config["LDAP_ALLOW_INSECURE"] == "1" assert plaintext_config["LDAP_URL"] == "ldap://openldap.openldap.svc.cluster.local:389" assert all(isinstance(value, str) for value in plaintext_config.values()) assert "MEMBERSHIP_SECRET_KEY" not in config and "SHKEEPER_API_KEY" not in config tiers = json.loads(find(all_objects, "ConfigMap", "membership-tiers")["data"]["tiers.json"]) service_groups = json.loads(find(all_objects, "ConfigMap", "membership-tiers")["data"]["service-groups.json"]) assert config["MEMBERSHIP_SERVICE_GROUPS_FILE"] == "/etc/membership/tiers/service-groups.json" assert service_groups["0"] == ["cn=free-service,ou=groups,dc=example,dc=org"] assert len(service_groups["2"]) == 2 assert len(tiers) == 5 and tiers["level-5"]["usd_amount"] == "64.00" assert [tiers[f"level-{level}"]["level"] for level in range(1, 6)] == list(range(1, 6)) for name in ["membership", "membership-worker"]: deployment = find(all_objects, "Deployment", name) pod_checks(deployment["spec"]["template"]["spec"]) web = find(all_objects, "Deployment", "membership")["spec"]["template"]["spec"]["containers"][0] assert "assert r.status==200" in web["readinessProbe"]["exec"]["command"][-1] worker = find(all_objects, "Deployment", "membership-worker") assert worker["spec"]["replicas"] == 1 and worker["spec"]["strategy"]["type"] == "Recreate" assert "sync_memberships" in worker["spec"]["template"]["spec"]["containers"][0]["command"] job = next(obj for obj in all_objects if obj["kind"] == "Job") assert job["metadata"]["name"] == "membership-migrate-" + "a" * 16 pod_checks(job["spec"]["template"]["spec"]) assert job["spec"]["template"]["spec"]["containers"][0]["command"] == ["python", "manage.py", "migrate", "--noinput"] db = find(all_objects, "StatefulSet", "membership-db") assert db["spec"]["volumeClaimTemplates"][0]["spec"]["accessModes"] == ["ReadWriteOnce"] assert "persistentVolumeClaimRetentionPolicy" not in db["spec"] assert find(all_objects, "Service", "membership-db")["spec"]["type"] == "ClusterIP" assert find(all_objects, "Service", "membership")["spec"]["type"] == "ClusterIP" policy = find(all_objects, "NetworkPolicy", "membership-web") assert policy["spec"]["ingress"][0]["from"] == [{"podSelector": {"matchLabels": {"app": "httpd"}}}] apache = find(all_objects, "ConfigMap", "httpd")["data"] assert "http://membership:8000/members/" in apache["membership.conf"] assert "X-Forwarded-Proto" in apache["membership.conf"] assert "Require all denied" in apache["membership.conf"] assert "LimitRequestBody 262144" in apache["membership.conf"] assert '' in apache["membership.conf"] assert "LimitRequestBody 2097152" in apache["membership.conf"] assert "env=!membership_sensitive" in apache["httpd.conf"] assert "LoadModule proxy_http_module" in apache["httpd.conf"] source = find(all_objects, "Deployment", "httpd")["spec"]["template"]["spec"]["initContainers"][0] assert "rm -rf" not in source["command"][-1] assert 'cp -a /tmp/www/htdocs/. /data/' in source["command"][-1] ingress = find(all_objects, "Ingress", "www") assert ingress["metadata"]["annotations"]["nginx.ingress.kubernetes.io/enable-access-log"] == "false" assert ingress["metadata"]["annotations"]["nginx.ingress.kubernetes.io/proxy-body-size"] == "2m" assert ingress["spec"]["rules"][0]["http"]["paths"][0]["backend"]["service"]["name"] == "httpd" for obj in docs("external-membership-workloads"): if obj["kind"] == "Deployment": pod_checks(obj["spec"]["template"]["spec"], external=True) external_config = docs("external-membership-config") assert not any(obj["kind"] == "NetworkPolicy" and obj["metadata"]["name"] == "membership-db" for obj in external_config) assert find(external_config, "ConfigMap", "membership-config")["data"]["POSTGRES_SSLMODE"] == "verify-full" assert find(external_config, "ConfigMap", "membership-config")["data"]["LDAP_ALLOW_INSECURE"] == "0" disabled = docs("disabled-website") assert not any(obj["kind"] == "OnionService" for obj in disabled) assert "ProxyPass" not in find(disabled, "ConfigMap", "httpd")["data"]["membership.conf"] print(f"PASS: {len(all_objects)} Kubernetes objects; default, plaintext LDAP, external/CA/SHKeeper and disabled variants")