Skip to content
Open
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
49 changes: 49 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -591,6 +591,55 @@ control:

The provider's `[auth.<provider>]` section still has to render for the login route to be enabled, so keep at least one inline field (`client_id`, `allowed_orgs`/`allowed_domains`) or the `secret` block set under the provider. Env vars sourced this way are not hashed into the deployment's `checksum/config` annotation — rotating the referenced Secret needs a manual `kubectl rollout restart deployment/<release>-control`.

#### Sourcing cookie_secret from external-secrets

Instead of the chart's random-generate-and-reuse `cookie_secret` (see above), you
can source it from a Secret managed by the [external-secrets](https://external-secrets.io)
operator.

**Option 1: Create the ExternalSecret with the chart**

```yaml
control:
externalSecrets:
enabled: true
create: true
secretStoreRef:
name: aws-secrets-manager
kind: SecretStore
remoteRefs:
- secretKey: cookie_secret
remoteRef:
key: pgdog/control
property: cookie_secret
```

**Option 2: Use an existing ExternalSecret**

```yaml
control:
externalSecrets:
enabled: true
create: false
secretName: "my-secret" # Name of Secret you created/manage
```

In both cases, leave `config.auth.cookie_secret` unset — the chart looks up the
`cookie_secret` key of the target Secret (`control.externalSecrets.secretName`,
default `<release>-secrets`) at render time and inlines it into `control.toml`,
the same way it does for its own auto-generated secret. `helm upgrade` picks up
rotated values automatically since the `lookup` re-runs on every render.

| Option | Description |
|-|-|
| `control.externalSecrets.enabled` | Source `cookie_secret` from a Secret instead of the chart's random one (bool, default `false`). |
| `control.externalSecrets.create` | Render an `ExternalSecret` resource (bool, default `true`). Set to `false` to reference one you manage yourself. |
| `control.externalSecrets.name` | Name of the `ExternalSecret` resource (only used when `create: true`; defaults to `<release>-control`). |
| `control.externalSecrets.secretName` | Name of the target `Secret` populated by the `ExternalSecret`, expected to contain a `cookie_secret` key (defaults to `<release>-secrets`). |
| `control.externalSecrets.refreshInterval` | How often the operator resyncs from the external store (only used when `create: true`; default `1h`). |
| `control.externalSecrets.secretStoreRef` | `{name, kind}` of the `SecretStore`/`ClusterSecretStore` to use (only used when `create: true`). |
| `control.externalSecrets.remoteRefs` | List of `{secretKey, remoteRef: {key, property}}` entries defining what to fetch (only used when `create: true`). |

### Helm

When the dashboard provisions a new PgDog cluster, it shells out to `helm upgrade --install` against a chart fetched from our Helm repository. `control.config.helm` controls which chart and which repository. The defaults point at the public `pgdogdev` chart on `helm.pgdog.dev`, which is what you want unless you mirror the chart internally.
Expand Down
10 changes: 10 additions & 0 deletions templates/_helpers.tpl
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,16 @@ the same cluster don't collide.
{{- printf "%s-redis" .Release.Name | trunc 63 | trimSuffix "-" }}
{{- end }}

{{/*
Name of the Secret expected to hold the cookie_secret key: either the
chart's own randomly generated Secret, or the Secret targeted by
control.externalSecrets (populated by the chart-managed ExternalSecret,
or by one the user manages themselves).
*/}}
{{- define "pgdog-control.secretsName" -}}
{{- default (printf "%s-secrets" .Release.Name) .Values.control.externalSecrets.secretName }}
{{- end }}

{{/*
ServiceAccount name for the control component. Falls back to the
control fullname when not explicitly set in values.
Expand Down
2 changes: 1 addition & 1 deletion templates/configmap.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
{{- if $auth.cookie_secret -}}
{{- $cookieSecret = $auth.cookie_secret -}}
{{- else -}}
{{- $existing := (lookup "v1" "Secret" .Release.Namespace (printf "%s-secrets" .Release.Name)) | default dict -}}
{{- $existing := (lookup "v1" "Secret" .Release.Namespace (include "pgdog-control.secretsName" .)) | default dict -}}
{{- $existingData := $existing.data | default dict -}}
{{- if hasKey $existingData "cookie_secret" -}}
{{- $cookieSecret = index $existingData "cookie_secret" | b64dec -}}
Expand Down
31 changes: 31 additions & 0 deletions templates/externalsecret.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
{{- if and .Values.control.externalSecrets.enabled .Values.control.externalSecrets.create }}
apiVersion: {{ if .Capabilities.APIVersions.Has "external-secrets.io/v1" }}external-secrets.io/v1{{ else }}external-secrets.io/v1beta1{{ end }}
kind: ExternalSecret
metadata:
name: {{ default (include "pgdog-control.control.fullname" .) .Values.control.externalSecrets.name }}
labels:
{{- include "pgdog-control.labels" . | nindent 4 }}
spec:
refreshInterval: {{ .Values.control.externalSecrets.refreshInterval }}
secretStoreRef:
name: {{ .Values.control.externalSecrets.secretStoreRef.name }}
kind: {{ .Values.control.externalSecrets.secretStoreRef.kind }}
target:
name: {{ include "pgdog-control.secretsName" . }}
creationPolicy: Owner
{{- if .Values.control.externalSecrets.remoteRefs }}
data:
{{- range .Values.control.externalSecrets.remoteRefs }}
- secretKey: {{ .secretKey }}
remoteRef:
key: {{ .remoteRef.key }}
{{- if .remoteRef.property }}
property: {{ .remoteRef.property }}
{{- end }}
{{- end }}
{{- else }}
# Default: fetch cookie_secret from external secret store
# Configure remoteRefs in values.yaml for your specific secret store
data: []
{{- end }}
{{- end }}
7 changes: 4 additions & 3 deletions templates/secrets.yaml
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
{{- $config := .Values.control.config | default dict -}}
{{- $auth := $config.auth | default dict -}}
{{- if not $auth.cookie_secret -}}
{{- $existing := (lookup "v1" "Secret" .Release.Namespace (printf "%s-secrets" .Release.Name)) | default dict -}}
{{/* Skip the chart-generated random secret when externalSecrets supplies cookie_secret instead. */}}
{{- if and (not $auth.cookie_secret) (not .Values.control.externalSecrets.enabled) -}}
{{- $existing := (lookup "v1" "Secret" .Release.Namespace (include "pgdog-control.secretsName" .)) | default dict -}}
{{- $existingData := $existing.data | default dict -}}
apiVersion: v1
kind: Secret
metadata:
name: {{ .Release.Name }}-secrets
name: {{ include "pgdog-control.secretsName" . }}
labels:
{{- include "pgdog-control.labels" . | nindent 4 }}
type: Opaque
Expand Down
15 changes: 15 additions & 0 deletions test/values-external-secrets.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
control:
externalSecrets:
enabled: true
create: true
secretStoreRef:
name: aws-secrets-manager
kind: SecretStore
remoteRefs:
- secretKey: cookie_secret
remoteRef:
key: pgdog/control
property: cookie_secret
config:
auth:
redirect_base_url: https://control.example.com
40 changes: 39 additions & 1 deletion values.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,42 @@ control:
# means no write access anywhere — list the release namespace
# explicitly if you want control to manage workloads alongside itself.
writeNamespaces: []
# externalSecrets sources config.auth.cookie_secret from a Secret managed
# by the external-secrets operator (https://external-secrets.io) instead
# of the chart's own randomly generated one. See config.auth.cookie_secret
# below for how the value is picked up once synced.
externalSecrets:
# enabled switches cookie_secret sourcing to the Secret named below,
# instead of the chart-managed random secret.
enabled: false
# create controls whether the chart renders an ExternalSecret resource.
# Set to false to reference an ExternalSecret you already manage
# yourself (only secretName is then used).
create: true
# name of the ExternalSecret resource to create (only used when
# create: true). Defaults to `<release>-control`.
name: ""
# secretName is the target Secret populated by the ExternalSecret (or
# by your own ExternalSecret when create: false). Must contain a
# cookie_secret key. Defaults to `<release>-secrets`, the same name the
# chart would otherwise use for its own generated secret.
secretName: ""
# refreshInterval defines how often to sync secrets from external
# source (only used when create: true)
refreshInterval: 1h
# secretStoreRef references the SecretStore to use
# (only used when create: true)
secretStoreRef:
name: ""
kind: SecretStore
# remoteRefs defines the external secret references
# (only used when create: true)
remoteRefs: []
# Example structure:
# - secretKey: cookie_secret
# remoteRef:
# key: pgdog/control
# property: cookie_secret
resources:
requests:
memory: "256Mi"
Expand Down Expand Up @@ -118,7 +154,9 @@ control:
# repo: pgdogdev
# repo_url: https://helm.pgdog.dev
auth: {}
# cookie_secret: "" # optional; random key generated at boot when absent
# cookie_secret: "" # optional; random key generated at boot when absent.
# # To source it from external-secrets instead, leave
# # this unset and configure control.externalSecrets above.
# redirect_base_url: "" # e.g. https://control.example.com
# cookie_secure: true
# session_max_age_days: 30
Expand Down
Loading