Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 17 additions & 7 deletions AuthBridge/client-registration/example_deployment.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,24 @@ metadata:
namespace: my-agent
data:
SPIRE_ENABLED: "false"
# Replace these placeholder values with real endpoints/credentials
# Replace these placeholder values with real endpoints
KEYCLOAK_URL: "http://keycloak.keycloak.svc:8080"
KEYCLOAK_REALM: "master"
KEYCLOAK_ADMIN_USERNAME: "admin"
KEYCLOAK_ADMIN_PASSWORD: "admin"
KEYCLOAK_TOKEN_EXCHANGE_ENABLED: "true"
KEYCLOAK_CLIENT_REGISTRATION_ENABLED: "true"
---
# keycloak-admin-secret - Keycloak admin credentials for client registration
# Replace the placeholder values with your actual admin credentials.
apiVersion: v1
kind: Secret
metadata:
name: keycloak-admin-secret
namespace: my-agent
type: Opaque
stringData:
KEYCLOAK_ADMIN_USERNAME: "admin"
KEYCLOAK_ADMIN_PASSWORD: "changeme"
---
apiVersion: v1
kind: ServiceAccount
metadata:
Expand Down Expand Up @@ -77,13 +87,13 @@ spec:
key: KEYCLOAK_REALM
- name: KEYCLOAK_ADMIN_USERNAME
valueFrom:
configMapKeyRef:
name: environments
secretKeyRef:
name: keycloak-admin-secret
key: KEYCLOAK_ADMIN_USERNAME
- name: KEYCLOAK_ADMIN_PASSWORD
valueFrom:
configMapKeyRef:
name: environments
secretKeyRef:
name: keycloak-admin-secret
key: KEYCLOAK_ADMIN_PASSWORD
- name: CLIENT_NAME
value: my-app
Expand Down
24 changes: 17 additions & 7 deletions AuthBridge/client-registration/example_deployment_spiffe.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,24 @@ metadata:
namespace: my-agent
data:
SPIRE_ENABLED: "true"
# Replace these placeholder values with real endpoints/credentials
# Replace these placeholder values with real endpoints
KEYCLOAK_URL: "http://keycloak.keycloak.svc:8080"
KEYCLOAK_REALM: "master"
KEYCLOAK_ADMIN_USERNAME: "admin"
KEYCLOAK_ADMIN_PASSWORD: "admin"
KEYCLOAK_TOKEN_EXCHANGE_ENABLED: "true"
KEYCLOAK_CLIENT_REGISTRATION_ENABLED: "true"
---
# keycloak-admin-secret - Keycloak admin credentials for client registration
# Replace the placeholder values with your actual admin credentials.
apiVersion: v1
kind: Secret
metadata:
name: keycloak-admin-secret
namespace: my-agent
type: Opaque
stringData:
KEYCLOAK_ADMIN_USERNAME: "admin"
KEYCLOAK_ADMIN_PASSWORD: "changeme"
---
apiVersion: v1
kind: ServiceAccount
metadata:
Expand Down Expand Up @@ -91,13 +101,13 @@ spec:
key: KEYCLOAK_REALM
- name: KEYCLOAK_ADMIN_USERNAME
valueFrom:
configMapKeyRef:
name: environments
secretKeyRef:
name: keycloak-admin-secret
key: KEYCLOAK_ADMIN_USERNAME
- name: KEYCLOAK_ADMIN_PASSWORD
valueFrom:
configMapKeyRef:
name: environments
secretKeyRef:
name: keycloak-admin-secret
key: KEYCLOAK_ADMIN_PASSWORD
- name: CLIENT_NAME
value: my-app
Expand Down
16 changes: 12 additions & 4 deletions AuthBridge/demos/github-issue/k8s/configmaps.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,19 @@ data:
SPIRE_ENABLED: "true"
KEYCLOAK_URL: "http://keycloak-service.keycloak.svc:8080"
KEYCLOAK_REALM: "demo"
# Demo/development only: do NOT use hardcoded admin credentials in production.
# For production deployments, supply these via a Kubernetes Secret and reference
# them from your Pod/Deployment using env.valueFrom.secretKeyRef instead.

---
# keycloak-admin-secret - Keycloak admin credentials for client registration
# Replace the placeholder values with your actual admin credentials.
apiVersion: v1
kind: Secret
metadata:
name: keycloak-admin-secret
namespace: team1
type: Opaque
stringData:
KEYCLOAK_ADMIN_USERNAME: "admin"
KEYCLOAK_ADMIN_PASSWORD: "admin"
KEYCLOAK_ADMIN_PASSWORD: "changeme"

