Install the aapm-sidecar Injector
The Injector is a mutating admission webhook that automatically adds an aapm-client container to pods created in labeled namespaces. This webhook has cluster-wide authorization (ClusterRole/ClusterRoleBinding); because of this, only one instance can run per cluster (identically-named cluster-scoped resources would conflict).
Create and label the target namespace
The aapm-injection=enabled label tells the injector to inject pods in this namespace.
kubectl create namespace <TARGET_NAMESPACE>
kubectl label namespace <TARGET_NAMESPACE> aapm-injection=enabledCreate the secret file
This file defines which secrets the aapm-client container will fetch, from which Kron PAM account, using which token.
Secret File Fields | |
|---|---|
Field | Meaning |
userLabel | Determines the output filename: /keystore/{userLabel}.env. A free-form label. |
secret | The account name in Kron PAM. |
token | The Kron PAM access token (typically in GUID format). |
accPath | The account's path within Kron PAM. |
cat <<'EOF' > /tmp/application-aapm-client.yml
aapm:
client:
poll-interval-ms: 30000
secrets:
- userLabel: "<LABEL>"
secret: "<ACCOUNT_NAME>"
token: "<KRON_PAM_TOKEN>"
accPath: "<ACCOUNT_PATH>"
EOF
kubectl create secret generic aapm-client-secret \
--namespace <TARGET_NAMESPACE> \
--from-file=application-aapm-client.yml=/tmp/application-aapm-client.ymlInstall the injector
Injector Parameters | |
|---|---|
Parameter | Meaning |
namespace.name | The Injector's own namespace — required, the ClusterRoleBinding's ServiceAccount reference is derived from it. |
aapmConnection.directAccessUrl | Kron PAM's direct URL — required, if missing the sidecar won't start. |
aapmConnection.ignoreCertificate | Must be true for the Agent connection (due to the self-signed certificate). |
sidecarImage.tag | The version of the aapm-client image to inject. Use a tag verified to work in your environment — the chart default may not be compatible everywhere (for example, architecture mismatch). |
helm install kron-aapm-sidecar kron-pam/kron-aapm-sidecar \
--namespace ns-sidecar \
--create-namespace \
--set namespace.name=ns-sidecar \
--set aapmConnection.agentService="kron-aapm-agent.ns-agent.svc.cluster.local" \
--set aapmConnection.agentPort="8080" \
--set aapmConnection.directAccessUrl="https://<KRON_PAM_SERVER_ADDRESS>" \
--set aapmConnection.ignoreCertificate=true \
--set aapmConnection.ignoreInterceptorCertificate=false \
--set sidecarImage.tag="<VERIFIED_IMAGE_TAG>"Verification
kubectl get pods -n ns-sidecar
kubectl logs -n ns-sidecar deploy/kron-aapm-sidecar --tail=20Success criteria: Pod is Running, logs show Webhook server started on port 8443.
Excluding a Pod from Injection
Injection applies to every pod created in a namespace labeled aapm-injection=enabled. To opt a specific pod out, add the following annotation to the pod template:
annotations:
aapm-sidecar-injector.kron.com/inject: "false"Defining Multiple Secrets
More than one entry can be defined under aapm.client.secrets. Each entry produces its own file, named after its userLabel:
aapm:
client:
poll-interval-ms: 30000
secrets:
- userLabel: "db-user"
secret: "<ACCOUNT_NAME_1>"
token: "<KRON_PAM_TOKEN_1>"
accPath: "<ACCOUNT_PATH_1>"
- userLabel: "api-user"
secret: "<ACCOUNT_NAME_2>"
token: "<KRON_PAM_TOKEN_2>"
accPath: "<ACCOUNT_PATH_2>"This produces /keystore/db-user.env and /keystore/api-user.env.
How the Application Reads the Secret
The aapm-client container writes the retrieved secrets into a shared emptyDir volume mounted at /keystore. The application container in the same pod reads the .env file from that path. The secrets are refreshed on every polling cycle (poll-interval-ms, default 30000 ms), so a rotated credential in Kron PAM reaches the pod without a restart.
The aapm-client-secret content is read only at pod startup. Updating the Kubernetes Secret doesn't affect running pods — the pod must be deleted and recreated, or the Deployment restarted, for the new configuration to take effect.
Each target namespace requires its own aapm-client-secret. A single injector can serve any number of labeled namespaces, but the secret is namespace-scoped and isn't copied automatically.