Skip to content

feat: add AWS IAM database authentication for MySQL and PostgreSQL#396

Open
michielvha wants to merge 6 commits into
crossplane-contrib:masterfrom
michielvha:feat/aws-iam-auth
Open

feat: add AWS IAM database authentication for MySQL and PostgreSQL#396
michielvha wants to merge 6 commits into
crossplane-contrib:masterfrom
michielvha:feat/aws-iam-auth

Conversation

@michielvha

Copy link
Copy Markdown

Description of your changes

This adds AWS IAM database authentication for Aurora/RDS MySQL and PostgreSQL. When it is enabled the provider connects using a short-lived IAM token instead of a static password, so combined with EKS Pod Identity or IRSA there is no static database credential to manage.

It adds a new AWSIAMAuth value to the credentials.source enum, alongside the existing *ConnectionSecret sources. When it is selected:

  • the connection secret only needs endpoint, port and username (no password);
  • a token is generated at connect time with aws-sdk-go-v2/feature/rds/auth and used as the password;
  • TLS is enforced, and for MySQL allowCleartextPasswords=true is set, which the AWSAuthenticationPlugin requires.

An optional region field is added, with fallback to a region key in the secret and then to the controller's AWS environment.

Scope is provider authentication only, as discussed in #347. Creating the IAM-enabled database users themselves stays a separate, out-of-band step, and is already possible through the existing Role/Grant resources.

On the RDS certificate authority: following the discussion with @kkendzia and @phmcder, the Amazon RDS CA is treated as an external dependency rather than bundled in the provider. Operators make it available to the provider pod (for example with trust-manager, or a mounted secret) and choose the verification mode through the existing tls / sslMode fields. If neither is configured the connection is still encrypted but unverified. This is documented in docs/aws-iam-auth.md, with example ProviderConfigs under examples/{cluster,namespaced}/{mysql,postgresql}/config_iam.yaml.

Fixes #347

I have:

  • Read and followed Crossplane's contribution process.
  • Run make reviewable to ensure this PR is ready for review.

How has this code been tested

  • Unit tests for the new awsiam package (region resolution, host:port assembly, token injection, error paths), the MySQL cleartext DSN, and the IAM branch in the cluster reconcilers and the namespaced providers. The injection sits behind a small package-level seam so that path is covered without any AWS access.
  • gofmt, goimports, go vet, golangci-lint and code generation are all clean, and the full test suite passes.
  • End to end against real RDS (MySQL 8.0 and PostgreSQL 16 with IAM authentication enabled): the provider's own client code generates a token and connects for both engines.

Add pkg/clients/awsiam: generates short-lived RDS IAM auth tokens and
injects them as the database password, with region resolution and a
test seam (injectable TokenBuilder) so the logic is unit-tested without
AWS credentials or network.

Part of crossplane-contrib#347.

Signed-off-by: michielvha <michielvh@outlook.com>
Add the AWSIAMAuth credential source value and an optional Region field
to the MySQL and PostgreSQL ProviderConfig (and namespaced
ClusterProviderConfig) credential types, for both cluster and namespaced
API groups. Regenerate deepcopy and CRDs.

Part of crossplane-contrib#347.

Signed-off-by: michielvha <michielvh@outlook.com>
Add a cleartext parameter to mysql.New/DSN that appends
allowCleartextPasswords=true to the DSN when set. AWS RDS IAM
authentication needs this because the AWSAuthenticationPlugin uses
MySQL's cleartext client plugin, which go-sql-driver refuses by default.

This commit only plumbs the flag (all existing callers pass false, so
behaviour is unchanged); the IAM reconciler changes that set it follow.

Part of crossplane-contrib#347.

Signed-off-by: michielvha <michielvh@outlook.com>
Add awsiam.Inject (load AWS config, resolve region, generate and inject
the IAM token) and call it from each cluster reconciler's Connect() when
the credentials source is AWSIAMAuth. For MySQL this also enables the
cleartext flag and ensures TLS is on; for PostgreSQL it forces
sslmode=require. Certificate verification relies on the operator
supplying the RDS CA (e.g. via trust-manager or a mounted secret).

Part of crossplane-contrib#347.

Signed-off-by: michielvha <michielvh@outlook.com>
Inject the IAM token centrally in GetProviderConfig() for the namespaced
MySQL and PostgreSQL providers when the credentials source is AWSIAMAuth.
MySQL additionally surfaces a Cleartext flag (forwarded by its three
reconcilers) and forces TLS on; PostgreSQL forces sslmode=require. The six
namespaced PostgreSQL reconcilers need no change.

Part of crossplane-contrib#347.

Signed-off-by: michielvha <michielvh@outlook.com>
Add example AWSIAMAuth ProviderConfigs for cluster and namespaced MySQL
and PostgreSQL, and docs/aws-iam-auth.md covering prerequisites, the
operator-supplied RDS CA trust options (trust-manager / mounted secret),
region resolution and the TLS behaviour.

Part of crossplane-contrib#347.

Signed-off-by: michielvha <michielvh@outlook.com>
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.

feat: Add AWS IAM database authentication support for MySQL and PostgreSQL

1 participant