---
# authbridge-config ConfigMap - Used by envoy-proxy for token exchange
Expand Down
16 changes: 12 additions & 4 deletions AuthBridge/demos/webhook/k8s/configmaps-webhook.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,19 @@ data:
SPIRE_ENABLED: "true"
KEYCLOAK_URL: "http://keycloak-service.keycloak.svc:8080"
KEYCLOAK_REALM: "demo"
# Demo/development only: do NOT use hardcoded admin credentials in production.
# For production deployments, supply these via a Kubernetes Secret and reference
# them from your Pod/Deployment using env.valueFrom.secretKeyRef instead of this ConfigMap.

---
# keycloak-admin-secret - Keycloak admin credentials for client registration
# Replace the placeholder values with your actual admin credentials.
apiVersion: v1
kind: Secret
metadata:
name: keycloak-admin-secret
namespace: team1
type: Opaque
stringData:
KEYCLOAK_ADMIN_USERNAME: "admin"
KEYCLOAK_ADMIN_PASSWORD: "admin"
KEYCLOAK_ADMIN_PASSWORD: "changeme"

---
# authbridge-config ConfigMap - Used by envoy-proxy for token exchange and inbound validation
Expand Down
13 changes: 7 additions & 6 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -196,12 +196,13 @@ Hooks:

When the webhook injects sidecars, the target namespace needs these ConfigMaps:

| ConfigMap | Used by | Keys |
|-----------|---------|------|
| `environments` | client-registration | `KEYCLOAK_URL`, `KEYCLOAK_REALM`, `KEYCLOAK_ADMIN_USERNAME`, `KEYCLOAK_ADMIN_PASSWORD` |
| `authbridge-config` | envoy-proxy (ext-proc) | `TOKEN_URL`, `ISSUER`, `TARGET_AUDIENCE`, `TARGET_SCOPES` |
| `spiffe-helper-config` | spiffe-helper | SPIFFE helper configuration file |
| `envoy-config` | envoy-proxy | Envoy YAML configuration |
| Resource | Kind | Used by | Keys |
|----------|------|---------|------|
| `environments` | ConfigMap | client-registration | `KEYCLOAK_URL`, `KEYCLOAK_REALM` |
| `keycloak-admin-secret` | Secret | client-registration | `KEYCLOAK_ADMIN_USERNAME`, `KEYCLOAK_ADMIN_PASSWORD` |
| `authbridge-config` | ConfigMap | envoy-proxy (ext-proc) | `TOKEN_URL`, `ISSUER`, `TARGET_AUDIENCE`, `TARGET_SCOPES` |
| `spiffe-helper-config` | ConfigMap | spiffe-helper | SPIFFE helper configuration file |
| `envoy-config` | ConfigMap | envoy-proxy | Envoy YAML configuration |

## Common Development Tasks

Expand Down
3 changes: 3 additions & 0 deletions charts/kagenti-webhook/templates/clusterrole.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@ rules:
- apiGroups: [""]
resources: ["configmaps"]
verbs: ["get", "list", "watch"]
- apiGroups: [""]
resources: ["secrets"]
verbs: ["get", "list", "watch"]
- apiGroups: [""]
resources: ["serviceaccounts"]
verbs: ["get", "create", "update"]
Expand Down
11 changes: 8 additions & 3 deletions kagenti-webhook/CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -149,13 +149,18 @@ make generate
- **Container existence checks**: `containerExists()` and `volumeExists()` helpers prevent duplicate injection.
- **Kubebuilder markers**: Webhook path markers (e.g., `+kubebuilder:webhook:path=...`) in Go comments generate the webhook manifests. Do not change these without running `make manifests`.

### ConfigMap Dependencies at Runtime
Injected sidecars expect these ConfigMaps to exist in the target namespace:
- `environments` -- `KEYCLOAK_URL`, `KEYCLOAK_REALM`, `KEYCLOAK_ADMIN_USERNAME`, `KEYCLOAK_ADMIN_PASSWORD`
### Runtime Dependencies
Injected sidecars expect these resources to exist in the target namespace:

