You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Today, every ProviderConfig in provider-sql requires master database credentials to be materialized as a Kubernetes Secret (referenced via spec.credentials.connectionSecretRef). For control planes that broker access to upstream secret stores (AWS Secrets Manager, GCP Secret Manager, Vault, etc.), this means the master password ends up sitting in plaintext in a user-visible namespace, exposed to anyone with namespace-scoped read access — even though the upstream system already enforces stricter access controls.
There is no way today to instruct provider-sql to fetch credentials from somewhere other than a Secret in the cluster.
Proposal
Add a new credential Source value that points provider-sql at a configurable HTTP endpoint. The operator hosts a small "credential helper" — typically a sidecar bound to localhost — that resolves credentials from whatever upstream backend they want (Secrets Manager, Vault, etc.) and returns them over HTTP. Provider-sql never sees the upstream credentials and they never land in a Secret.
Mirrored for mysql.sql.crossplane.io and mssql.sql.crossplane.io with MySQLConnectionHelper / MSSQLConnectionHelper to match the existing per-engine Source naming convention.
Helper response contract
The helper returns JSON whose keys map directly to the existing xpv1.ResourceCredentialsSecret*Key constants the connection clients already consume:
This keeps pkg/clients/{postgresql,mysql,mssql}.New() unchanged — they continue to receive a flat map[string][]byte of credentials and don't need to know whether the source was a Secret or a helper.
v1 scope (kept deliberately small)
Localhost sidecar only — no auth on the helper endpoint in v1; security boundary is the pod network namespace
All three engines (postgres, mysql, mssql), cluster + namespaced ProviderConfig variants
Additive only — no changes to the existing *ConnectionSecret source; existing users unaffected
No new dependencies — net/http + encoding/json from stdlib are sufficient
Auth on the helper endpoint (bearer token, mTLS) and non-localhost endpoints are deliberately out of scope for v1, but the API shape leaves room to add them compatibly later (e.g. optional fields on ConnectionHelperConfig).
Implementation footprint
API types: apis/{namespaced,cluster}/{postgresql,mysql,mssql}/v1alpha1/provider_types.go — new enum const + optional ConnectionHelperConfig field on ProviderCredentials
Connectors: each pkg/controller/.../reconciler.goConnect() gains a switch on pc.Spec.Credentials.Source with a new branch that calls the HTTP helper client
New file: pkg/clients/credentialhelper/http.go — HTTP GET + JSON decode → map[string][]byte
Tests: httptest.Server-based fixtures in the existing reconciler test suites
PR granularity — would you prefer one PR per engine (postgres first, mysql/mssql follow), or a single PR covering all three? The reconciler change is mechanical but replicated across ~24 files.
Naming — per-engine *ConnectionHelper constants matches the existing *ConnectionSecret convention, but a single shared ConnectionHelper value across all three engines is also defensible. Preference?
Helper response shape — is JSON-with-stringly-typed-fields acceptable, or would you prefer a versioned content-type (e.g. application/vnd.crossplane.provider-sql.credentials.v1+json) from day one?
Problem
Today, every
ProviderConfigin provider-sql requires master database credentials to be materialized as a KubernetesSecret(referenced viaspec.credentials.connectionSecretRef). For control planes that broker access to upstream secret stores (AWS Secrets Manager, GCP Secret Manager, Vault, etc.), this means the master password ends up sitting in plaintext in a user-visible namespace, exposed to anyone with namespace-scoped read access — even though the upstream system already enforces stricter access controls.There is no way today to instruct provider-sql to fetch credentials from somewhere other than a
Secretin the cluster.Proposal
Add a new credential
Sourcevalue that points provider-sql at a configurable HTTP endpoint. The operator hosts a small "credential helper" — typically a sidecar bound to localhost — that resolves credentials from whatever upstream backend they want (Secrets Manager, Vault, etc.) and returns them over HTTP. Provider-sql never sees the upstream credentials and they never land in aSecret.API shape
Mirrored for
mysql.sql.crossplane.ioandmssql.sql.crossplane.iowithMySQLConnectionHelper/MSSQLConnectionHelperto match the existing per-engineSourcenaming convention.Helper response contract
The helper returns JSON whose keys map directly to the existing
xpv1.ResourceCredentialsSecret*Keyconstants the connection clients already consume:{ "endpoint": "db.example.internal", "port": "5432", "username": "master", "password": "..." }This keeps
pkg/clients/{postgresql,mysql,mssql}.New()unchanged — they continue to receive a flatmap[string][]byteof credentials and don't need to know whether the source was aSecretor a helper.v1 scope (kept deliberately small)
*ConnectionSecretsource; existing users unaffectednet/http+encoding/jsonfrom stdlib are sufficientAuth on the helper endpoint (bearer token, mTLS) and non-localhost endpoints are deliberately out of scope for v1, but the API shape leaves room to add them compatibly later (e.g. optional fields on
ConnectionHelperConfig).Implementation footprint
apis/{namespaced,cluster}/{postgresql,mysql,mssql}/v1alpha1/provider_types.go— new enum const + optionalConnectionHelperConfigfield onProviderCredentialspkg/controller/.../reconciler.goConnect()gains aswitchonpc.Spec.Credentials.Sourcewith a new branch that calls the HTTP helper clientpkg/clients/credentialhelper/http.go— HTTP GET + JSON decode →map[string][]bytehttptest.Server-based fixtures in the existing reconciler test suitesNo refactoring of existing code is required.
Prior art / related work
ProviderCredentials.Sourceas the natural extension point for alternative credential sources. This proposal is complementary, not competing: IAM auth solves "use AWS-issued tokens" while a credential helper solves "fetch from any backend, including AWS Secrets Manager today, before IAM auth lands". Happy to coordinate naming/structure with whoever picks up feat: Add AWS IAM database authentication support for MySQL and PostgreSQL #347.SecretKeyMapping(merged) — recent precedent thatProviderCredentialsis being actively evolved.Questions for maintainers before I open a PR
*ConnectionHelperconstants matches the existing*ConnectionSecretconvention, but a single sharedConnectionHelpervalue across all three engines is also defensible. Preference?application/vnd.crossplane.provider-sql.credentials.v1+json) from day one?Happy to iterate on the design here before any code lands. If reception is positive I'll open a draft PR scoped per your preference above.