Description
When an APIKey is approved, the controller should check for the existence of an enforcement secret in the kuadrant namespace and create it if it doesn't exist. When an APIKey is denied, the controller should delete the enforcement secret.
Background
The RBAC design separates API key storage into two locations:
- Consumer's secret (in consumer's namespace): Created and owned by consumer, referenced via
APIKey.spec.secretRef, never modified by controller
- Enforcement secret (in kuadrant namespace): Created by controller on approval, used by Authorino/Limitador for policy enforcement
Implementation Details
Approval Flow
When APIKey has Approved condition with status="True":
- Check if enforcement secret exists in kuadrant namespace
- If it does NOT exist:
- Read API key value from consumer's secret (
APIKey.spec.secretRef)
- Create enforcement secret with API key value + policy metadata + labels for Authorino
- If it already exists: Do nothing (no reconciliation of secret value)
Denial Flow
When APIKey has Denied condition with status="True":
- Check if enforcement secret exists in kuadrant namespace
- If it exists: Delete it
- Consumer's secret is NEVER touched (consumer-owned)
Pending/Failed States
When APIKey has no conditions (Pending) or Failed condition:
- Do NOT create enforcement secret
- If one exists from a previous approval, leave it (cleanup only on explicit denial)
Enforcement Secret Format
apiVersion: v1
kind: Secret
metadata:
name: <derived-from-apikey-mapping-system> # See acceptance criteria for naming design
namespace: kuadrant # Centralized enforcement namespace
labels:
devportal.kuadrant.io/apiproduct: "<apiproduct-name>"
devportal.kuadrant.io/apikey: "<apikey-name>"
devportal.kuadrant.io/apikey-namespace: "<apikey-namespace>"
authorino.kuadrant.io/managed-by: "authorino"
# Note: ownerReferences cannot be cross-namespace
# Controller must handle cleanup when APIKey is deleted
type: Opaque
data:
api_key: <base64-encoded-value-from-consumer-secret>
# Additional policy metadata as needed
Error Handling
- If consumer's secret doesn't exist during approval:
- Set
Failed condition with reason "SecretNotFound"
- Do not create enforcement secret
- If consumer's secret cannot be read:
- Set
Failed condition with reason "SecretReadError"
- If enforcement secret creation fails:
- Set
Failed condition with reason "EnforcementSecretCreationFailed"
Acceptance Criteria
Related
RBAC Requirements
Controller ServiceAccount needs:
- Cluster-wide
get, list, watch on secrets (to read consumer secrets)
create, delete on secrets in kuadrant namespace only (via RoleBinding for enforcement secrets)
- Cluster-wide
get, list, watch on apikeys
- Cluster-wide
update, patch on apikeys/status (to set error conditions)
Notes
One-time creation: The enforcement secret is created once on approval. If the consumer changes their secret value, the enforcement secret is NOT updated. Consumer must delete and recreate the APIKey for key rotation.
Security isolation: Controller is the only component that creates enforcement secrets. Owners and consumers do NOT have access to enforcement secrets in kuadrant namespace.
Consumer ownership: Consumer's secret is never modified or deleted by the controller. It is entirely consumer-owned.
Naming collision prevention: Multiple APIKeys with the same name in different namespaces must map to unique enforcement secret names to prevent overwrites and data loss.
Description
When an APIKey is approved, the controller should check for the existence of an enforcement secret in the kuadrant namespace and create it if it doesn't exist. When an APIKey is denied, the controller should delete the enforcement secret.
Background
The RBAC design separates API key storage into two locations:
APIKey.spec.secretRef, never modified by controllerImplementation Details
Approval Flow
When APIKey has
Approvedcondition with status="True":APIKey.spec.secretRef)Denial Flow
When APIKey has
Deniedcondition with status="True":Pending/Failed States
When APIKey has no conditions (Pending) or
Failedcondition:Enforcement Secret Format
Error Handling
Failedcondition with reason "SecretNotFound"Failedcondition with reason "SecretReadError"Failedcondition with reason "EnforcementSecretCreationFailed"Acceptance Criteria
Approvedcondition: Check if enforcement secret exists in kuadrant namespaceApprovedcondition: If secret doesn't exist, read from consumer's secret and create enforcement secretApprovedcondition: If secret already exists, do nothing (no value reconciliation)Deniedcondition: Delete enforcement secret if it existsFailedcondition if consumer's secret is missing or unreadableFailedcondition if enforcement secret creation failsdevportal.kuadrant.io/apiproduct: APIProduct namedevportal.kuadrant.io/apikey: APIKey namedevportal.kuadrant.io/apikey-namespace: APIKey namespaceauthorino.kuadrant.io/managed-by: authorinoRelated
RBAC Requirements
Controller ServiceAccount needs:
get, list, watchon secrets (to read consumer secrets)create, deleteon secrets in kuadrant namespace only (via RoleBinding for enforcement secrets)get, list, watchon apikeysupdate, patchon apikeys/status (to set error conditions)Notes
One-time creation: The enforcement secret is created once on approval. If the consumer changes their secret value, the enforcement secret is NOT updated. Consumer must delete and recreate the APIKey for key rotation.
Security isolation: Controller is the only component that creates enforcement secrets. Owners and consumers do NOT have access to enforcement secrets in kuadrant namespace.
Consumer ownership: Consumer's secret is never modified or deleted by the controller. It is entirely consumer-owned.
Naming collision prevention: Multiple APIKeys with the same name in different namespaces must map to unique enforcement secret names to prevent overwrites and data loss.