Deploy internal user-engine portal foundation
This commit is contained in:
parent
480a84abfb
commit
49f727c54c
4 changed files with 180 additions and 4 deletions
|
|
@ -13,8 +13,8 @@
|
||||||
| workplan | NK-WP-0009 | backlog | — | workplans/NK-WP-0009-netkingdom-security-pattern-tutorials.md |
|
| workplan | NK-WP-0009 | backlog | — | workplans/NK-WP-0009-netkingdom-security-pattern-tutorials.md |
|
||||||
| workplan | NK-WP-0011 | backlog | — | workplans/NK-WP-0011-enterprise-federation-saml.md |
|
| workplan | NK-WP-0011 | backlog | — | workplans/NK-WP-0011-enterprise-federation-saml.md |
|
||||||
| workplan | NK-WP-0021 | finished | — | workplans/NK-WP-0021-activity-core-ops-sso-operators.md |
|
| workplan | NK-WP-0021 | finished | — | workplans/NK-WP-0021-activity-core-ops-sso-operators.md |
|
||||||
| workplan | NK-WP-0022 | backlog | — | workplans/NK-WP-0022-railiance01-identity-cutover-and-coulombcore-retirement.md |
|
| workplan | NK-WP-0022 | active | — | workplans/NK-WP-0022-railiance01-identity-cutover-and-coulombcore-retirement.md |
|
||||||
| workplan | NK-WP-0023 | ready | — | workplans/NK-WP-0023-user-engine-portal-platform-integration.md |
|
| workplan | NK-WP-0023 | active | — | workplans/NK-WP-0023-user-engine-portal-platform-integration.md |
|
||||||
| task | ADHOC-2026-07-02-T01 | done | — | workplans/ADHOC-2026-07-02.md |
|
| task | ADHOC-2026-07-02-T01 | done | — | workplans/ADHOC-2026-07-02.md |
|
||||||
| task | ADHOC-2026-07-02-T02 | done | — | workplans/ADHOC-2026-07-02.md |
|
| task | ADHOC-2026-07-02-T02 | done | — | workplans/ADHOC-2026-07-02.md |
|
||||||
| task | NET-WP-0020-T01 | done | — | workplans/NET-WP-0020-openbao-unseal-custody-and-ssh-automation.md |
|
| task | NET-WP-0020-T01 | done | — | workplans/NET-WP-0020-openbao-unseal-custody-and-ssh-automation.md |
|
||||||
|
|
@ -49,8 +49,8 @@
|
||||||
| task | NK-WP-0022-T06 | wait | — | workplans/NK-WP-0022-railiance01-identity-cutover-and-coulombcore-retirement.md |
|
| task | NK-WP-0022-T06 | wait | — | workplans/NK-WP-0022-railiance01-identity-cutover-and-coulombcore-retirement.md |
|
||||||
| task | NK-WP-0022-T07 | wait | — | workplans/NK-WP-0022-railiance01-identity-cutover-and-coulombcore-retirement.md |
|
| task | NK-WP-0022-T07 | wait | — | workplans/NK-WP-0022-railiance01-identity-cutover-and-coulombcore-retirement.md |
|
||||||
| task | NK-WP-0022-T08 | wait | — | workplans/NK-WP-0022-railiance01-identity-cutover-and-coulombcore-retirement.md |
|
| task | NK-WP-0022-T08 | wait | — | workplans/NK-WP-0022-railiance01-identity-cutover-and-coulombcore-retirement.md |
|
||||||
| task | NK-WP-0023-T01 | todo | — | workplans/NK-WP-0023-user-engine-portal-platform-integration.md |
|
| task | NK-WP-0023-T01 | done | — | workplans/NK-WP-0023-user-engine-portal-platform-integration.md |
|
||||||
| task | NK-WP-0023-T02 | wait | — | workplans/NK-WP-0023-user-engine-portal-platform-integration.md |
|
| task | NK-WP-0023-T02 | progress | — | workplans/NK-WP-0023-user-engine-portal-platform-integration.md |
|
||||||
| task | NK-WP-0023-T03 | wait | — | workplans/NK-WP-0023-user-engine-portal-platform-integration.md |
|
| task | NK-WP-0023-T03 | wait | — | workplans/NK-WP-0023-user-engine-portal-platform-integration.md |
|
||||||
| task | NK-WP-0023-T04 | wait | — | workplans/NK-WP-0023-user-engine-portal-platform-integration.md |
|
| task | NK-WP-0023-T04 | wait | — | workplans/NK-WP-0023-user-engine-portal-platform-integration.md |
|
||||||
| task | NK-WP-0023-T05 | wait | — | workplans/NK-WP-0023-user-engine-portal-platform-integration.md |
|
| task | NK-WP-0023-T05 | wait | — | workplans/NK-WP-0023-user-engine-portal-platform-integration.md |
|
||||||
|
|
|
||||||
26
sso-mfa/k8s/user-engine/README.md
Normal file
26
sso-mfa/k8s/user-engine/README.md
Normal file
|
|
@ -0,0 +1,26 @@
|
||||||
|
# user-engine portal on reef-railiance
|
||||||
|
|
||||||
|
This is a stateful `rail-kubernetes` platform workload. It intentionally has
|
||||||
|
no public Ingress until the KeyCape authorization-code/PKCE edge and
|
||||||
|
`user-engine-portal` client are configured. Direct access to protected routes
|
||||||
|
must remain impossible because the application accepts identity only from a
|
||||||
|
trusted edge marker plus verified claims.
|
||||||
|
|
||||||
|
For the current pre-production bootstrap the image is imported directly into
|
||||||
|
k3s and uses `imagePullPolicy: Never`. Replace it with the immutable Forgejo
|
||||||
|
OCI digest after the OpenBao package-publisher lane is available.
|
||||||
|
|
||||||
|
The CloudNativePG operator creates `user-engine-pg-app`, including its `uri`
|
||||||
|
field. `user-engine-runtime` contains only the generated edge marker and must
|
||||||
|
be replaced by an ExternalSecret before public exposure.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
kubectl apply -f runtime.yaml
|
||||||
|
kubectl -n user-engine rollout status deployment/user-engine
|
||||||
|
kubectl -n user-engine get cluster,pod,service,networkpolicy
|
||||||
|
```
|
||||||
|
|
||||||
|
Rollback sets the Deployment image to the preceding immutable digest.
|
||||||
|
Database migrations are additive and run before serving; restore uses the
|
||||||
|
standard CNPG recovery contract once the offsite object-store reference is
|
||||||
|
attached.
|
||||||
142
sso-mfa/k8s/user-engine/runtime.yaml
Normal file
142
sso-mfa/k8s/user-engine/runtime.yaml
Normal file
|
|
@ -0,0 +1,142 @@
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Namespace
|
||||||
|
metadata:
|
||||||
|
name: user-engine
|
||||||
|
labels:
|
||||||
|
railiance.io/workload-class: platform
|
||||||
|
---
|
||||||
|
apiVersion: postgresql.cnpg.io/v1
|
||||||
|
kind: Cluster
|
||||||
|
metadata:
|
||||||
|
name: user-engine-pg
|
||||||
|
namespace: user-engine
|
||||||
|
spec:
|
||||||
|
instances: 1
|
||||||
|
imageName: ghcr.io/cloudnative-pg/postgresql:17.5
|
||||||
|
storage:
|
||||||
|
size: 5Gi
|
||||||
|
bootstrap:
|
||||||
|
initdb:
|
||||||
|
database: user_engine
|
||||||
|
owner: user_engine
|
||||||
|
resources:
|
||||||
|
requests: {cpu: 100m, memory: 256Mi}
|
||||||
|
limits: {cpu: "1", memory: 1Gi}
|
||||||
|
---
|
||||||
|
apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
name: user-engine
|
||||||
|
namespace: user-engine
|
||||||
|
labels: &labels
|
||||||
|
app.kubernetes.io/name: user-engine
|
||||||
|
app.kubernetes.io/component: portal
|
||||||
|
spec:
|
||||||
|
replicas: 1
|
||||||
|
selector:
|
||||||
|
matchLabels: {app.kubernetes.io/name: user-engine}
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels: *labels
|
||||||
|
spec:
|
||||||
|
automountServiceAccountToken: false
|
||||||
|
securityContext:
|
||||||
|
runAsNonRoot: true
|
||||||
|
seccompProfile: {type: RuntimeDefault}
|
||||||
|
containers:
|
||||||
|
- name: portal
|
||||||
|
image: user-engine:portal-c27012a
|
||||||
|
imagePullPolicy: Never
|
||||||
|
ports: [{name: http, containerPort: 8080}]
|
||||||
|
env:
|
||||||
|
- name: USER_ENGINE_DATABASE_URL
|
||||||
|
valueFrom:
|
||||||
|
secretKeyRef: {name: user-engine-pg-app, key: uri}
|
||||||
|
- name: USER_ENGINE_PROXY_SECRET
|
||||||
|
valueFrom:
|
||||||
|
secretKeyRef: {name: user-engine-runtime, key: proxy-secret}
|
||||||
|
- {name: USER_ENGINE_LOGIN_URL, value: "https://kc.coulomb.social/"}
|
||||||
|
- {name: USER_ENGINE_OIDC_ISSUER, value: "https://kc.coulomb.social"}
|
||||||
|
- {name: USER_ENGINE_OIDC_AUDIENCE, value: user-engine-portal}
|
||||||
|
- {name: USER_ENGINE_PUBLIC_REGISTRATION, value: "false"}
|
||||||
|
securityContext:
|
||||||
|
allowPrivilegeEscalation: false
|
||||||
|
capabilities: {drop: ["ALL"]}
|
||||||
|
readOnlyRootFilesystem: true
|
||||||
|
resources:
|
||||||
|
requests: {cpu: 50m, memory: 64Mi}
|
||||||
|
limits: {cpu: 500m, memory: 256Mi}
|
||||||
|
startupProbe:
|
||||||
|
httpGet: {path: /readyz, port: http}
|
||||||
|
failureThreshold: 30
|
||||||
|
periodSeconds: 5
|
||||||
|
readinessProbe:
|
||||||
|
httpGet: {path: /readyz, port: http}
|
||||||
|
periodSeconds: 10
|
||||||
|
livenessProbe:
|
||||||
|
httpGet: {path: /healthz, port: http}
|
||||||
|
periodSeconds: 20
|
||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Service
|
||||||
|
metadata: {name: user-engine, namespace: user-engine}
|
||||||
|
spec:
|
||||||
|
selector: {app.kubernetes.io/name: user-engine}
|
||||||
|
ports: [{name: http, port: 8080, targetPort: http}]
|
||||||
|
---
|
||||||
|
apiVersion: networking.k8s.io/v1
|
||||||
|
kind: NetworkPolicy
|
||||||
|
metadata: {name: user-engine-default-deny, namespace: user-engine}
|
||||||
|
spec:
|
||||||
|
podSelector: {}
|
||||||
|
policyTypes: [Ingress, Egress]
|
||||||
|
---
|
||||||
|
apiVersion: networking.k8s.io/v1
|
||||||
|
kind: NetworkPolicy
|
||||||
|
metadata: {name: user-engine-runtime, namespace: user-engine}
|
||||||
|
spec:
|
||||||
|
podSelector:
|
||||||
|
matchLabels: {app.kubernetes.io/name: user-engine}
|
||||||
|
policyTypes: [Ingress, Egress]
|
||||||
|
ingress:
|
||||||
|
- from:
|
||||||
|
- namespaceSelector:
|
||||||
|
matchLabels: {kubernetes.io/metadata.name: kube-system}
|
||||||
|
ports: [{protocol: TCP, port: 8080}]
|
||||||
|
egress:
|
||||||
|
- to:
|
||||||
|
- podSelector:
|
||||||
|
matchLabels: {cnpg.io/cluster: user-engine-pg}
|
||||||
|
ports: [{protocol: TCP, port: 5432}]
|
||||||
|
- to:
|
||||||
|
- namespaceSelector:
|
||||||
|
matchLabels: {kubernetes.io/metadata.name: kube-system}
|
||||||
|
ports: [{protocol: UDP, port: 53}, {protocol: TCP, port: 53}]
|
||||||
|
---
|
||||||
|
apiVersion: networking.k8s.io/v1
|
||||||
|
kind: NetworkPolicy
|
||||||
|
metadata: {name: user-engine-postgres, namespace: user-engine}
|
||||||
|
spec:
|
||||||
|
podSelector:
|
||||||
|
matchLabels: {cnpg.io/cluster: user-engine-pg}
|
||||||
|
policyTypes: [Ingress, Egress]
|
||||||
|
ingress:
|
||||||
|
- from:
|
||||||
|
- podSelector:
|
||||||
|
matchLabels: {app.kubernetes.io/name: user-engine}
|
||||||
|
ports: [{protocol: TCP, port: 5432}]
|
||||||
|
- from:
|
||||||
|
- namespaceSelector:
|
||||||
|
matchLabels: {kubernetes.io/metadata.name: cnpg-system}
|
||||||
|
ports:
|
||||||
|
- {protocol: TCP, port: 5432}
|
||||||
|
- {protocol: TCP, port: 8000}
|
||||||
|
- {protocol: TCP, port: 9187}
|
||||||
|
egress:
|
||||||
|
# CNPG instance manager must read its Cluster resource during bootstrap.
|
||||||
|
# K3s network policy evaluates the API service after DNAT on port 6443.
|
||||||
|
- ports: [{protocol: TCP, port: 6443}]
|
||||||
|
- to:
|
||||||
|
- namespaceSelector:
|
||||||
|
matchLabels: {kubernetes.io/metadata.name: kube-system}
|
||||||
|
ports: [{protocol: UDP, port: 53}, {protocol: TCP, port: 53}]
|
||||||
|
|
@ -98,6 +98,14 @@ runtime references, NetworkPolicies, TLS ingress, backups, observability,
|
||||||
resource limits, rollout/rollback, and availability evidence. Do not place
|
resource limits, rollout/rollback, and availability evidence. Do not place
|
||||||
this stateful platform control surface on scale-to-zero Knative.
|
this stateful platform control surface on scale-to-zero Knative.
|
||||||
|
|
||||||
|
Implementation evidence (2026-07-27): the internal-only portal foundation is
|
||||||
|
running on `reef-railiance` as `Deployment/user-engine` with dedicated healthy
|
||||||
|
`Cluster/user-engine-pg`, default-deny NetworkPolicies, immutable directly
|
||||||
|
imported image `user-engine:portal-c27012a`, and successful `/readyz` probes.
|
||||||
|
Public ingress remains intentionally absent until T03 supplies the verified
|
||||||
|
KeyCape OIDC edge. Forgejo OCI publication is pending restoration of the
|
||||||
|
OpenBao package-publisher capability; no credential was bypassed or exposed.
|
||||||
|
|
||||||
## T06 - Prove role-scoped administration and failure safety
|
## T06 - Prove role-scoped administration and failure safety
|
||||||
|
|
||||||
```task
|
```task
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue