Skip to content

runtime: forward the config-encryption endpoint to connectors - #3291

Open
mdibaiee wants to merge 1 commit into
masterfrom
mahdi/forward-encryption-url
Open

runtime: forward the config-encryption endpoint to connectors#3291
mdibaiee wants to merge 1 commit into
masterfrom
mahdi/forward-encryption-url

Conversation

@mdibaiee

@mdibaiee mdibaiee commented Aug 1, 2026

Copy link
Copy Markdown
Member

Description:

Connectors that emit configUpdate events encrypt the restated config through the config-encryption service, reading ENCRYPTION_URL and otherwise falling back to Estuary's public endpoint (go/common/config_update.go in the connectors repo, and estuary-cdk's base_capture_connector.py).

Nothing ever set that variable. crates/runtime/src/container.rs passes connector containers only LOG_FORMAT and LOG_LEVEL, and mise/tasks/local/supabase sets CONFIG_ENCRYPTION_URL for the agent, not for connectors. So on a local stack a connector emitting a configUpdate called production config-encryption and produced a config sealed with keys that stack cannot decrypt.

This forwards CONFIG_ENCRYPTION_URL from the runtime's own environment into the container as ENCRYPTION_URL, next to the other runtime knobs already read there (CONNECTOR_CGROUP_PARENT, CONNECTOR_MEMORY_LIMIT, DOCKER_CLI), and has the local stack emit it via emit_common_vars so both the reactor's embedded runtime and the agent have it to pass on. When the variable is unset — production today — behavior is unchanged.

Connector containers on local planes also get --add-host=host.docker.internal:host-gateway. That hostname is how the local stack already addresses host services, but Linux docker doesn't provide it (only Docker Desktop does), and connector containers sit on the flow bridge network where the gateway address isn't fixed.

Workflow steps:

No workflow change. After mise run local:stack, connectors emitting configUpdate events reach the stack's own config-encryption service instead of production.

Documentation links affected:

None.

Notes for reviewers:

Verified end-to-end on a local stack, with the connector built carrying the production default URL so that reaching the local service could only come from the forwarded variable:

  • docker inspect on the running connector container shows ENCRYPTION_URL=http://host.docker.internal:10021/v1/encrypt-config and ExtraHosts: [host.docker.internal:host-gateway].
  • The emitted configUpdate event's config has credentials.password_sops = ENC[AES256_GCM,…] with an age sops stanza — the local service's keychain. Production seals with GCP KMS, so this is positive evidence the local endpoint served the request.

One step I could not verify in my stack: whether the control plane then applies the update. config_updates is populated by the ops catalog materialization, and this stack's ops pipeline is degraded for unrelated reasons (plane-link and the ops rollup derivations fail because derive-typescript is published for amd64 only, so they cannot run on an arm64 VM). The connector-side half — which is what this PR changes — is verified.

Depends on nothing, but note #3290 fixes a separate blocker that must be in place for connectors to run at all on an arm64 dev VM.

Connectors which emit configUpdate events encrypt the restated config through
the config-encryption service, defaulting to Estuary's public one when
ENCRYPTION_URL is unset. Nothing set it: connector containers receive only
LOG_FORMAT and LOG_LEVEL, so on a local stack a connector reached production and
produced a config sealed with keys that stack cannot decrypt.

Forward CONFIG_ENCRYPTION_URL from the runtime's own environment as
ENCRYPTION_URL, alongside the other runtime knobs already read there, and have
the local stack emit it. Connector containers also get
--add-host=host.docker.internal:host-gateway for local planes, since that name
is how the stack addresses host services and Linux docker does not provide it.

Verified on a local stack: the connector container receives
ENCRYPTION_URL=http://host.docker.internal:10021/v1/encrypt-config, and a
connector built with the production default emitted a configUpdate whose secrets
are AGE-encrypted -- the local service's keychain, not production GCP KMS.
Comment on lines +167 to +170
// Resolve `host.docker.internal` to the host, so that URLs
// pointing at host services (e.g. CONFIG_ENCRYPTION_URL) work
// under Linux docker as well as Docker Desktop.
"--add-host=host.docker.internal:host-gateway".to_string(),

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think we want this merged, I'm leaving this PR as a reference for agents to know how to run connectors locally which need config encryption endpoint

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant