Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for configuring username and password fields for select DB Engines #1331

Merged
merged 13 commits into from
Feb 10, 2022
Merged
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ IMPROVEMENTS:
intermediate and issuing CA certificates (PEM encoded) ([#1330](https://github.com/hashicorp/terraform-provider-vault/pull/1330))
* `resource/azure_secret_backend`: Add support for setting `use_microsoft_graph_api` ([#1335](https://github.com/hashicorp/terraform-provider-vault/pull/1335))
* `r/d/kubernetes_auth_backend_role`: Add support for setting and getting `alias_name_source` ([#1336](https://github.com/hashicorp/terraform-provider-vault/pull/1336))
* `resource/database_secret_backend_connection`: Add `username` and `password` fields to all DB Engines that support them ([#1331](https://github.com/hashicorp/terraform-provider-vault/pull/1331))

## 3.2.1 (January 20, 2022)
BUGS:
Expand Down
147 changes: 93 additions & 54 deletions vault/resource_database_secret_backend_connection.go
Original file line number Diff line number Diff line change
Expand Up @@ -443,10 +443,12 @@ func databaseSecretBackendConnectionResource() *schema.Resource {
},

dbEngineMongoDB.name: {
Type: schema.TypeList,
Optional: true,
Description: "Connection parameters for the mongodb-database-plugin plugin.",
Elem: connectionStringResource(&connectionStringConfig{}),
Type: schema.TypeList,
Optional: true,
Description: "Connection parameters for the mongodb-database-plugin plugin.",
Elem: connectionStringResource(&connectionStringConfig{
includeUserPass: true,
}),
MaxItems: 1,
ConflictsWith: util.CalculateConflictsWith(dbEngineMongoDB.Name(), dbEngineTypes),
},
Expand Down Expand Up @@ -485,6 +487,7 @@ func databaseSecretBackendConnectionResource() *schema.Resource {
Description: "Connection parameters for the hana-database-plugin plugin.",
Elem: connectionStringResource(&connectionStringConfig{
excludeUsernameTemplate: true,
includeUserPass: true,
}),
MaxItems: 1,
ConflictsWith: util.CalculateConflictsWith(dbEngineHana.Name(), dbEngineTypes),
Expand All @@ -508,62 +511,76 @@ func databaseSecretBackendConnectionResource() *schema.Resource {
ConflictsWith: util.CalculateConflictsWith(dbEngineMySQL.Name(), dbEngineTypes),
},
dbEngineMySQLRDS.name: {
Type: schema.TypeList,
Optional: true,
Description: "Connection parameters for the mysql-rds-database-plugin plugin.",
Elem: connectionStringResource(&connectionStringConfig{}),
Type: schema.TypeList,
Optional: true,
Description: "Connection parameters for the mysql-rds-database-plugin plugin.",
Elem: connectionStringResource(&connectionStringConfig{
includeUserPass: true,
}),
MaxItems: 1,
ConflictsWith: util.CalculateConflictsWith(dbEngineMySQLRDS.Name(), dbEngineTypes),
},
dbEngineMySQLAurora.name: {
Type: schema.TypeList,
Optional: true,
Description: "Connection parameters for the mysql-aurora-database-plugin plugin.",
Elem: connectionStringResource(&connectionStringConfig{}),
Type: schema.TypeList,
Optional: true,
Description: "Connection parameters for the mysql-aurora-database-plugin plugin.",
Elem: connectionStringResource(&connectionStringConfig{
includeUserPass: true,
}),
MaxItems: 1,
ConflictsWith: util.CalculateConflictsWith(dbEngineMySQLAurora.Name(), dbEngineTypes),
},
dbEngineMySQLLegacy.name: {
Type: schema.TypeList,
Optional: true,
Description: "Connection parameters for the mysql-legacy-database-plugin plugin.",
Elem: connectionStringResource(&connectionStringConfig{}),
Type: schema.TypeList,
Optional: true,
Description: "Connection parameters for the mysql-legacy-database-plugin plugin.",
Elem: connectionStringResource(&connectionStringConfig{
includeUserPass: true,
}),
MaxItems: 1,
ConflictsWith: util.CalculateConflictsWith(dbEngineMySQLLegacy.Name(), dbEngineTypes),
},

dbEnginePostgres.name: {
Type: schema.TypeList,
Optional: true,
Description: "Connection parameters for the postgresql-database-plugin plugin.",
Elem: connectionStringResource(&connectionStringConfig{}),
Type: schema.TypeList,
Optional: true,
Description: "Connection parameters for the postgresql-database-plugin plugin.",
Elem: connectionStringResource(&connectionStringConfig{
includeUserPass: true,
}),
MaxItems: 1,
ConflictsWith: util.CalculateConflictsWith(dbEnginePostgres.Name(), dbEngineTypes),
},

dbEngineOracle.name: {
Type: schema.TypeList,
Optional: true,
Description: "Connection parameters for the oracle-database-plugin plugin.",
Elem: connectionStringResource(&connectionStringConfig{}),
Type: schema.TypeList,
Optional: true,
Description: "Connection parameters for the oracle-database-plugin plugin.",
Elem: connectionStringResource(&connectionStringConfig{
includeUserPass: true,
}),
MaxItems: 1,
ConflictsWith: util.CalculateConflictsWith(dbEngineOracle.Name(), dbEngineTypes),
},

dbEngineRedshift.name: {
Type: schema.TypeList,
Optional: true,
Description: "Connection parameters for the redshift-database-plugin plugin.",
Elem: connectionStringResource(&connectionStringConfig{includeUserPass: true}),
Type: schema.TypeList,
Optional: true,
Description: "Connection parameters for the redshift-database-plugin plugin.",
Elem: connectionStringResource(&connectionStringConfig{
includeUserPass: true,
}),
MaxItems: 1,
ConflictsWith: util.CalculateConflictsWith(dbEngineRedshift.Name(), dbEngineTypes),
},

dbEngineSnowflake.name: {
Type: schema.TypeList,
Optional: true,
Description: "Connection parameters for the snowflake-database-plugin plugin.",
Elem: connectionStringResource(&connectionStringConfig{includeUserPass: true}),
Type: schema.TypeList,
Optional: true,
Description: "Connection parameters for the snowflake-database-plugin plugin.",
Elem: connectionStringResource(&connectionStringConfig{
includeUserPass: true,
}),
MaxItems: 1,
ConflictsWith: util.CalculateConflictsWith(dbEngineSnowflake.Name(), dbEngineTypes),
},
Expand Down Expand Up @@ -634,7 +651,9 @@ func connectionStringResource(config *connectionStringConfig) *schema.Resource {
}

func mysqlConnectionStringResource() *schema.Resource {
r := connectionStringResource(&connectionStringConfig{})
r := connectionStringResource(&connectionStringConfig{
includeUserPass: true,
})
r.Schema["tls_certificate_key"] = &schema.Schema{
Type: schema.TypeString,
Optional: true,
Expand All @@ -650,7 +669,9 @@ func mysqlConnectionStringResource() *schema.Resource {
}

func mssqlConnectionStringResource() *schema.Resource {
r := connectionStringResource(&connectionStringConfig{})
r := connectionStringResource(&connectionStringConfig{
includeUserPass: true,
})
r.Schema["contained_db"] = &schema.Schema{
Type: schema.TypeBool,
Optional: true,
Expand Down Expand Up @@ -729,9 +750,9 @@ func getDatabaseAPIData(d *schema.ResourceData) (map[string]interface{}, error)
case dbEngineInfluxDB:
setInfluxDBDatabaseConnectionData(d, "influxdb.0.", data)
case dbEngineHana:
setDatabaseConnectionData(d, "hana.0.", data)
setDatabaseConnectionDataWithUserPass(d, "hana.0.", data)
case dbEngineMongoDB:
setDatabaseConnectionData(d, "mongodb.0.", data)
setDatabaseConnectionDataWithUserPass(d, "mongodb.0.", data)
case dbEngineMongoDBAtlas:
if v, ok := d.GetOk("mongodbatlas.0.public_key"); ok {
data["public_key"] = v.(string)
Expand All @@ -747,15 +768,15 @@ func getDatabaseAPIData(d *schema.ResourceData) (map[string]interface{}, error)
case dbEngineMySQL:
setMySQLDatabaseConnectionData(d, "mysql.0.", data)
case dbEngineMySQLRDS:
setDatabaseConnectionData(d, "mysql_rds.0.", data)
setDatabaseConnectionDataWithUserPass(d, "mysql_rds.0.", data)
case dbEngineMySQLAurora:
setDatabaseConnectionData(d, "mysql_aurora.0.", data)
setDatabaseConnectionDataWithUserPass(d, "mysql_aurora.0.", data)
case dbEngineMySQLLegacy:
setDatabaseConnectionData(d, "mysql_legacy.0.", data)
setDatabaseConnectionDataWithUserPass(d, "mysql_legacy.0.", data)
case dbEngineOracle:
setDatabaseConnectionData(d, "oracle.0.", data)
setDatabaseConnectionDataWithUserPass(d, "oracle.0.", data)
case dbEnginePostgres:
setDatabaseConnectionData(d, "postgresql.0.", data)
setDatabaseConnectionDataWithUserPass(d, "postgresql.0.", data)
case dbEngineElasticSearch:
setElasticsearchDatabaseConnectionData(d, "elasticsearch.0.", data)
case dbEngineSnowflake:
Expand Down Expand Up @@ -818,7 +839,7 @@ func getConnectionDetailsFromResponse(d *schema.ResourceData, prefix string, res
}

func getMSSQLConnectionDetailsFromResponse(d *schema.ResourceData, prefix string, resp *api.Secret) ([]map[string]interface{}, error) {
result := getConnectionDetailsFromResponse(d, prefix, resp)
result := getConnectionDetailsFromResponseWithUserPass(d, prefix, resp)
if result == nil {
return nil, nil
}
Expand All @@ -831,11 +852,12 @@ func getMSSQLConnectionDetailsFromResponse(d *schema.ResourceData, prefix string
}
result[0]["contained_db"] = containedDB
}

return result, nil
}

func getMySQLConnectionDetailsFromResponse(d *schema.ResourceData, prefix string, resp *api.Secret) []map[string]interface{} {
commonDetails := getConnectionDetailsFromResponse(d, prefix, resp)
commonDetails := getConnectionDetailsFromResponseWithUserPass(d, prefix, resp)
details := resp.Data["connection_details"]
data, ok := details.(map[string]interface{})
if !ok {
Expand Down Expand Up @@ -984,7 +1006,7 @@ func getInfluxDBConnectionDetailsFromResponse(d *schema.ResourceData, prefix str
}

func getSnowflakeConnectionDetailsFromResponse(d *schema.ResourceData, prefix string, resp *api.Secret) []map[string]interface{} {
commonDetails := getConnectionDetailsFromResponse(d, prefix, resp)
commonDetails := getConnectionDetailsFromResponseWithUserPass(d, prefix, resp)
details := resp.Data["connection_details"]
data, ok := details.(map[string]interface{})
if !ok {
Expand Down Expand Up @@ -1015,6 +1037,23 @@ func getSnowflakeConnectionDetailsFromResponse(d *schema.ResourceData, prefix st
return []map[string]interface{}{result}
}

func getConnectionDetailsFromResponseWithUserPass(d *schema.ResourceData, prefix string, resp *api.Secret) []map[string]interface{} {
result := getConnectionDetailsFromResponse(d, prefix, resp)
if result == nil {
return nil
}

details := resp.Data["connection_details"].(map[string]interface{})
if v, ok := details["username"]; ok {
result[0]["username"] = v.(string)
}
if v, ok := d.GetOk(prefix + "password"); ok {
result[0]["password"] = v.(string)
}

return result
}

func setDatabaseConnectionData(d *schema.ResourceData, prefix string, data map[string]interface{}) {
if v, ok := d.GetOk(prefix + "connection_url"); ok {
data["connection_url"] = v.(string)
Expand All @@ -1034,7 +1073,7 @@ func setDatabaseConnectionData(d *schema.ResourceData, prefix string, data map[s
}

func setMSSQLDatabaseConnectionData(d *schema.ResourceData, prefix string, data map[string]interface{}) {
setDatabaseConnectionData(d, prefix, data)
setDatabaseConnectionDataWithUserPass(d, prefix, data)
if v, ok := d.GetOk(prefix + "contained_db"); ok {
// TODO:
// we have to pass string value here due to an issue with the
Expand All @@ -1045,7 +1084,7 @@ func setMSSQLDatabaseConnectionData(d *schema.ResourceData, prefix string, data
}

func setMySQLDatabaseConnectionData(d *schema.ResourceData, prefix string, data map[string]interface{}) {
setDatabaseConnectionData(d, prefix, data)
setDatabaseConnectionDataWithUserPass(d, prefix, data)
if v, ok := d.GetOk(prefix + "tls_certificate_key"); ok {
data["tls_certificate_key"] = v.(string)
}
Expand Down Expand Up @@ -1284,9 +1323,9 @@ func databaseSecretBackendConnectionRead(d *schema.ResourceData, meta interface{
case dbEngineInfluxDB:
d.Set("influxdb", getInfluxDBConnectionDetailsFromResponse(d, "influxdb.0.", resp))
case dbEngineHana:
d.Set("hana", getConnectionDetailsFromResponse(d, "hana.0.", resp))
d.Set("hana", getConnectionDetailsFromResponseWithUserPass(d, "hana.0.", resp))
case dbEngineMongoDB:
d.Set("mongodb", getConnectionDetailsFromResponse(d, "mongodb.0.", resp))
d.Set("mongodb", getConnectionDetailsFromResponseWithUserPass(d, "mongodb.0.", resp))
case dbEngineMongoDBAtlas:
details := resp.Data["connection_details"]
data, ok := details.(map[string]interface{})
Expand All @@ -1313,21 +1352,21 @@ func databaseSecretBackendConnectionRead(d *schema.ResourceData, meta interface{
case dbEngineMySQL:
d.Set("mysql", getMySQLConnectionDetailsFromResponse(d, "mysql.0.", resp))
case dbEngineMySQLRDS:
d.Set("mysql_rds", getConnectionDetailsFromResponse(d, "mysql_rds.0.", resp))
d.Set("mysql_rds", getConnectionDetailsFromResponseWithUserPass(d, "mysql_rds.0.", resp))
case dbEngineMySQLAurora:
d.Set("mysql_aurora", getConnectionDetailsFromResponse(d, "mysql_aurora.0.", resp))
d.Set("mysql_aurora", getConnectionDetailsFromResponseWithUserPass(d, "mysql_aurora.0.", resp))
case dbEngineMySQLLegacy:
d.Set("mysql_legacy", getConnectionDetailsFromResponse(d, "mysql_legacy.0.", resp))
d.Set("mysql_legacy", getConnectionDetailsFromResponseWithUserPass(d, "mysql_legacy.0.", resp))
case dbEngineOracle:
d.Set("oracle", getConnectionDetailsFromResponse(d, "oracle.0.", resp))
d.Set("oracle", getConnectionDetailsFromResponseWithUserPass(d, "oracle.0.", resp))
case dbEnginePostgres:
d.Set("postgresql", getConnectionDetailsFromResponse(d, "postgresql.0.", resp))
d.Set("postgresql", getConnectionDetailsFromResponseWithUserPass(d, "postgresql.0.", resp))
case dbEngineElasticSearch:
d.Set("elasticsearch", getElasticsearchConnectionDetailsFromResponse(d, "elasticsearch.0.", resp))
case dbEngineSnowflake:
d.Set("snowflake", getSnowflakeConnectionDetailsFromResponse(d, "snowflake.0.", resp))
case dbEngineRedshift:
d.Set("redshift", getConnectionDetailsFromResponse(d, "redshift.0.", resp))
d.Set("redshift", getConnectionDetailsFromResponseWithUserPass(d, "redshift.0.", resp))
default:
return fmt.Errorf("no response handler for dbEngine: %s", db)
}
Expand Down
Loading