Skip to content
Merged
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
2 changes: 1 addition & 1 deletion charts/retool/Chart.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ apiVersion: v2
name: retool
description: A Helm chart for Kubernetes
type: application
version: 6.11.2
version: 6.11.3
maintainers:
- name: Retool Engineering
email: engineering+helm@retool.com
Expand Down
12 changes: 9 additions & 3 deletions charts/retool/ci/test-agent-sandbox-enabled-option.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,10 @@ rr:
# the image-prepuller + seccomp DaemonSets, the smarter-device-manager device
# plugin DaemonSet, the NetworkPolicies, and both PDBs.
#
# Secret/Postgres sourcing here uses externalSecret.name (Postgres OPTION 4:
# the secret's postgres-url key). The other secret/Postgres precedence paths and
# the same-origin (no-ingress) proxy mode are covered by sibling files:
# Secrets come from externalSecret.name (JWT/encryption); Postgres reads its DSN
# from that same Secret via postgres.urlSecretName (Option 3). The other
# secret/Postgres precedence paths and the same-origin (no-ingress) proxy mode
# are covered by sibling files:
# - test-agent-sandbox-inline-secrets-option.yaml (inline secrets, plaintext DSN, same-origin/no ingress, hostPath tun)
# - test-agent-sandbox-postgres-fields-option.yaml (assemble DSN from fields + PGPASSWORD secret)
# - test-agent-sandbox-postgres-url-secret-option.yaml (full DSN from an existing secret)
Expand All @@ -31,6 +32,11 @@ rr:
name: agent-sandbox-secrets

postgres:
# Option 3: read the DSN from the same Secret that holds the JWT/encryption
# keys by pointing urlSecretName at it. externalSecret.name itself never
# sources Postgres.
urlSecretName: agent-sandbox-secrets
urlSecretKey: postgres-url
schema: agent_executor
poolMax: 10

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,3 +20,5 @@ rr:

jwtPublicKey: '-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEljtqa2nhBwe/PqNhWgPHhj0jv8AI\nY+QUCicYtfv9wLGcEGPQuXoBQtuoIuOwXOdbEWgrQyLdIEb0YjegAW3miA==\n-----END PUBLIC KEY-----'
jwtPrivateKey: '-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMFXLiN/YsJv89D2YkEZ6/Dj5fujghENmYTOilwdChU3oAoGCCqGSM49\nAwEHoUQDQgAEljtqa2nhBwe/PqNhWgPHhj0jv8AIY+QUCicYtfv9wLGcEGPQuXoB\nQtuoIuOwXOdbEWgrQyLdIEb0YjegAW3miA==\n-----END EC PRIVATE KEY-----'
# encryption key is required (proxy derives the asset-token HMAC key from it)
encryptionKey: a12b01429fe0fe69a80da94e9e837ab2f1e9bda378ed8a25905a238f6fea6b7a
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ rr:

jwtPublicKey: '-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEljtqa2nhBwe/PqNhWgPHhj0jv8AI\nY+QUCicYtfv9wLGcEGPQuXoBQtuoIuOwXOdbEWgrQyLdIEb0YjegAW3miA==\n-----END PUBLIC KEY-----'
jwtPrivateKey: '-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMFXLiN/YsJv89D2YkEZ6/Dj5fujghENmYTOilwdChU3oAoGCCqGSM49\nAwEHoUQDQgAEljtqa2nhBwe/PqNhWgPHhj0jv8AIY+QUCicYtfv9wLGcEGPQuXoB\nQtuoIuOwXOdbEWgrQyLdIEb0YjegAW3miA==\n-----END EC PRIVATE KEY-----'
# encryption key is required (proxy derives the asset-token HMAC key from it)
encryptionKey: a12b01429fe0fe69a80da94e9e837ab2f1e9bda378ed8a25905a238f6fea6b7a

# Option 2: host + user + database, password via PGPASSWORD secretKeyRef.
postgres:
Expand Down
2 changes: 2 additions & 0 deletions charts/retool/ci/test-rr-enabled-option.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ rr:
# be single-line (\n-escaped) or templating breaks.
jwtPublicKey: '-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEljtqa2nhBwe/PqNhWgPHhj0jv8AIY+QUCicYtfv9wLGcEGPQuXoBQtuoIuOwXOdbEWgrQyLdIEb0YjegAW3miA==\n-----END PUBLIC KEY-----'
jwtPrivateKey: '-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMFXLiN/YsJv89D2YkEZ6/Dj5fujghENmYTOilwdChU3oAoGCCqGSM49AwEHoUQDQgAEljtqa2nhBwe/PqNhWgPHhj0jv8AIY+QUCicYtfv9wLGcEGPQuXoBQtuoIuOwXOdbEWgrQyLdIEb0YjegAW3miA==\n-----END EC PRIVATE KEY-----'
# encryption key is required (proxy derives the asset-token HMAC key from it)
encryptionKey: a12b01429fe0fe69a80da94e9e837ab2f1e9bda378ed8a25905a238f6fea6b7a
postgres:
url: postgres://retool:retool@agent-sandbox-db.example.internal:5432/agent_sandbox
schema: agent_executor
Expand Down
30 changes: 20 additions & 10 deletions charts/retool/templates/_helpers.tpl
Original file line number Diff line number Diff line change
Expand Up @@ -676,14 +676,14 @@ or the catch-all externalSecret.name. No-op when agentSandbox is disabled.
{{- if eq (include "retool.rr.componentEnabled" (dict "root" . "component" "agentSandbox")) "1" -}}
{{- $as := .Values.rr.agentSandbox -}}
{{- $ext := $as.externalSecret.name -}}
{{- $explicitPg := or $as.postgres.url $as.postgres.urlSecretName $as.postgres.host $ext -}}
{{- $explicitPg := or $as.postgres.url $as.postgres.urlSecretName $as.postgres.host -}}
{{- if not $explicitPg -}}
{{- /* No explicit source: inherit the backend's Postgres connection. */ -}}
{{- if not (include "retool.postgresql.host" . | trimAll "\"") -}}
{{- fail "agentSandbox.enabled defaults to reusing the backend's Postgres connection, but config.postgresql resolved no host. Set agentSandbox.postgres.url / .host / .urlSecretName / externalSecret.name, or configure config.postgresql." -}}
{{- fail "agentSandbox.enabled defaults to reusing the backend's Postgres connection, but config.postgresql resolved no host. Set agentSandbox.postgres.url / .host / .urlSecretName (point .urlSecretName at your externalSecret to reuse its postgres-url key; externalSecret.name alone only covers the JWT/encryption keys), or configure config.postgresql." -}}
{{- end -}}
{{- if not (or .Values.postgresql.enabled .Values.config.postgresql.passwordSecretName (eq (include "shouldIncludeConfigSecretsEnvVars" . | trim) "1")) -}}
{{- fail "agentSandbox.postgres is unset so it would inherit the backend's Postgres password, but that password is supplied via external secrets (envFrom) and cannot be referenced from a separate pod. Set agentSandbox.postgres.url / .urlSecretName / .host (+ passwordSecretName), or agentSandbox.externalSecret.name." -}}
{{- fail "agentSandbox.postgres is unset so it would inherit the backend's Postgres password, but that password is supplied via external secrets (envFrom) and cannot be referenced from a separate pod. Set agentSandbox.postgres.url / .urlSecretName / .host (+ passwordSecretName) -- .urlSecretName can point at your externalSecret's postgres-url key (externalSecret.name alone only covers the JWT/encryption keys)." -}}
{{- end -}}
{{- end -}}
{{- if $as.postgres.host -}}
Expand Down Expand Up @@ -714,15 +714,20 @@ or the catch-all externalSecret.name. No-op when agentSandbox is disabled.
{{- if not (or $as.jwtPrivateKey $ext) -}}
{{- fail "agentSandbox.enabled requires a JWT private key (the backend signs sandbox tokens with it). Set agentSandbox.jwtPrivateKey or agentSandbox.externalSecret.name." -}}
{{- end -}}
{{- if not (or $as.encryptionKey $ext) -}}
{{- fail "agentSandbox.enabled requires an encryption key: the proxy derives the sandbox-iframe asset-token HMAC key from it and throws when serving a sandbox without it, and the backend must use the same value. Set agentSandbox.encryptionKey (64 hex chars, openssl rand -hex 32) or agentSandbox.externalSecret.name (with an encryption-key entry)." -}}
{{- end -}}
{{- end -}}
{{- end -}}

