Skip to content

Create enforcement secret in kuadrant namespace on APIKey approval #47

@eguzki

Description

@eguzki

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":

  1. Check if enforcement secret exists in kuadrant namespace
  2. 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
  3. If it already exists: Do nothing (no reconciliation of secret value)

Denial Flow

When APIKey has Denied condition with status="True":

  1. Check if enforcement secret exists in kuadrant namespace
  2. If it exists: Delete it
  3. 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

  1. If consumer's secret doesn't exist during approval:
    • Set Failed condition with reason "SecretNotFound"
    • Do not create enforcement secret
  2. If consumer's secret cannot be read:
    • Set Failed condition with reason "SecretReadError"
  3. If enforcement secret creation fails:
    • Set Failed condition with reason "EnforcementSecretCreationFailed"

Acceptance Criteria

  • Design a mapping system between APIKey and enforcement secret name that prevents collisions (e.g., two APIKeys named "my-key" in different namespaces must create different enforcement secrets)
  • Controller watches APIKey resources cluster-wide
  • On Approved condition: Check if enforcement secret exists in kuadrant namespace
  • On Approved condition: If secret doesn't exist, read from consumer's secret and create enforcement secret
  • On Approved condition: If secret already exists, do nothing (no value reconciliation)
  • On Denied condition: Delete enforcement secret if it exists
  • NEVER modifies consumer's secret (consumer-owned, read-only for controller)
  • Handles APIKey deletion (explicit cleanup of enforcement secret, no ownerReferences)
  • Sets Failed condition if consumer's secret is missing or unreadable
  • Sets Failed condition if enforcement secret creation fails
  • Enforcement secret includes proper 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
  • Add unit tests for secret creation on approval
  • Add unit tests for secret deletion on denial
  • Add unit tests for naming collision prevention
  • Add integration tests for approval → creation and denial → deletion flows
  • Add e2e tests for complete workflow

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.

Metadata

Metadata

Assignees

Labels

enhancementNew feature or request

Type

No type

Projects

Status

Todo

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions