Summary
Issue tabularis#694 asks for AWS IAM authentication support for PostgreSQL connections (MySQL already has it via use_iam_auth). This plugin has no IAM auth support at all — confirmed by grepping src/models.rs and src/client.rs for iam, which returns nothing.
The builtin driver's MySQL implementation establishes the pattern this plugin would need to mirror for Postgres:
ConnectionParams.use_iam_auth: Option<bool> (src-tauri/src/models.rs:219)
build_mysql_options in src-tauri/src/pool_manager.rs:
- Refuses IAM auth over
Disabled SSL (pool_manager.rs:222-229)
- Force-upgrades
Preferred → Required so the pre-signed token can never fall back to a plaintext handshake (pool_manager.rs:235-237)
- Auto-escalates
Required/Preferred + user-supplied ssl_ca to VerifyCa (pool_manager.rs:211-216)
- Rejects an empty password/token unconditionally (
pool_manager.rs:243-250)
require_iam_token in src-tauri/src/commands.rs:217 — guards test_connection/list_databases so an empty token surfaces an actionable error instead of an opaque "Access denied"
find_connection_by_id/duplicate_connection skip the OS keychain for IAM connections (commands.rs:626-630, commands.rs:1312-1315) since RDS tokens are 15-minute pre-signed and must come from the form on every connect, never a cached password
build_connection_key's pool cache key includes the IAM flag so IAM and non-IAM connections to the same host never share a pool (pool_manager.rs:104-116)
- Frontend gates the "Use AWS IAM Authentication (RDS)" checkbox to an enforced TLS mode (
src/components/modals/NewConnectionModal.tsx:3177-3227)
For PostgreSQL, AWS RDS IAM auth works differently at the wire level than MySQL's mysql_clear_password plugin negotiation, but the net effect is the same: the DB user must have the rds_iam role granted, RDS then forces the standard PostgreSQL cleartext-password auth method for that user, and the "password" sent over the wire is actually a short-lived (15 min) pre-signed token from aws rds generate-db-auth-token. tokio_postgres already handles AuthenticationCleartextPassword (tokio-postgres/src/connect_raw.rs:173) with no changes needed — this is purely a "send the token as password, over an encrypted link" feature, not a new auth mechanism to implement.
Security note: why "cleartext password" is acceptable here
The wire-level mechanism above ("RDS forces cleartext-password auth") sounds alarming out of context, so this was verified against primary sources rather than left as an assertion:
- PostgreSQL's own docs for the
password auth method are explicit: it "sends the password in clear-text... If the connection is protected by SSL encryption then password can be used safely" (auth-password.html). This is different from md5/scram-sha-256, which are challenge-response and never put the password/token on the wire at all.
- pgjdbc's
ConnectionFactoryImpl confirms there's no hashing step for this auth type — on AUTH_REQ_PASSWORD it sends the value straight back via a plain PASSWORD_REQUEST message.
- AWS's IAM auth token is exactly that plain string (a ~1KB pre-signed SigV4 token, from
aws rds generate-db-auth-token), validated server-side against IAM instead of a stored password hash. As far as the wire protocol is concerned it's an ordinary cleartext password.
- AWS's docs state network traffic for IAM-authenticated connections is (and must be) SSL/TLS-encrypted, and a live example — rust-postgres#1108 — shows a user's IAM-auth connection failing under
NoTls and succeeding once they switched to a real TLS implementation.
So this is the same tradeoff PostgreSQL's docs describe as safe: cleartext auth is fine specifically when TLS is enforced, since TLS — not the auth method — is what protects the token in transit. The 15-minute token lifetime bounds the damage if it did leak. This is why the proposed approach below requires an enforced TLS mode (require/verify-ca/verify-full) whenever use_iam_auth is true and rejects disable/unset outright — mirroring the identical safeguard the MySQL builtin driver already applies for its own cleartext-plugin exposure (pool_manager.rs:222-229).
Proposed approach
src/models.rs: add use_iam_auth: Option<bool> to ConnectionParams, parsed via get_str/a bool equivalent in from_value (mirror the builtin's models.rs:219 field and its #[serde(default)] intent, adapted to this file's manual Value parsing style).
src/client.rs (build_pool):
- When
use_iam_auth is true, require an enforced TLS mode (require/verify-ca/verify-full) — reject disable/prefer/unset with an actionable error, mirroring build_mysql_options's refusal (pool_manager.rs:222-229). Postgres has no Preferred-style opportunistic-then-silent-downgrade auto-escalation to worry about the same way MySQL does, but the "must be enforced TLS" rule is identical in spirit.
- Reject an empty
password when use_iam_auth is true, with a message pointing at aws rds generate-db-auth-token (mirror pool_manager.rs:243-250).
- Fold
use_iam_auth into connection_key (client.rs:223-236) alongside the existing TLS params, so IAM and non-IAM pools to the same host:port:database:user never collide — same rationale as the builtin's build_connection_key (pool_manager.rs:111-115).
- Host-side (
tabularis repo, out of scope for this plugin but noted for cross-repo coordination): the require_iam_token guard in commands.rs:217 and the keychain-skip logic in commands.rs:626-630/commands.rs:1312-1315 are host-side and already driver-agnostic (they check params.use_iam_auth directly, not params.driver) — they should start working for Postgres connections automatically once this plugin declares/accepts the field, provided the frontend checkbox at NewConnectionModal.tsx:3177 is also updated to render for driver === "postgres" (it's currently hard-gated to driver === "mysql" only). That frontend change and any manifest/capability declaration this plugin needs to advertise (use_iam_auth support) belongs to a follow-up PR/issue in tabularis itself, filed once this plugin implements the field.
- Tests: unit tests in
src/client_tests.rs covering:
- IAM +
disable/unset TLS → rejected with the actionable error (no live server needed, mirrors the TDD pattern in CLAUDE.md's "TDD for parity bugs without a live database" — this is a pure config-validation branch in build_pool/a small extracted helper, testable without a live server).
- IAM + empty password → rejected.
- IAM +
require + non-empty password → does not hit the TLS/password guards (can't assert full pool success without a real server, but can assert the guard functions return Ok).
connection_key differs for IAM vs non-IAM given otherwise-identical params.
Why the plugin repo, not tabularis
Per tabularis#694's discussion, @aesslinger proposed migrating this request here since the Postgres driver now lives in the plugin, not the builtin — no further work is planned on a builtin Postgres implementation.
Summary
Issue tabularis#694 asks for AWS IAM authentication support for PostgreSQL connections (MySQL already has it via
use_iam_auth). This plugin has no IAM auth support at all — confirmed by greppingsrc/models.rsandsrc/client.rsforiam, which returns nothing.The builtin driver's MySQL implementation establishes the pattern this plugin would need to mirror for Postgres:
ConnectionParams.use_iam_auth: Option<bool>(src-tauri/src/models.rs:219)build_mysql_optionsinsrc-tauri/src/pool_manager.rs:DisabledSSL (pool_manager.rs:222-229)Preferred→Requiredso the pre-signed token can never fall back to a plaintext handshake (pool_manager.rs:235-237)Required/Preferred+ user-suppliedssl_catoVerifyCa(pool_manager.rs:211-216)pool_manager.rs:243-250)require_iam_tokeninsrc-tauri/src/commands.rs:217— guardstest_connection/list_databasesso an empty token surfaces an actionable error instead of an opaque "Access denied"find_connection_by_id/duplicate_connectionskip the OS keychain for IAM connections (commands.rs:626-630,commands.rs:1312-1315) since RDS tokens are 15-minute pre-signed and must come from the form on every connect, never a cached passwordbuild_connection_key's pool cache key includes the IAM flag so IAM and non-IAM connections to the same host never share a pool (pool_manager.rs:104-116)src/components/modals/NewConnectionModal.tsx:3177-3227)For PostgreSQL, AWS RDS IAM auth works differently at the wire level than MySQL's
mysql_clear_passwordplugin negotiation, but the net effect is the same: the DB user must have therds_iamrole granted, RDS then forces the standard PostgreSQL cleartext-password auth method for that user, and the "password" sent over the wire is actually a short-lived (15 min) pre-signed token fromaws rds generate-db-auth-token.tokio_postgresalready handlesAuthenticationCleartextPassword(tokio-postgres/src/connect_raw.rs:173) with no changes needed — this is purely a "send the token as password, over an encrypted link" feature, not a new auth mechanism to implement.Security note: why "cleartext password" is acceptable here
The wire-level mechanism above ("RDS forces cleartext-password auth") sounds alarming out of context, so this was verified against primary sources rather than left as an assertion:
passwordauth method are explicit: it "sends the password in clear-text... If the connection is protected by SSL encryption thenpasswordcan be used safely" (auth-password.html). This is different frommd5/scram-sha-256, which are challenge-response and never put the password/token on the wire at all.ConnectionFactoryImplconfirms there's no hashing step for this auth type — onAUTH_REQ_PASSWORDit sends the value straight back via a plainPASSWORD_REQUESTmessage.aws rds generate-db-auth-token), validated server-side against IAM instead of a stored password hash. As far as the wire protocol is concerned it's an ordinary cleartext password.NoTlsand succeeding once they switched to a real TLS implementation.So this is the same tradeoff PostgreSQL's docs describe as safe: cleartext auth is fine specifically when TLS is enforced, since TLS — not the auth method — is what protects the token in transit. The 15-minute token lifetime bounds the damage if it did leak. This is why the proposed approach below requires an enforced TLS mode (
require/verify-ca/verify-full) wheneveruse_iam_authis true and rejectsdisable/unset outright — mirroring the identical safeguard the MySQL builtin driver already applies for its own cleartext-plugin exposure (pool_manager.rs:222-229).Proposed approach
src/models.rs: adduse_iam_auth: Option<bool>toConnectionParams, parsed viaget_str/a bool equivalent infrom_value(mirror the builtin'smodels.rs:219field and its#[serde(default)]intent, adapted to this file's manualValueparsing style).src/client.rs(build_pool):use_iam_authis true, require an enforced TLS mode (require/verify-ca/verify-full) — rejectdisable/prefer/unset with an actionable error, mirroringbuild_mysql_options's refusal (pool_manager.rs:222-229). Postgres has noPreferred-style opportunistic-then-silent-downgrade auto-escalation to worry about the same way MySQL does, but the "must be enforced TLS" rule is identical in spirit.passwordwhenuse_iam_authis true, with a message pointing ataws rds generate-db-auth-token(mirrorpool_manager.rs:243-250).use_iam_authintoconnection_key(client.rs:223-236) alongside the existing TLS params, so IAM and non-IAM pools to the same host:port:database:user never collide — same rationale as the builtin'sbuild_connection_key(pool_manager.rs:111-115).tabularisrepo, out of scope for this plugin but noted for cross-repo coordination): therequire_iam_tokenguard incommands.rs:217and the keychain-skip logic incommands.rs:626-630/commands.rs:1312-1315are host-side and already driver-agnostic (they checkparams.use_iam_authdirectly, notparams.driver) — they should start working for Postgres connections automatically once this plugin declares/accepts the field, provided the frontend checkbox atNewConnectionModal.tsx:3177is also updated to render fordriver === "postgres"(it's currently hard-gated todriver === "mysql"only). That frontend change and any manifest/capability declaration this plugin needs to advertise (use_iam_authsupport) belongs to a follow-up PR/issue intabularisitself, filed once this plugin implements the field.src/client_tests.rscovering:disable/unset TLS → rejected with the actionable error (no live server needed, mirrors the TDD pattern inCLAUDE.md's "TDD for parity bugs without a live database" — this is a pure config-validation branch inbuild_pool/a small extracted helper, testable without a live server).require+ non-empty password → does not hit the TLS/password guards (can't assert full pool success without a real server, but can assert the guard functions returnOk).connection_keydiffers for IAM vs non-IAM given otherwise-identical params.Why the plugin repo, not
tabularisPer tabularis#694's discussion,
@aesslingerproposed migrating this request here since the Postgres driver now lives in the plugin, not the builtin — no further work is planned on a builtin Postgres implementation.