From 960ed0914f9e1ca3d51989d6e51a8fe6b5248b76 Mon Sep 17 00:00:00 2001 From: codex Date: Thu, 24 Sep 2026 00:52:07 +0200 Subject: [PATCH] RPF-WP-0047: static notice page manifests for bao.coulomb.social Isolated namespace (Traefik-only ingress, no egress), pinned unprivileged nginx, / -> 200 notice, every other path -> 404, letsencrypt-prod TLS, HTTP->HTTPS redirect. Nothing proxies to OpenBao. Co-Authored-By: Claude Opus 5.5 Assistant: claude-code Assistant-Model: opus Assistant-Process: 150322@bnt-lap001 Assistant-Session: 16a7b788-374e-4915-a1df-fc87ffd9a5e4 --- .../platform-addons/bao-notice/default.conf | 34 ++++ argocd/platform-addons/bao-notice/index.html | 19 +++ .../bao-notice/kustomization.yaml | 18 ++ .../platform-addons/bao-notice/manifests.yaml | 154 ++++++++++++++++++ 4 files changed, 225 insertions(+) create mode 100644 argocd/platform-addons/bao-notice/default.conf create mode 100644 argocd/platform-addons/bao-notice/index.html create mode 100644 argocd/platform-addons/bao-notice/kustomization.yaml create mode 100644 argocd/platform-addons/bao-notice/manifests.yaml diff --git a/argocd/platform-addons/bao-notice/default.conf b/argocd/platform-addons/bao-notice/default.conf new file mode 100644 index 0000000..13ca404 --- /dev/null +++ b/argocd/platform-addons/bao-notice/default.conf @@ -0,0 +1,34 @@ +# Static notice for bao.coulomb.social (RPF-WP-0047). Serves one page; proxies nothing. +server { + listen 8080; + server_name _; + server_tokens off; + root /usr/share/nginx/html; + + add_header Content-Security-Policy "default-src 'none'; style-src 'unsafe-inline'; frame-ancestors 'none'" always; + add_header X-Content-Type-Options "nosniff" always; + add_header Referrer-Policy "no-referrer" always; + add_header Cache-Control "no-store" always; + add_header X-Robots-Tag "noindex, nofollow" always; + + location = / { + try_files /index.html =404; + } + location = /robots.txt { + default_type text/plain; + return 200 "User-agent: *\nDisallow: /\n"; + } + location = /healthz { + access_log off; + default_type text/plain; + return 200 "ok\n"; + } + # Any other path (e.g. /v1/sys/health, /ui/) is 404 with the same notice, never 200. + location / { + error_page 404 /index.html; + return 404; + } + location = /index.html { + internal; + } +} diff --git a/argocd/platform-addons/bao-notice/index.html b/argocd/platform-addons/bao-notice/index.html new file mode 100644 index 0000000..6346724 --- /dev/null +++ b/argocd/platform-addons/bao-notice/index.html @@ -0,0 +1,19 @@ + + + + + + +Not publicly available + + + +

Not publicly available

+

This address belongs to an internal service that is not offered publicly.

+

There is nothing to sign in to here. If you were sent to this address, please contact the person who gave it to you.

