apiVersion: v1 kind: ServiceAccount metadata: name: keycape-factor-eso namespace: sso labels: app.kubernetes.io/part-of: net-kingdom-sso-mfa automountServiceAccountToken: false --- apiVersion: v1 kind: ServiceAccount metadata: name: keycape-factor-renewer namespace: sso labels: app.kubernetes.io/part-of: net-kingdom-sso-mfa automountServiceAccountToken: false --- apiVersion: external-secrets.io/v1 kind: ClusterSecretStore metadata: name: openbao-keycape-factor-read spec: conditions: - namespaces: - sso provider: vault: server: http://openbao.openbao.svc.cluster.local:8200 path: platform version: v2 auth: kubernetes: mountPath: kubernetes role: keycape-factor-workload-kv-read serviceAccountRef: name: keycape-factor-eso namespace: sso audiences: - openbao --- apiVersion: external-secrets.io/v1 kind: ExternalSecret metadata: name: keycape-factor-read namespace: sso labels: app.kubernetes.io/part-of: net-kingdom-sso-mfa spec: refreshInterval: 1m secretStoreRef: kind: ClusterSecretStore name: openbao-keycape-factor-read target: name: keycape-factor-read creationPolicy: Owner data: - secretKey: admin-token remoteRef: key: workloads/net-kingdom/keycape-factor-read property: TOKEN - secretKey: expires-at remoteRef: key: workloads/net-kingdom/keycape-factor-read property: EXPIRES_AT --- apiVersion: v1 kind: ConfigMap metadata: name: keycape-factor-renewer-2cf770000e namespace: sso labels: app.kubernetes.io/part-of: net-kingdom-sso-mfa immutable: true data: renew.py: "\"\"\"Dedicated Kubernetes renewal worker. Only sanitized outcome metadata\ \ is emitted.\"\"\"\nimport base64,json,sys,time,urllib.request,urllib.error,urllib.parse\n\ from pathlib import Path\nBAO=\"http://openbao.openbao.svc.cluster.local:8200/v1\"\ \nPI=\"http://privacyidea.mfa.svc.cluster.local:8080\"\nISSUER=\"platform/data/workloads/net-kingdom/keycape-factor-issuer\"\ \nTARGET=\"platform/data/workloads/net-kingdom/keycape-factor-read\"\nUSER=\"\ keycape-factor-reader\"\nPROVENANCE=\"RPF-WP-0040\"\nclass Failure(Exception):pass\n\ class NoRedirect(urllib.request.HTTPRedirectHandler):\n def redirect_request(self,*args,**kwargs):return\ \ None\n\ndef http(url,body=None,headers=None,method=None,form=False):\n data=None\n\ \ headers=dict(headers or {})\n if body is not None:\n data=(urllib.parse.urlencode(body)\ \ if form else json.dumps(body)).encode()\n headers[\"Content-Type\"]=\"application/x-www-form-urlencoded\"\ \ if form else \"application/json\"\n req=urllib.request.Request(url,data=data,headers=headers,method=method)\n\ \ try:\n with urllib.request.build_opener(NoRedirect()).open(req,timeout=15)\ \ as r:\n raw=r.read(1048577)\n if len(raw)>1048576:raise Failure()\n return\ \ r.status,json.loads(raw) if raw else {}\n except urllib.error.HTTPError as e:return\ \ e.code,{}\n\ndef success(code,data):\n if code!=200 or not data.get(\"result\"\ ,{}).get(\"status\"):raise Failure()\n return data[\"result\"][\"value\"]\n\n\ def run():\n session=None;receipt={\"success\":False,\"phase\":\"workload_login\"\ }\n try:\n jwt=Path(\"/var/run/keycape-factor/token\").read_text().strip()\n\ \ code,body=http(BAO+\"/auth/kubernetes/login\",{\"role\":\"keycape-factor-renewer\"\ ,\"jwt\":jwt})\n if code!=200:raise Failure()\n session=body[\"auth\"][\"client_token\"\ ];headers={\"X-Vault-Token\":session}\n receipt[\"phase\"]=\"issuer_custody\"\ \n code,body=http(BAO+\"/\"+ISSUER,headers=headers)\n if code!=200:raise Failure()\n\ \ issuer=body[\"data\"][\"data\"]\n if issuer.get(\"REQUEST\")!=PROVENANCE or\ \ issuer.get(\"USERNAME\")!=USER:raise Failure()\n receipt[\"phase\"]=\"provider_authentication\"\ \n value=success(*http(PI+\"/auth\",{\"username\":USER,\"password\":issuer[\"\ PASSWORD\"]},form=True))\n if value.get(\"role\")!=\"admin\" or value.get(\"\ username\")!=USER:raise Failure()\n token=value[\"token\"];claims=json.loads(base64.urlsafe_b64decode(token.split('.')[1]+'==='));expiry=int(claims[\"\ exp\"])\n if not 3000)\n except Exception:pass\n finally:\n if session:\n try:\n code,_=http(BAO+\"\ /auth/token/revoke-self\",headers={\"X-Vault-Token\":session},method=\"POST\"\ )\n receipt[\"session_revoked\"]=code in (200,204)\n except Exception:receipt[\"\ session_revoked\"]=False\n if not receipt[\"session_revoked\"]:receipt[\"success\"\ ]=False;receipt[\"phase\"]=\"session_cleanup\"\n return receipt\nif __name__==\"\ __main__\":\n receipt=run();print(json.dumps(receipt));raise SystemExit(0 if receipt[\"\ success\"] else 1)\n" --- apiVersion: batch/v1 kind: CronJob metadata: name: keycape-factor-renewer namespace: sso labels: app.kubernetes.io/part-of: net-kingdom-sso-mfa spec: schedule: '*/10 * * * *' suspend: false concurrencyPolicy: Forbid startingDeadlineSeconds: 120 successfulJobsHistoryLimit: 2 failedJobsHistoryLimit: 3 jobTemplate: spec: activeDeadlineSeconds: 120 backoffLimit: 1 ttlSecondsAfterFinished: 3600 template: metadata: labels: app.kubernetes.io/name: keycape-factor-renewer spec: serviceAccountName: keycape-factor-renewer automountServiceAccountToken: false restartPolicy: Never securityContext: runAsNonRoot: true runAsUser: 65534 runAsGroup: 65534 fsGroup: 65534 seccompProfile: type: RuntimeDefault containers: - name: renew image: python:3.12-slim@sha256:d764629ce0ddd8c71fd371e9901efb324a95789d2315a47db7e4d27e78f1b0e9 command: - python3 - /worker/renew.py env: - name: PYTHONDONTWRITEBYTECODE value: '1' securityContext: allowPrivilegeEscalation: false readOnlyRootFilesystem: true capabilities: drop: - ALL resources: requests: cpu: 10m memory: 24Mi limits: cpu: 100m memory: 64Mi volumeMounts: - name: worker mountPath: /worker readOnly: true - name: identity mountPath: /var/run/keycape-factor readOnly: true volumes: - name: worker configMap: name: keycape-factor-renewer-2cf770000e - name: identity projected: defaultMode: 288 sources: - serviceAccountToken: path: token audience: openbao expirationSeconds: 600 --- apiVersion: networking.k8s.io/v1 kind: NetworkPolicy metadata: name: keycape-factor-renewer namespace: sso labels: app.kubernetes.io/part-of: net-kingdom-sso-mfa spec: podSelector: matchLabels: app.kubernetes.io/name: keycape-factor-renewer policyTypes: - Ingress - Egress ingress: [] egress: - to: - namespaceSelector: matchLabels: kubernetes.io/metadata.name: openbao ports: - port: 8200 protocol: TCP - to: - namespaceSelector: matchLabels: kubernetes.io/metadata.name: mfa podSelector: matchLabels: app.kubernetes.io/name: privacyidea ports: - port: 8080 protocol: TCP - to: - namespaceSelector: matchLabels: kubernetes.io/metadata.name: kube-system ports: - port: 53 protocol: UDP - port: 53 protocol: TCP --- apiVersion: networking.k8s.io/v1 kind: NetworkPolicy metadata: name: allow-keycape-factor-renewal namespace: mfa labels: app.kubernetes.io/part-of: net-kingdom-sso-mfa spec: podSelector: matchLabels: app.kubernetes.io/name: privacyidea policyTypes: - Ingress ingress: - from: - namespaceSelector: matchLabels: kubernetes.io/metadata.name: sso podSelector: matchLabels: app.kubernetes.io/name: keycape-factor-renewer ports: - port: 8080 protocol: TCP