{{/*
Render the AGENT_SANDBOX_POSTGRES_URL env entry for the controller/proxy (plus a
PGPASSWORD entry when assembling from fields). validateSecrets guarantees one of
these applies, in order: postgres.url -> postgres.host -> postgres.urlSecretName
-> externalSecret.name -> inherit the backend's config.postgresql connection
(the default when nothing agent-specific is set).
-> inherit the backend's config.postgresql connection (the default when nothing
agent-specific is set). externalSecret.name covers only the JWT/encryption keys
-- it never sources Postgres. To read a DSN from that same secret, point
postgres.urlSecretName at it (its postgres-url key is the urlSecretKey default).

For the host path the password is passed via PGPASSWORD rather than embedded in
the URL: node-postgres reads PGPASSWORD when the connection string omits the
Expand All @@ -737,7 +742,6 @@ Usage: {{- include "retool.agentSandbox.postgresUrlEnv" . | nindent 12 }}
*/}}
{{- define "retool.agentSandbox.postgresUrlEnv" -}}
{{- $pg := .Values.rr.agentSandbox.postgres -}}
{{- $ext := .Values.rr.agentSandbox.externalSecret.name -}}
{{- if $pg.url }}
- name: AGENT_SANDBOX_POSTGRES_URL
value: {{ $pg.url | quote }}
Expand All @@ -761,12 +765,18 @@ Usage: {{- include "retool.agentSandbox.postgresUrlEnv" . | nindent 12 }}
secretKeyRef:
name: {{ $pg.urlSecretName }}
key: {{ $pg.urlSecretKey | default "postgres-url" }}
{{- else if $ext }}
- name: AGENT_SANDBOX_POSTGRES_URL
{{- /*
The DSN may omit the password; supply it separately via passwordSecretName so
an auto-rotated password (e.g. the backend's RDS secret) isn't duplicated into
the DSN secret. node-postgres reads PGPASSWORD when the URL omits the password.
*/}}
{{- if $pg.passwordSecretName }}
- name: PGPASSWORD
valueFrom:
secretKeyRef:
name: {{ $ext }}
key: postgres-url
name: {{ $pg.passwordSecretName }}
key: {{ $pg.passwordSecretKey | default "password" }}
{{- end }}
{{- else }}
{{- /*
Default: inherit the backend's Postgres connection (config.postgresql or the
Expand Down
11 changes: 11 additions & 0 deletions charts/retool/templates/_workers.tpl
Original file line number Diff line number Diff line change
Expand Up @@ -230,6 +230,17 @@ spec:
value: http://{{ template "retool.jsExecutor.name" $ }}
{{- end }}
{{- include "retool.agentSandbox.backendEnvVars" $ | nindent 10 }}
{{- if $.Values.rr.gitServer.enabled }}
{{- /*
Snapshot blob storage: the agentExecutor / snapshotRetention temporal
activities run on this worker and read RR_SNAPSHOTS_* with an
RR_DEFAULT_* fallback (backend getBlobStoreForSnapshots). Render the
same blobStorage env the backend and git-server get, so the fallback
resolves here too. No git-server host/port split is needed -- the
worker is a blob-storage client, not the git server itself.
*/}}
{{- include "retool.gitServer.commonEnv" $ | nindent 10 }}
{{- end }}

{{- include "retool.telemetry.includeEnvVars" $ | nindent 10 }}

Expand Down
23 changes: 13 additions & 10 deletions charts/retool/values.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -887,14 +887,16 @@ rr:
# === Secrets ============================================================
# Provide each secret as a plaintext value below, OR set externalSecret.name
# to a pre-existing Secret with keys jwt-public-key, jwt-private-key,
# encryption-key, api-secret, postgres-url. A plaintext value always wins over
# the external secret for that key.
# encryption-key, api-secret. A plaintext value always wins over the external
# secret for that key. externalSecret.name covers ONLY these app secrets --
# it does not source Postgres. To read a DSN from that same Secret, point
# postgres.urlSecretName at it (see Postgres Option 3 below).
externalSecret:
name: '' # optional: existing Secret holding all keys below
name: '' # optional: existing Secret holding the keys below

jwtPublicKey: '' # REQUIRED (ES256) unless provided via externalSecret
jwtPrivateKey: '' # REQUIRED (ES256) unless provided via externalSecret
encryptionKey: '' # optional: hex 256-bit; must match backend AGENT_SANDBOX_ENCRYPTION_KEY
encryptionKey: '' # REQUIRED: 64 hex chars (openssl rand -hex 32, NOT base64). Proxy throws when serving a sandbox without it; must match the backend's AGENT_SANDBOX_ENCRYPTION_KEY. May instead be supplied via externalSecret.name (encryption-key entry).
apiSecret: '' # optional: admin/test endpoints

# === Postgres state backend =============================================
Expand Down Expand Up @@ -923,15 +925,16 @@ rr:
passwordSecretName: ''
passwordSecretKey: 'password'

# -- Option 3: existing Secret holding the full DSN --
# -- Option 3: DSN from an existing Secret --
# Set urlSecretName (urlSecretKey defaults to postgres-url). To reuse the
# Secret in rr.agentSandbox.externalSecret.name, just point urlSecretName at
# it -- externalSecret.name itself never sources Postgres.
# The DSN may omit the password; supply it separately via passwordSecretName
# (above) so an auto-rotated password isn't duplicated into the DSN secret.
urlSecretName: ''
urlSecretKey: 'postgres-url'

# -- Option 4: reuse externalSecret.name (its postgres-url key) --
# Selected by setting rr.agentSandbox.externalSecret.name (in the Secrets
# section above), not by anything here. Used when options 1-3 are blank.
#
# If options 1-4 are ALL unset, the default (inherit config.postgresql)
# If options 1-3 are ALL unset, the default (inherit config.postgresql)
# applies -- see the note at the top of this block.

# -- Optional tuning (defaults shown) --
Expand Down
23 changes: 13 additions & 10 deletions values.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -887,14 +887,16 @@ rr:
# === Secrets ============================================================
# Provide each secret as a plaintext value below, OR set externalSecret.name
# to a pre-existing Secret with keys jwt-public-key, jwt-private-key,
# encryption-key, api-secret, postgres-url. A plaintext value always wins over
# the external secret for that key.
# encryption-key, api-secret. A plaintext value always wins over the external
# secret for that key. externalSecret.name covers ONLY these app secrets --
# it does not source Postgres. To read a DSN from that same Secret, point
# postgres.urlSecretName at it (see Postgres Option 3 below).
externalSecret:
name: '' # optional: existing Secret holding all keys below
name: '' # optional: existing Secret holding the keys below

jwtPublicKey: '' # REQUIRED (ES256) unless provided via externalSecret
jwtPrivateKey: '' # REQUIRED (ES256) unless provided via externalSecret
encryptionKey: '' # optional: hex 256-bit; must match backend AGENT_SANDBOX_ENCRYPTION_KEY
encryptionKey: '' # REQUIRED: 64 hex chars (openssl rand -hex 32, NOT base64). Proxy throws when serving a sandbox without it; must match the backend's AGENT_SANDBOX_ENCRYPTION_KEY. May instead be supplied via externalSecret.name (encryption-key entry).
apiSecret: '' # optional: admin/test endpoints

# === Postgres state backend =============================================
Expand Down Expand Up @@ -923,15 +925,16 @@ rr:
passwordSecretName: ''
passwordSecretKey: 'password'

# -- Option 3: existing Secret holding the full DSN --
# -- Option 3: DSN from an existing Secret --
# Set urlSecretName (urlSecretKey defaults to postgres-url). To reuse the
# Secret in rr.agentSandbox.externalSecret.name, just point urlSecretName at
# it -- externalSecret.name itself never sources Postgres.
# The DSN may omit the password; supply it separately via passwordSecretName
# (above) so an auto-rotated password isn't duplicated into the DSN secret.
urlSecretName: ''
urlSecretKey: 'postgres-url'

# -- Option 4: reuse externalSecret.name (its postgres-url key) --
# Selected by setting rr.agentSandbox.externalSecret.name (in the Secrets
# section above), not by anything here. Used when options 1-3 are blank.
#
# If options 1-4 are ALL unset, the default (inherit config.postgresql)
# If options 1-3 are ALL unset, the default (inherit config.postgresql)
# applies -- see the note at the top of this block.

# -- Optional tuning (defaults shown) --
Expand Down
Loading