diff --git a/CHANGELOG.md b/CHANGELOG.md index fb789b06f..0c944ebfd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ ## Unreleased +FEATURES: + +* Update `vault_database_secret_backend_connection`to support `password_authentication` for PostgreSQL, allowing to encrypt password before being passed to PostgreSQL ([#2371](https://github.com/hashicorp/terraform-provider-vault/pull/2371)) + ## 4.5.0 (Nov 19, 2024) FEATURES: diff --git a/vault/resource_database_secret_backend_connection.go b/vault/resource_database_secret_backend_connection.go index 50bf82028..d394d5d54 100644 --- a/vault/resource_database_secret_backend_connection.go +++ b/vault/resource_database_secret_backend_connection.go @@ -836,6 +836,12 @@ func postgresConnectionStringResource() *schema.Resource { Optional: true, Description: "If set, allows onboarding static roles with a rootless connection configuration.", } + r.Schema["password_authentication"] = &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Default: "password", + Description: "When set to `scram-sha-256`, passwords will be hashed by Vault before being sent to PostgreSQL.", + } return r } @@ -1150,6 +1156,12 @@ func getPostgresConnectionDetailsFromResponse(d *schema.ResourceData, prefix str } } + if provider.IsAPISupported(meta, provider.VaultVersion114) { + if v, ok := data["password_authentication"]; ok { + result["password_authentication"] = v.(string) + } + } + if provider.IsAPISupported(meta, provider.VaultVersion118) { if v, ok := data["tls_ca"]; ok { result["tls_ca"] = v.(string) @@ -1571,6 +1583,12 @@ func setPostgresDatabaseConnectionData(d *schema.ResourceData, prefix string, da } } + if provider.IsAPISupported(meta, provider.VaultVersion114) { + if v, ok := d.GetOk(prefix + "password_authentication"); ok { + data["password_authentication"] = v.(string) + } + } + if provider.IsAPISupported(meta, provider.VaultVersion118) && provider.IsEnterpriseSupported(meta) { if v, ok := d.GetOk(prefix + "self_managed"); ok { data["self_managed"] = v.(bool) diff --git a/vault/resource_database_secret_backend_connection_test.go b/vault/resource_database_secret_backend_connection_test.go index 69e85fe17..104aec513 100644 --- a/vault/resource_database_secret_backend_connection_test.go +++ b/vault/resource_database_secret_backend_connection_test.go @@ -812,6 +812,7 @@ func TestAccDatabaseSecretBackendConnection_postgresql(t *testing.T) { resource.TestCheckResourceAttr(testDefaultDatabaseSecretBackendResource, "root_rotation_statements.0", "FOOBAR"), resource.TestCheckResourceAttr(testDefaultDatabaseSecretBackendResource, "verify_connection", "true"), resource.TestCheckResourceAttr(testDefaultDatabaseSecretBackendResource, "postgresql.0.connection_url", connURL), + resource.TestCheckResourceAttr(testDefaultDatabaseSecretBackendResource, "postgresql.0.password_authentication", "password"), resource.TestCheckResourceAttr(testDefaultDatabaseSecretBackendResource, "postgresql.0.max_open_connections", maxOpenConnections), resource.TestCheckResourceAttr(testDefaultDatabaseSecretBackendResource, "postgresql.0.max_idle_connections", maxIdleConnections), resource.TestCheckResourceAttr(testDefaultDatabaseSecretBackendResource, "postgresql.0.max_connection_lifetime", maxConnLifetime), @@ -833,6 +834,12 @@ func TestAccDatabaseSecretBackendConnection_postgresql(t *testing.T) { resource.TestCheckResourceAttr(testDefaultDatabaseSecretBackendResource, "postgresql.0.username_template", ""), ), }, + { + Config: testAccDatabaseSecretBackendConnectionConfig_postgresql_password_authentication(name, backend, parsedURL), + Check: testComposeCheckFuncCommonDatabaseSecretBackend(name, backend, pluginName, + resource.TestCheckResourceAttr(testDefaultDatabaseSecretBackendResource, "postgresql.0.password_authentication", "scram-sha-256"), + ), + }, }, }) } @@ -1771,6 +1778,27 @@ resource "vault_database_secret_backend_connection" "test" { `, path, name, parsedURL.String()) } +func testAccDatabaseSecretBackendConnectionConfig_postgresql_password_authentication(name, path string, parsedURL *url.URL) string { + return fmt.Sprintf(` +resource "vault_mount" "db" { + path = "%s" + type = "database" +} + +resource "vault_database_secret_backend_connection" "test" { + backend = vault_mount.db.path + name = "%s" + allowed_roles = ["dev", "prod"] + root_rotation_statements = ["FOOBAR"] + + postgresql { + connection_url = "%s" + password_authentication = "scram-sha-256" + } +} +`, path, name, parsedURL.String()) +} + func testAccDatabaseSecretBackendConnectionConfig_postgresql_tls(name, path, tlsCA, tlsCert, privateKey string) string { return fmt.Sprintf(` resource "vault_mount" "db" { @@ -1849,7 +1877,7 @@ resource "vault_database_secret_backend_connection" "test" { allowed_roles = ["dev", "prod"] root_rotation_statements = ["FOOBAR"] - snowflake { + snowflake { connection_url = "%s" username = "%s" password = "%s" diff --git a/website/docs/r/database_secret_backend_connection.md b/website/docs/r/database_secret_backend_connection.md index fab521f1a..eaf6bccbd 100644 --- a/website/docs/r/database_secret_backend_connection.md +++ b/website/docs/r/database_secret_backend_connection.md @@ -124,7 +124,7 @@ Exactly one of the nested blocks of configuration options must be supplied. * `connect_timeout` - (Optional) The number of seconds to use as a connection timeout. -* `skip_verification` - (Optional) Skip permissions checks when a connection to Cassandra is first created. +* `skip_verification` - (Optional) Skip permissions checks when a connection to Cassandra is first created. These checks ensure that Vault is able to create roles, but can be resource intensive in clusters with many roles. ### Couchbase Configuration Options @@ -328,8 +328,8 @@ See the [Vault * `password` - (Optional) The root credential password used in the connection URL. -* `self_managed` - (Optional) If set, allows onboarding static roles with a rootless - connection configuration. Mutually exclusive with `username` and `password`. +* `self_managed` - (Optional) If set, allows onboarding static roles with a rootless + connection configuration. Mutually exclusive with `username` and `password`. If set, will force `verify_connection` to be false. Requires Vault 1.18+ Enterprise. * `tls_ca` - (Optional) The x509 CA file for validating the certificate @@ -338,6 +338,10 @@ See the [Vault * `tls_certificate` - (Optional) The x509 client certificate for connecting to the database. Must be PEM encoded. +* `password_authentication` - (Optional) When set to `scram-sha-256`, passwords will be + hashed by Vault before being sent to PostgreSQL. See the [Vault docs](https://www.vaultproject.io/api-docs/secret/databases/postgresql.html#sample-payload) + for an example. Requires Vault 1.14+. + * `private_key` - (Optional) The secret key used for the x509 client certificate. Must be PEM encoded.