ConfigMaps:
- `environments` -- `KEYCLOAK_URL`, `KEYCLOAK_REALM`
- `authbridge-config` -- `TOKEN_URL`, `ISSUER`, `TARGET_AUDIENCE`, `TARGET_SCOPES`
- `spiffe-helper-config` -- SPIFFE helper configuration (when SPIRE is enabled)
- `envoy-config` -- Envoy proxy configuration

Secrets:
- `keycloak-admin-secret` -- `KEYCLOAK_ADMIN_USERNAME`, `KEYCLOAK_ADMIN_PASSWORD`

### Security Model
- `proxy-init` runs as an init container with a short lifetime (iptables setup).
- `envoy-proxy` runs as UID 1337.
Expand Down
3 changes: 3 additions & 0 deletions kagenti-webhook/config/rbac/role.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@ rules:
- apiGroups: [""]
resources: ["configmaps"]
verbs: ["get", "list", "watch"]
- apiGroups: [""]
resources: ["secrets"]
verbs: ["get", "list", "watch"]
- apiGroups: [""]
resources: ["serviceaccounts"]
verbs: ["get", "create", "update"]
Original file line number Diff line number Diff line change
Expand Up @@ -135,9 +135,9 @@ func (b *ContainerBuilder) BuildClientRegistrationContainerWithSpireOption(name,
{
Name: "KEYCLOAK_ADMIN_USERNAME",
ValueFrom: &corev1.EnvVarSource{
ConfigMapKeyRef: &corev1.ConfigMapKeySelector{
SecretKeyRef: &corev1.SecretKeySelector{
LocalObjectReference: corev1.LocalObjectReference{
Name: "environments",
Name: "keycloak-admin-secret",
},
Key: "KEYCLOAK_ADMIN_USERNAME",
},
Expand All @@ -146,9 +146,9 @@ func (b *ContainerBuilder) BuildClientRegistrationContainerWithSpireOption(name,
{
Name: "KEYCLOAK_ADMIN_PASSWORD",
ValueFrom: &corev1.EnvVarSource{
ConfigMapKeyRef: &corev1.ConfigMapKeySelector{
SecretKeyRef: &corev1.SecretKeySelector{
LocalObjectReference: corev1.LocalObjectReference{
Name: "environments",
Name: "keycloak-admin-secret",
},
Key: "KEYCLOAK_ADMIN_PASSWORD",
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -107,3 +107,48 @@ func TestBuildEnvoyProxyContainer_Name(t *testing.T) {
t.Errorf("container name = %q, want %q", container.Name, EnvoyProxyContainerName)
}
}

func TestBuildClientRegistrationContainer_AdminCredentialsFromSecret(t *testing.T) {
builder := NewContainerBuilder(config.CompiledDefaults())
container := builder.BuildClientRegistrationContainer("my-app", "my-ns")

sensitiveKeys := []string{"KEYCLOAK_ADMIN_USERNAME", "KEYCLOAK_ADMIN_PASSWORD"}
for _, key := range sensitiveKeys {
for _, env := range container.Env {
if env.Name != key {
continue
}
if env.ValueFrom == nil || env.ValueFrom.SecretKeyRef == nil {
t.Errorf("env %q must use SecretKeyRef, got ConfigMapKeyRef or literal", key)
continue
}
if env.ValueFrom.SecretKeyRef.Name != "keycloak-admin-secret" {
t.Errorf("env %q SecretKeyRef.Name = %q, want %q", key, env.ValueFrom.SecretKeyRef.Name, "keycloak-admin-secret")
}
if env.ValueFrom.ConfigMapKeyRef != nil {
t.Errorf("env %q must NOT use ConfigMapKeyRef", key)
}
}
}
}

func TestBuildClientRegistrationContainer_NonSensitiveKeysFromConfigMap(t *testing.T) {
builder := NewContainerBuilder(config.CompiledDefaults())
container := builder.BuildClientRegistrationContainer("my-app", "my-ns")

nonSensitiveKeys := []string{"KEYCLOAK_URL", "KEYCLOAK_REALM"}
for _, key := range nonSensitiveKeys {
for _, env := range container.Env {
if env.Name != key {
continue
}
if env.ValueFrom == nil || env.ValueFrom.ConfigMapKeyRef == nil {
t.Errorf("env %q must use ConfigMapKeyRef", key)
continue
}
if env.ValueFrom.ConfigMapKeyRef.Name != "environments" {
t.Errorf("env %q ConfigMapKeyRef.Name = %q, want %q", key, env.ValueFrom.ConfigMapKeyRef.Name, "environments")
}
}
}
}
Loading