+ + diff --git a/argocd/platform-addons/bao-notice/kustomization.yaml b/argocd/platform-addons/bao-notice/kustomization.yaml new file mode 100644 index 0000000..e454999 --- /dev/null +++ b/argocd/platform-addons/bao-notice/kustomization.yaml @@ -0,0 +1,18 @@ +apiVersion: kustomize.config.k8s.io/v1beta1 +kind: Kustomization + +# RPF-WP-0047. Read only by argocd/railiance01/applications/bao-notice.application.yaml. + +resources: + - manifests.yaml + +generatorOptions: + disableNameSuffixHash: false + +configMapGenerator: + - name: bao-notice-conf + namespace: bao-notice + files: [default.conf] + - name: bao-notice-html + namespace: bao-notice + files: [index.html] diff --git a/argocd/platform-addons/bao-notice/manifests.yaml b/argocd/platform-addons/bao-notice/manifests.yaml new file mode 100644 index 0000000..6d83945 --- /dev/null +++ b/argocd/platform-addons/bao-notice/manifests.yaml @@ -0,0 +1,154 @@ +# RPF-WP-0047: static "not publicly available" notice for bao.coulomb.social. +# OpenBao stays non-public (RMASTER-WP-0020-T09). This namespace has no route +# to OpenBao: ingress only from Traefik, no egress at all. +apiVersion: v1 +kind: Namespace +metadata: + name: bao-notice + labels: + app.kubernetes.io/part-of: railiance-platform +--- +apiVersion: networking.k8s.io/v1 +kind: NetworkPolicy +metadata: + name: bao-notice-isolation + namespace: bao-notice +spec: + podSelector: {} + policyTypes: [Ingress, Egress] + ingress: + - from: + - namespaceSelector: + matchLabels: + kubernetes.io/metadata.name: kube-system + podSelector: + matchLabels: + app.kubernetes.io/name: traefik + ports: + - {protocol: TCP, port: 8080} + egress: [] +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: bao-notice + namespace: bao-notice + labels: + app.kubernetes.io/name: bao-notice +spec: + replicas: 1 + revisionHistoryLimit: 2 + selector: + matchLabels: + app.kubernetes.io/name: bao-notice + template: + metadata: + labels: + app.kubernetes.io/name: bao-notice + spec: + automountServiceAccountToken: false + enableServiceLinks: false + securityContext: + runAsNonRoot: true + runAsUser: 101 + runAsGroup: 101 + seccompProfile: + type: RuntimeDefault + containers: + - name: nginx + image: nginxinc/nginx-unprivileged@sha256:65e3e85dbaed8ba248841d9d58a899b6197106c23cb0ff1a132b7bfe0547e4c0 + ports: + - {name: http, containerPort: 8080} + securityContext: + allowPrivilegeEscalation: false + readOnlyRootFilesystem: true + capabilities: + drop: [ALL] + resources: + requests: {cpu: 5m, memory: 16Mi} + limits: {cpu: 100m, memory: 64Mi} + readinessProbe: + httpGet: {path: /healthz, port: http} + periodSeconds: 20 + livenessProbe: + httpGet: {path: /healthz, port: http} + periodSeconds: 60 + volumeMounts: + - {name: conf, mountPath: /etc/nginx/conf.d, readOnly: true} + - {name: html, mountPath: /usr/share/nginx/html, readOnly: true} + - {name: tmp, mountPath: /tmp} + volumes: + - name: conf + configMap: + name: bao-notice-conf + items: [{key: default.conf, path: default.conf}] + - name: html + configMap: + name: bao-notice-html + items: [{key: index.html, path: index.html}] + - name: tmp + emptyDir: {sizeLimit: 16Mi} +--- +apiVersion: v1 +kind: Service +metadata: + name: bao-notice + namespace: bao-notice +spec: + selector: + app.kubernetes.io/name: bao-notice + ports: + - {name: http, port: 80, targetPort: http} +--- +apiVersion: traefik.io/v1alpha1 +kind: Middleware +metadata: + name: redirect-https + namespace: bao-notice +spec: + redirectScheme: + scheme: https + permanent: true +--- +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: bao-notice + namespace: bao-notice + annotations: + cert-manager.io/cluster-issuer: letsencrypt-prod + traefik.ingress.kubernetes.io/router.entrypoints: websecure + traefik.ingress.kubernetes.io/router.tls: "true" +spec: + ingressClassName: traefik + tls: + - hosts: [bao.coulomb.social] + secretName: bao-notice-tls + rules: + - host: bao.coulomb.social + http: + paths: + - path: / + pathType: Prefix + backend: + service: {name: bao-notice, port: {number: 80}} +--- +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: bao-notice-http-redirect + namespace: bao-notice + annotations: + traefik.ingress.kubernetes.io/router.entrypoints: web + traefik.ingress.kubernetes.io/router.middlewares: bao-notice-redirect-https@kubernetescrd + traefik.ingress.kubernetes.io/router.priority: "1" +spec: + ingressClassName: traefik + rules: + - host: bao.coulomb.social + http: + paths: + - path: / + pathType: Prefix + backend: + service: {name: bao-notice, port: {number: 80}}