Skip to content

Latest commit

 

History

2 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Identity Contract + vCluster MVP Overlay

This overlay is for an existing -mc-dev checkout. It assumes MC is already deployed with Keycloak, Envoy Gateway, cert-manager, and Flux controllers running.

This version is intentionally manual and staged. The scripts are helpers only. They do not perform the full onboarding flow for you. The goal is to let a developer render the contract, inspect the output, apply one step at a time, and validate where each change happens.

What this proves

Identity contract YAML
  → render Keycloak Config CLI YAML
  → inspect generated config
  → apply ConfigMap + Job
  → Keycloak creates/updates realms and clients
  → platform publishes OIDC Secret
  → tenant/vcluster app consumes the Secret and CA bundle
  → Envoy exposes the app

Current validated runtime assumptions

  • vcluster chart 0.20.0 works with minimal values.
  • vcluster connect ... --print is the supported CLI flow.
  • Keycloak admin secret uses KEYCLOAK_ADMIN and KEYCLOAK_ADMIN_PASSWORD.
  • scripts/keycloak/prepare-admin-secret.sh normalizes those keys to username and password for the Keycloak Config CLI Job.
  • Keycloak internal URL is http://keycloak-keycloakx-http.keycloak.svc.cluster.local:80/auth.
  • Default shared-service model is token validation first. Tenant users are not stored, synced, or linked in a shared realm.

Mental model

Tenant landing zone first
  vcluster + namespace + trust preparation

Identity creation second
  realm + app client + app OIDC Secret

App onboarding third
  app deployment + service + route + validation

Apps should not mutate Keycloak. Apps only consume identity outputs.


Phase 1 — Review the contract input

Start by looking at the contract examples. These are the intent files.

find gitops/platform/identity/contracts/examples -type f -name '*.yaml' -print
cat gitops/platform/identity/contracts/examples/tenants/opp/realm-identity.yaml
cat gitops/platform/identity/contracts/examples/tenants/opp/app-smoke-app.yaml
cat gitops/platform/identity/contracts/examples/platform/shared-client--shell.yaml
cat gitops/platform/identity/contracts/examples/platform/redirect-workspaces.yaml

The important scenarios are:

RealmIdentity                 creates an identity boundary / tenant realm
ApplicationIdentity           creates an app client and output Secret
ApplicationIdentity shared    creates shared platform clients like -app-envoy
ApplicationRedirectRegistration adds redirect URIs to an existing shared client
SharedServiceAccess           documents token-validation-first shared service access

Phase 2 — Render identity config, but do not apply yet

python3 scripts/identity/identityctl.py demo --repo-root .

Expected output:

OK: validated 6 contract file(s)
Rendered demo output: build/identity/demo

Inspect everything before applying:

ls -l build/identity/demo
cat build/identity/demo/platform.yaml
cat build/identity/demo/tenant-opp.yaml
cat build/identity/demo/configmap.yaml
cat build/identity/demo/job.yaml
cat build/identity/demo/output-secrets.yaml

This is the most important step. It proves the contract can be translated into Keycloak Config CLI input and Kubernetes manifests without touching the cluster yet.


Phase 3 — Prepare the platform identity namespace and Keycloak admin secret

Create the namespace expected by the demo Job:

kubectl create ns platform-identity --dry-run=client -o yaml | kubectl apply -f -

Normalize the Keycloak admin secret for the Job:

bash scripts/keycloak/prepare-admin-secret.sh
kubectl -n platform-identity get secret keycloak-admin-secret -o json | jq '.data'

Expected keys:

{
  "password": "...",
  "username": "..."
}

Validate that Keycloak is reachable from the Job namespace:

kubectl -n platform-identity run curl-test --rm -it --image=curlimages/curl --restart=Never -- \
  curl -v http://keycloak-keycloakx-http.keycloak.svc.cluster.local:80/auth

Phase 4 — Apply identity configuration to Keycloak, step by step

Apply only the rendered ConfigMap first:

kubectl apply -f build/identity/demo/configmap.yaml
kubectl -n platform-identity get configmap keycloak-rendered-config

Apply the output Secrets next. For the demo, these are host-cluster Secrets used as app outputs:

kubectl create ns opp-apps --dry-run=client -o yaml | kubectl apply -f -
kubectl apply -f build/identity/demo/output-secrets.yaml
kubectl -n opp-apps get secret opp-smoke-app-oidc

Run the Keycloak Config CLI Job last:

kubectl -n platform-identity delete job keycloak-config-cli --ignore-not-found
kubectl apply -f build/identity/demo/job.yaml
kubectl -n platform-identity get pods -w

Check the Job logs:

kubectl -n platform-identity logs job/keycloak-config-cli

Expected successful pattern:

Importing file 'file:/config/platform.yaml'
Importing file 'file:/config/tenant-opp.yaml'
keycloak-config-cli ran in ...

Phase 5 — Validate Keycloak state from CLI

Port-forward Keycloak:

kubectl -n keycloak port-forward svc/keycloak-keycloakx-http 8080:80

In another terminal:

curl -s http://localhost:8080/auth/realms/platform/.well-known/openid-configuration | jq .issuer
curl -s http://localhost:8080/auth/realms/tenant-opp/.well-known/openid-configuration | jq .issuer

If the realms exist, the contract successfully changed Keycloak state.


Phase 6 — Create the tenant landing zone / vcluster

Apply the vcluster source and tenant namespace:

kubectl apply -f gitops/platform/vcluster/sources/loft-helmrepository.yaml
kubectl apply -f gitops/tenants/opp/namespace.yaml
kubectl apply -f gitops/tenants/opp/vcluster/values.yaml
kubectl apply -f gitops/tenants/opp/vcluster/helmrelease.yaml

Watch:

kubectl -n tenant-opp-system get helmrelease tenant-opp -w
kubectl -n tenant-opp-system get pods,svc

Expected host resources:

pod/tenant-opp-0
service/tenant-opp
service/tenant-opp-headless

Connect to the vcluster:

vcluster connect tenant-opp -n tenant-opp-system --print > ./tenant-opp.kubeconfig
kubectl --kubeconfig ./tenant-opp.kubeconfig get ns

Phase 7 — Prepare app namespace and copy identity outputs into vcluster

Create the app namespace inside the vcluster:

kubectl --kubeconfig ./tenant-opp.kubeconfig apply -f gitops/tenants/opp/app/namespace.yaml
kubectl --kubeconfig ./tenant-opp.kubeconfig get ns

For MVP only, copy the generated OIDC Secret from host cluster into the vcluster:

kubectl -n opp-apps get secret opp-smoke-app-oidc -o yaml \
  | sed '/resourceVersion:/d;/uid:/d;/creationTimestamp:/d;/managedFields:/,/^$/d' \
  | kubectl --kubeconfig ./tenant-opp.kubeconfig apply -f -

kubectl --kubeconfig ./tenant-opp.kubeconfig -n opp-apps get secret opp-smoke-app-oidc

Later this manual copy should be replaced with ExternalSecrets, OpenBao, or supported vcluster sync.


Phase 8 — Export CA bundle into vcluster

Later this should be replaced with cert-manager trust-manager bundle distribution.


Phase 9 — App onboarding contract and app deployment

The app onboarding contract is the ApplicationIdentity file. For the demo:

cat gitops/platform/identity/contracts/examples/tenants/opp/app-smoke-app.yaml

It says:

Create an app identity for opp-smoke-app in the tenant-opp realm.
Publish the OIDC output as opp-apps/opp-smoke-app-oidc.

After the identity output and CA bundle exist in the vcluster, deploy the app:

kubectl --kubeconfig ./tenant-opp.kubeconfig apply -f gitops/tenants/opp/app/deployment.yaml
kubectl --kubeconfig ./tenant-opp.kubeconfig apply -f gitops/tenants/opp/app/service.yaml
kubectl --kubeconfig ./tenant-opp.kubeconfig -n opp-apps get pods,svc,secret,configmap

This keeps the dependency correct:

identity + trust first
app deployment second

Phase 10 — Expose the app through host Envoy

Check host-side service names generated by vcluster:

kubectl -n tenant-opp-system get svc | grep opp-demo-app || true
bash scripts/vcluster/tenantctl.sh host-services opp

If the host-side service name differs from the sample, update:

vi gitops/tenants/opp/gateway/httproute.yaml

Apply the route:

kubectl apply -f gitops/tenants/opp/gateway/httproute.yaml
kubectl -n tenant-opp-system get httproute opp-demo-app

Expected:

hello from opp vcluster app

Useful helper commands

These helpers only print or inspect; they do not onboard everything.

bash scripts/vcluster/tenantctl.sh plan opp
bash scripts/vcluster/tenantctl.sh status opp
bash scripts/vcluster/tenantctl.sh connect opp
bash scripts/vcluster/tenantctl.sh host-services opp

Cleanup

bash scripts/cleanup/cleanup-mvp.sh opp

This removes MVP Kubernetes resources, vcluster namespace, generated files, and local kubeconfig. It does not delete Keycloak realms by default because destructive identity deletion should be explicit.


Future GitOps direction

Flux should eventually own steady-state objects:

tenant namespace
vcluster HelmRelease
app manifests
HTTPRoute
CA bundle resources
validation jobs

The Keycloak Config CLI Job can remain a controlled one-time execution until the onboarding API writes contracts to Git and Flux reconciles them.

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages