# Default values for certctl Helm chart
# This is a YAML-formatted file.
# Declare variables to be passed into your templates.

# Namespace override (optional)
namespace: ""

# Global configuration
commonLabels: {}
imagePullSecrets: []
nameOverride: ""
fullnameOverride: ""

# ==============================================================================
# Certctl Server Configuration
# ==============================================================================
server:
  # Number of replicas (for HA deployments)
  replicas: 1

  # Image configuration
  image:
    repository: ghcr.io/certctl-io/certctl
    tag: "" # defaults to Chart.appVersion
    pullPolicy: IfNotPresent

  # Server port
  port: 8443

  # Resource requests and limits
  resources:
    requests:
      cpu: 100m
      memory: 128Mi
    limits:
      cpu: 500m
      memory: 512Mi

  # Pod security context
  securityContext:
    runAsNonRoot: true
    runAsUser: 1000
    runAsGroup: 1000
    fsGroup: 1000
    readOnlyRootFilesystem: true
    allowPrivilegeEscalation: false
    capabilities:
      drop:
        - ALL

  # Liveness and readiness probes (HTTPS-only as of v2.2).
  #
  # The two paths exposed for probes are `/health` and `/ready` —
  # registered in internal/api/router/router.go:76-85 and bypassing the
  # auth middleware via the no-auth list at cmd/server/main.go:920.
  # Both serve the same JSON shape today (`{"status":"healthy"}` /
  # `{"status":"ready"}`) but exist as separate routes so liveness and
  # readiness can diverge in the future without renaming.
  livenessProbe:
    httpGet:
      path: /health
      port: https
      scheme: HTTPS
    initialDelaySeconds: 10
    periodSeconds: 10
    timeoutSeconds: 5
    failureThreshold: 3

  # U-2 (P1, cat-u-healthcheck_protocol_mismatch — adjacent fix): pre-U-2
  # the readiness probe pointed at `/readyz`, the conventional kube-flavor
  # name. The certctl server doesn't register `/readyz` (only `/health`
  # and `/ready`) — see cmd/server/main.go:920 and
  # internal/api/router/router.go:81. K8s readiness probes therefore
  # received a 404 (or, with auth enabled, a 401 from the api-key middleware
  # because `/readyz` was NOT in the no-auth bypass set), pods stayed
  # `NotReady` indefinitely, and Helm rollouts stalled. Post-U-2 the path
  # matches a registered route.
  readinessProbe:
    httpGet:
      path: /ready
      port: https
      scheme: HTTPS
    initialDelaySeconds: 5
    periodSeconds: 5
    timeoutSeconds: 3
    failureThreshold: 2

  # TLS configuration — REQUIRED. HTTPS is the only supported mode (v2.2+).
  # Operator must configure EXACTLY ONE of:
  #   (a) server.tls.existingSecret: <name>        # pre-existing kubernetes.io/tls Secret
  #   (b) server.tls.certManager.enabled: true     # provision a cert-manager Certificate CR
  # Refusing to set either makes `helm template` fail with a diagnostic pointing at docs/tls.md.
  tls:
    # Name of a pre-existing Secret (type kubernetes.io/tls) holding tls.crt + tls.key (+ optional ca.crt).
    # Leave empty to fall through to the cert-manager path.
    existingSecret: ""

    # Mount path for the TLS Secret inside the server + agent containers.
    mountPath: /etc/certctl/tls

    # cert-manager auto-provisioning. Opt-in (off by default per milestone §3.4).
    certManager:
      enabled: false

      # Secret name the cert-manager Certificate CR writes into. Agents and the server
      # both read from this Secret. If empty, defaults to "<fullname>-tls".
      secretName: ""

      # Cert-manager issuer reference.
      issuerRef:
        name: ""                      # e.g. "letsencrypt-prod" or "internal-ca"
        kind: ClusterIssuer           # ClusterIssuer or Issuer
        group: cert-manager.io

      # Subject fields on the issued cert.
      commonName: "certctl-server"
      dnsNames:
        - certctl-server
        - localhost

      # Certificate lifetime + renewal window.
      duration: 2160h                 # 90 days
      renewBefore: 360h               # 15 days

  # Service type (ClusterIP, LoadBalancer, NodePort)
  service:
    type: ClusterIP
    port: 8443
    annotations: {}

  # Authentication configuration.
  # Valid types: "api-key" (production) or "none" (demo only — disables
  # authentication on the API and logs a loud Warn at server startup).
  # For JWT/OIDC, run an authenticating gateway in front of certctl
  # (oauth2-proxy / Envoy ext_authz / Traefik ForwardAuth / Pomerium)
  # and set type=none here so the gateway terminates federated identity.
  # See docs/architecture.md "Authenticating-gateway pattern".
  #
  # G-1 (P1): pre-G-1 the chart accepted server.auth.type=jwt and the
  # certctl-server container silently routed every request through the
  # api-key bearer middleware — silent auth downgrade. Post-G-1 the
  # chart's `certctl.validateAuthType` template helper rejects any value
  # outside {api-key, none} at template time. See
  # docs/upgrade-to-v2-jwt-removal.md if you previously set type=jwt.
  auth:
    type: api-key
    apiKey: ""     # REQUIRED when type=api-key (set via --set or values override).

  # Logging configuration
  logging:
    level: info  # debug, info, warn, error
    format: json  # json or text

  # SMTP configuration for email notifications (optional)
  smtp:
    enabled: false
    host: ""
    port: 587
    username: ""
    password: ""
    fromAddress: ""
    useTLS: true

  # Certificate digest digest (periodic email summary)
  digest:
    enabled: false
    interval: "24h"
    recipients: []
    # Example:
    # - admin@example.com
    # - ops@example.com

  # Enrollment over Secure Transport (EST) configuration
  est:
    enabled: false
    issuerID: "iss-local"
    profileID: ""

  # Rate limiting configuration
  rateLimiting:
    rps: 100      # Requests per second
    burst: 200    # Burst capacity

  # Network scanning configuration
  networkScan:
    enabled: false
    interval: "6h"

  # Certificate key generation mode
  keygen:
    mode: agent   # Options: agent (production), server (demo with warning)

  # CORS configuration
  cors:
    origins: ""   # Comma-separated list, empty means deny all cross-origin requests

  # Issuer connectors configuration
  issuer:
    local:
      enabled: true
      # For sub-CA mode, provide these paths:
      # caCertPath: /path/to/ca.crt
      # caKeyPath: /path/to/ca.key

    acme:
      enabled: false
      directoryURL: ""
      email: ""
      challengeType: "http-01"  # Options: http-01, dns-01, dns-persist-01
      # DNS configuration (for dns-01 or dns-persist-01)
      # dnsPresentScript: /path/to/dns-present.sh
      # dnsCleanupScript: /path/to/dns-cleanup.sh
      # dnsPropagationWait: "30s"
      # dnsPersistIssuerDomain: "validation.example.com"
      # EAB configuration (for ZeroSSL, Google Trust Services, etc.)
      # eabKid: ""
      # eabHmac: ""

    stepca:
      enabled: false
      # rootCAPath: /path/to/root_ca.crt
      # intermediateCAPath: /path/to/intermediate_ca.crt
      # provisionerName: ""
      # provisionerPassword: ""

    openssl:
      enabled: false
      # signScript: /path/to/sign.sh
      # revokeScript: /path/to/revoke.sh
      # crlScript: /path/to/crl.sh
      # timeoutSeconds: 30

  # Notifier connectors configuration
  notifiers:
    slack:
      enabled: false
      # webhookUrl: ""
      # channel: ""
      # username: ""
      # iconEmoji: ""

    teams:
      enabled: false
      # webhookUrl: ""

    pagerduty:
      enabled: false
      # routingKey: ""
      # severity: warning

    opsgenie:
      enabled: false
      # apiKey: ""
      # priority: P3

  # Additional environment variables
  # Will be passed as-is to the server container
  env: {}
  # Example:
  # CERTCTL_SCHEDULER_RENEWAL_CHECK_INTERVAL: "1h"
  # CERTCTL_DATABASE_MAX_CONNS: "25"

  # Additional volume mounts for custom configurations
  # volumeMounts: []
  # - name: ca-cert
  #   mountPath: /etc/ssl/certs/ca.crt
  #   subPath: ca.crt

  # Additional volumes
  # volumes: []
  # - name: ca-cert
  #   secret:
  #     secretName: ca-cert

# ==============================================================================
# PostgreSQL Configuration
# ==============================================================================
postgresql:
  # Enable/disable PostgreSQL (set to false if using external database)
  enabled: true

  # Image configuration
  image:
    repository: postgres
    tag: "16-alpine"
    pullPolicy: IfNotPresent

  # Authentication
  auth:
    database: certctl
    username: certctl
    # REQUIRED — set via `--set postgresql.auth.password=<value>` or values override.
    #
    # WARNING (U-1): rotating this value after first deploy does NOT change the
    # database password. The `postgres:16-alpine` image runs `initdb` only when
    # /var/lib/postgresql/data is empty, so POSTGRES_PASSWORD is written into
    # pg_authid exactly once — on the first boot of the StatefulSet's PVC.
    # Subsequent rollouts pick up the new env value in the postgres container
    # but the certctl-server container's CERTCTL_DATABASE_URL also picks up
    # the new value, while pg_authid still expects the old one — leading to
    # `pq: password authentication failed for user "certctl"` (SQLSTATE 28P01).
    #
    # The certctl-server emits guidance via internal/repository/postgres/db.go::
    # wrapPingError when it sees SQLSTATE 28P01 at startup. To resolve in a
    # Helm deployment:
    #   - Non-destructive (preferred for environments with data):
    #       kubectl exec -it <release>-postgres-0 -- \
    #         psql -U certctl -c "ALTER ROLE certctl PASSWORD '<new>';"
    #     then update the secret/values to match and let the certctl-server
    #     pod restart against the matching credential.
    #   - Destructive (DESTROYS DATA — only acceptable on dev/demo PVCs):
    #       helm uninstall <release> && \
    #       kubectl delete pvc -l app.kubernetes.io/name=certctl,app.kubernetes.io/component=postgres && \
    #       helm install <release> ...  # PVC re-creates empty, initdb seeds new password
    password: ""

  # ─────────────────────────────────────────────────────────────────────
  # Bundle B / Audit M-018 (PCI-DSS Req 4 / CWE-319): TLS to Postgres
  # ─────────────────────────────────────────────────────────────────────
  # postgresql.tls.mode is wired into the database-url sslmode parameter
  # (see templates/_helpers.tpl::certctl.databaseURL).
  #
  # Acceptable values (lib/pq):
  #   disable     — no TLS (default, preserves in-cluster pod-to-pod
  #                 traffic on the K8s pod network).
  #   require     — TLS required, no certificate verification.
  #   verify-ca   — TLS required + verify CA chain.
  #   verify-full — TLS required + verify CA chain + verify hostname.
  #
  # PCI-DSS Req 4 v4.0 §2.2.5 requires verify-ca or verify-full when the
  # database carries sensitive data crossing untrusted networks (RDS,
  # Cloud SQL, cross-VPC, etc). The bundled Helm Postgres runs in the
  # same pod network as certctl-server; sslmode=disable is acceptable
  # there only when the cluster CNI provides L2/L3 encryption (Cilium
  # WireGuard, Calico Wireguard, Tailscale operator, etc).
  #
  # When mode != disable AND tls.caSecretRef is set, the CA bundle is
  # mounted at /etc/postgresql-ca/ca.crt and the server's PGSSLROOTCERT
  # env points there. caSecretRef must reference an existing Secret with
  # a "ca.crt" key.
  tls:
    mode: disable
    # caSecretRef: ""  # Secret with ca.crt key (required for verify-ca/verify-full)

  # Storage configuration
  storage:
    size: 10Gi
    storageClass: ""  # Uses default StorageClass if empty
    # deleteOnTermination: false  # Keep data on Helm uninstall

  # Resource requests and limits
  resources:
    requests:
      cpu: 100m
      memory: 256Mi
    limits:
      cpu: 500m
      memory: 512Mi

  # Pod security context
  securityContext:
    runAsNonRoot: true
    runAsUser: 999
    runAsGroup: 999
    fsGroup: 999

  # Liveness and readiness probes
  livenessProbe:
    exec:
      command:
        - /bin/sh
        - -c
        - pg_isready -U certctl -d certctl
    initialDelaySeconds: 10
    periodSeconds: 10
    timeoutSeconds: 5
    failureThreshold: 3

  readinessProbe:
    exec:
      command:
        - /bin/sh
        - -c
        - pg_isready -U certctl -d certctl
    initialDelaySeconds: 5
    periodSeconds: 5
    timeoutSeconds: 3
    failureThreshold: 2

  # Service configuration
  service:
    type: ClusterIP
    port: 5432

  # PostgreSQL-specific settings
  postgresqlConfig: {}
  # Example:
  # max_connections: "200"
  # shared_buffers: "256MB"

# ==============================================================================
# Certctl Agent Configuration
# ==============================================================================
agent:
  # Enable/disable agent deployment
  enabled: true

  # Deployment strategy: DaemonSet (recommended) or Deployment
  kind: DaemonSet  # Options: DaemonSet, Deployment

  # Image configuration
  image:
    repository: ghcr.io/certctl-io/certctl-agent
    tag: ""  # defaults to Chart.appVersion
    pullPolicy: IfNotPresent

  # Number of replicas (for Deployment kind; ignored for DaemonSet)
  replicas: 1

  # Resource requests and limits
  resources:
    requests:
      cpu: 50m
      memory: 64Mi
    limits:
      cpu: 200m
      memory: 256Mi

  # Pod security context
  securityContext:
    runAsNonRoot: true
    runAsUser: 1000
    runAsGroup: 1000
    fsGroup: 1000
    readOnlyRootFilesystem: true
    allowPrivilegeEscalation: false
    capabilities:
      drop:
        - ALL

  # Agent name (can be overridden per pod via StatefulSet ordinals)
  name: ""  # If empty, uses release name

  # Key storage directory
  keyDir: /var/lib/certctl/keys

  # Certificate discovery directories (comma-separated)
  discoveryDirs: ""
  # Example: "/etc/ssl/certs,/etc/pki/tls"

  # Node selector for agent pods (for DaemonSet)
  nodeSelector: {}
  # Example:
  # node-role.kubernetes.io/worker: "true"

  # Tolerations for agent pods
  tolerations: []
  # Example:
  # - key: node-role
  #   operator: Equal
  #   value: worker
  #   effect: NoSchedule

  # Affinity rules
  affinity: {}

  # Additional environment variables
  env: {}

# ==============================================================================
# Ingress Configuration
# ==============================================================================
ingress:
  enabled: false
  className: ""
  annotations: {}
    # kubernetes.io/ingress.class: nginx

  # Optional cert-manager integration for the public-facing Ingress cert.
  # This is completely independent of server.tls.* — the Ingress terminates
  # an *additional* TLS hop between the internet and the in-cluster Service.
  # Leave disabled unless an Ingress is exposing certctl to the outside world.
  certManager:
    enabled: false
    issuerRef:
      name: ""                      # e.g. "letsencrypt-prod"
      kind: ClusterIssuer           # ClusterIssuer or Issuer
  hosts:
    - host: certctl.local
      paths:
        - path: /
          pathType: Prefix
  tls: []
    # - secretName: certctl-tls
    #   hosts:
    #     - certctl.local

# ==============================================================================
# Service Account Configuration
# ==============================================================================
serviceAccount:
  create: true
  annotations: {}
  name: ""  # defaults to release name if empty

# ==============================================================================
# RBAC Configuration
# ==============================================================================
rbac:
  create: true

# ==============================================================================
# Kubernetes Secrets Target Connector
# ==============================================================================
kubernetesSecrets:
  # Enable RBAC rules for managing TLS Secrets
  enabled: false

# ==============================================================================
# Pod Disruption Budget (for HA deployments)
# ==============================================================================
podDisruptionBudget:
  enabled: false
  minAvailable: 1
  # maxUnavailable: 1

# ==============================================================================
# Monitoring Configuration
# ==============================================================================
monitoring:
  enabled: false
  # Prometheus ServiceMonitor
  serviceMonitor:
    enabled: false
    interval: 30s
    scrapeTimeout: 10s
    # labels: {}
    # selector: {}

# ==============================================================================
# Advanced Configuration
# ==============================================================================

# Node affinity for server pods
nodeAffinity: {}

# Pod affinity for server pods
podAffinity: {}

# Pod anti-affinity for server pods (for HA)
podAntiAffinity: {}
# Example:
# podAntiAffinity:
#   preferredDuringSchedulingIgnoredDuringExecution:
#     - weight: 100
#       podAffinityTerm:
#         labelSelector:
#           matchExpressions:
#             - key: app.kubernetes.io/name
#               operator: In
#               values:
#                 - certctl
#         topologyKey: kubernetes.io/hostname

# Custom labels for all resources
customLabels: {}

# Custom annotations for all resources
customAnnotations: {}
