diff --git a/go.mod b/go.mod index 69dcdd18..39a48173 100644 --- a/go.mod +++ b/go.mod @@ -3,6 +3,8 @@ module github.com/terraform-providers/terraform-provider-postgresql go 1.20 require ( + github.com/Azure/azure-sdk-for-go/sdk/azcore v1.7.0 + github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.3.0 github.com/aws/aws-sdk-go-v2 v1.20.0 github.com/aws/aws-sdk-go-v2/config v1.18.32 github.com/aws/aws-sdk-go-v2/feature/rds/auth v1.2.12 @@ -20,6 +22,8 @@ require ( cloud.google.com/go/compute v1.23.0 // indirect cloud.google.com/go/compute/metadata v0.2.3 // indirect contrib.go.opencensus.io/integrations/ocsql v0.1.7 // indirect + github.com/Azure/azure-sdk-for-go/sdk/internal v1.3.0 // indirect + github.com/AzureAD/microsoft-authentication-library-for-go v1.0.0 // indirect github.com/GoogleCloudPlatform/cloudsql-proxy v1.33.9 // indirect github.com/agext/levenshtein v1.2.3 // indirect github.com/apparentlymart/go-textseg/v13 v13.0.0 // indirect @@ -35,6 +39,7 @@ require ( github.com/aws/smithy-go v1.14.0 // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/fatih/color v1.15.0 // indirect + github.com/golang-jwt/jwt/v4 v4.5.0 // indirect github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect github.com/golang/protobuf v1.5.3 // indirect github.com/google/go-cmp v0.5.9 // indirect @@ -62,6 +67,7 @@ require ( github.com/hashicorp/terraform-registry-address v0.2.1 // indirect github.com/hashicorp/terraform-svchost v0.1.1 // indirect github.com/hashicorp/yamux v0.1.1 // indirect + github.com/kylelemons/godebug v1.1.0 // indirect github.com/mattn/go-colorable v0.1.13 // indirect github.com/mattn/go-isatty v0.0.19 // indirect github.com/mitchellh/copystructure v1.2.0 // indirect @@ -70,6 +76,7 @@ require ( github.com/mitchellh/mapstructure v1.5.0 // indirect github.com/mitchellh/reflectwalk v1.0.2 // indirect github.com/oklog/run v1.1.0 // indirect + github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect github.com/vmihailenco/msgpack v4.0.4+incompatible // indirect github.com/vmihailenco/msgpack/v5 v5.3.5 // indirect diff --git a/go.sum b/go.sum index f06c0212..40cdd471 100644 --- a/go.sum +++ b/go.sum @@ -749,13 +749,17 @@ github.com/Azure/azure-sdk-for-go/sdk/azcore v1.1.2/go.mod h1:uGG2W01BaETf0Ozp+Q github.com/Azure/azure-sdk-for-go/sdk/azcore v1.3.0/go.mod h1:tZoQYdDZNOiIjdSn0dVWVfl0NEPGOJqVLzSrcFk4Is0= github.com/Azure/azure-sdk-for-go/sdk/azcore v1.3.1/go.mod h1:DffdKW9RFqa5VgmsjUOsS7UE7eiA5iAvYUs63bhKQ0M= github.com/Azure/azure-sdk-for-go/sdk/azcore v1.6.0/go.mod h1:bjGvMhVMb+EEm3VRNQawDMUyMMjo+S5ewNjflkep/0Q= +github.com/Azure/azure-sdk-for-go/sdk/azcore v1.7.0 h1:8q4SaHjFsClSvuVne0ID/5Ka8u3fcIHyqkLjcFpNRHQ= +github.com/Azure/azure-sdk-for-go/sdk/azcore v1.7.0/go.mod h1:bjGvMhVMb+EEm3VRNQawDMUyMMjo+S5ewNjflkep/0Q= github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.0.0/go.mod h1:+6sju8gk8FRmSajX3Oz4G5Gm7P+mbqE9FVaXXFYTkCM= github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.1.0/go.mod h1:bhXu1AjYL+wutSL/kpSq6s7733q2Rb0yuot9Zgfqa/0= github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.2.1/go.mod h1:gLa1CL2RNE4s7M3yopJ/p0iq5DdY6Yv5ZUt9MTRZOQM= +github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.3.0 h1:vcYCAze6p19qBW7MhZybIsqD8sMV8js0NyQM8JDnVtg= github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.3.0/go.mod h1:OQeznEEkTZ9OrhHJoDD8ZDq51FHgXjqtP9z6bEwBq9U= github.com/Azure/azure-sdk-for-go/sdk/internal v1.0.0/go.mod h1:eWRD7oawr1Mu1sLCawqVc0CUiF43ia3qQMxLscsKQ9w= github.com/Azure/azure-sdk-for-go/sdk/internal v1.1.1/go.mod h1:eWRD7oawr1Mu1sLCawqVc0CUiF43ia3qQMxLscsKQ9w= github.com/Azure/azure-sdk-for-go/sdk/internal v1.1.2/go.mod h1:eWRD7oawr1Mu1sLCawqVc0CUiF43ia3qQMxLscsKQ9w= +github.com/Azure/azure-sdk-for-go/sdk/internal v1.3.0 h1:sXr+ck84g/ZlZUOZiNELInmMgOsuGwdjjVkEIde0OtY= github.com/Azure/azure-sdk-for-go/sdk/internal v1.3.0/go.mod h1:okt5dMMTOFjX/aovMlrjvvXoPMBVSPzk9185BT0+eZM= github.com/Azure/azure-sdk-for-go/sdk/keyvault/azkeys v0.9.0/go.mod h1:EAyXOW1F6BTJPiK2pDvmnvxOHPxoTYWoqBeIlql+QhI= github.com/Azure/azure-sdk-for-go/sdk/keyvault/internal v0.7.0/go.mod h1:9V2j0jn9jDEkCkv8w/bKTNppX/d0FVA1ud77xCIP4KA= @@ -790,6 +794,7 @@ github.com/Azure/go-autorest/tracing v0.6.0/go.mod h1:+vhtPC754Xsa23ID7GlGsrdKBp github.com/AzureAD/microsoft-authentication-library-for-go v0.4.0/go.mod h1:Vt9sXTKwMyGcOxSmLDMnGPgqsUg7m8pe215qMLrDXw4= github.com/AzureAD/microsoft-authentication-library-for-go v0.5.1/go.mod h1:Vt9sXTKwMyGcOxSmLDMnGPgqsUg7m8pe215qMLrDXw4= github.com/AzureAD/microsoft-authentication-library-for-go v0.8.1/go.mod h1:4qFor3D/HDsvBME35Xy9rwW9DecL+M2sNw1ybjPtwA0= +github.com/AzureAD/microsoft-authentication-library-for-go v1.0.0 h1:OBhqkivkhkMqLPymWEppkm7vgPQY2XsHoEkaMQ0AdZY= github.com/AzureAD/microsoft-authentication-library-for-go v1.0.0/go.mod h1:kgDmCTgBzIEPFElEF+FK0SdjAor06dRq2Go927dnQ6o= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= @@ -1422,6 +1427,7 @@ github.com/golang-jwt/jwt/v4 v4.0.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzw github.com/golang-jwt/jwt/v4 v4.2.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzwAxVc6locg= github.com/golang-jwt/jwt/v4 v4.4.2/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0= github.com/golang-jwt/jwt/v4 v4.4.3/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0= +github.com/golang-jwt/jwt/v4 v4.5.0 h1:7cYmW1XlMY7h7ii7UhUyChSgS5wUJEnm9uZVTGqOWzg= github.com/golang-jwt/jwt/v4 v4.5.0/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0= github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0= github.com/golang-sql/civil v0.0.0-20220223132316-b832511892a9/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0= @@ -2078,6 +2084,7 @@ github.com/phpdave11/gofpdi v1.0.13/go.mod h1:vBmVV0Do6hSBHC8uKUQ71JGW+ZGQq74llk github.com/pierrec/lz4 v1.0.2-0.20190131084431-473cd7ce01a1/go.mod h1:3/3N9NVKO0jef7pBehbT1qWhCMrIgbYNnFAZCqQ5LRc= github.com/pierrec/lz4/v4 v4.1.15/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4= github.com/pkg/browser v0.0.0-20210115035449-ce105d075bb4/go.mod h1:N6UoU20jOqggOuDwUaBQpluzLNDqif3kq9z2wpdYEfQ= +github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8 h1:KoWmjvw+nsYOo29YJK9vDA65RGE3NrOnUtO7a+RF9HU= github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8/go.mod h1:HKlIX3XHQyzLZPlr7++PzdhaXEj94dEiJgZDTsxEqUI= github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= diff --git a/postgresql/config.go b/postgresql/config.go index 8ab56d3e..257c97bf 100644 --- a/postgresql/config.go +++ b/postgresql/config.go @@ -238,7 +238,6 @@ func (c *Config) connParams() []string { func (c *Config) connStr(database string) string { host := c.Host - // For GCP, support both project/region/instance and project:region:instance // (The second one allows to use the output of google_sql_database_instance as host if c.Scheme == "gcppostgres" { diff --git a/postgresql/provider.go b/postgresql/provider.go index 702efc94..7f15c92e 100644 --- a/postgresql/provider.go +++ b/postgresql/provider.go @@ -3,6 +3,8 @@ package postgresql import ( "context" "fmt" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/policy" + "github.com/Azure/azure-sdk-for-go/sdk/azidentity" "os" "github.com/blang/semver" @@ -87,6 +89,20 @@ func Provider() *schema.Provider { Description: "AWS region to use for IAM auth", }, + "azure_identity_auth": { + Type: schema.TypeBool, + Optional: true, + Description: "Use MS Azure identity OAuth token " + + "(see: https://learn.microsoft.com/en-us/azure/postgresql/flexible-server/how-to-configure-sign-in-azure-ad-authentication)", + }, + + "azure_tenant_id": { + Type: schema.TypeString, + Optional: true, + Default: "", + Description: "MS Azure tenant ID (see: https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/data-sources/client_config.html)", + }, + // Conection username can be different than database username with user name mapas (e.g.: in Azure) // See https://www.postgresql.org/docs/current/auth-username-maps.html "database_username": { @@ -250,6 +266,22 @@ func createGoogleCredsFileIfNeeded() error { return os.Setenv("GOOGLE_APPLICATION_CREDENTIALS", tmpFile.Name()) } +func acquireAzureOauthToken(tenantId string) (string, error) { + credential, err := azidentity.NewDefaultAzureCredential( + &azidentity.DefaultAzureCredentialOptions{TenantID: tenantId}) + if err != nil { + return "", err + } + token, err := credential.GetToken(context.Background(), policy.TokenRequestOptions{ + Scopes: []string{"https://ossrdbms-aad.database.windows.net/.default"}, + TenantID: tenantId, + }) + if err != nil { + return "", err + } + return token.Token, nil +} + func providerConfigure(d *schema.ResourceData) (interface{}, error) { var sslMode string if sslModeRaw, ok := d.GetOk("sslmode"); ok { @@ -276,6 +308,16 @@ func providerConfigure(d *schema.ResourceData) (interface{}, error) { if err != nil { return nil, err } + } else if d.Get("azure_identity_auth").(bool) { + tenantId := d.Get("azure_tenant_id").(string) + if tenantId == "" { + return nil, fmt.Errorf("postgresql: azure_identity_auth is enabled, azure_tenant_id must be provided also") + } + var err error + password, err = acquireAzureOauthToken(tenantId) + if err != nil { + return nil, err + } } else { password = d.Get("password").(string) } diff --git a/website/docs/index.html.markdown b/website/docs/index.html.markdown index a455cb3d..2e5287d8 100644 --- a/website/docs/index.html.markdown +++ b/website/docs/index.html.markdown @@ -115,6 +115,8 @@ The following arguments are supported: from the environment (or the given profile, see `aws_rds_iam_profile`) * `aws_rds_iam_profile` - (Optional) The AWS IAM Profile to use while using AWS RDS IAM Auth. * `aws_rds_iam_region` - (Optional) The AWS region to use while using AWS RDS IAM Auth. +* `azure_identity_auth` - (Optional) If set to `true`, call the Azure OAuth token endpoint for temporary token +* `azure_tenant_id` - (Optional) (Required if `azure_identity_auth` is `true`) Azure tenant ID [read more](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/data-sources/client_config.html) ## GoCloud @@ -199,6 +201,45 @@ resource postgresql_database "test_db" { } ``` +### Azure + +To enable [passwordless authentication](https://learn.microsoft.com/en-us/azure/postgresql/flexible-server/how-to-configure-sign-in-azure-ad-authentication) with MS Azure set `azure_identity_auth` to `true` and provide `azure_tenant_id` + +```hcl +data "azurerm_client_config" "current" { +} + +# https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/postgresql_flexible_server +resource "azurerm_postgresql_flexible_server" "pgsql" { + # ... + authentication { + active_directory_auth_enabled = true + password_auth_enabled = false + tenant_id = data.azurerm_client_config.current.tenant_id + } +} + +# https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/postgresql_flexible_server_active_directory_administrator +resource "azurerm_postgresql_flexible_server_active_directory_administrator" "administrators" { + object_id = "00000000-0000-0000-0000-000000000000" + principal_name = "Azure AD Admin Group" + principal_type = "Group" + resource_group_name = var.rg_name + server_name = azurerm_postgresql_flexible_server.pgsql.name + tenant_id = data.azurerm_client_config.current.tenant_id +} + +provider "postgresql" { + host = azurerm_postgresql_flexible_server.pgsql.fqdn + port = 5432 + database = "postgres" + username = azurerm_postgresql_flexible_server_active_directory_administrator.administrators.principal_name + sslmode = "require" + azure_identity_auth = true + azure_tenant_id = data.azurerm_client_config.current.tenant_id +} +``` + ### SOCKS5 Proxy Support The provider supports connecting via a SOCKS5 proxy, but when the `postgres` scheme is used. It can be configured by setting the `ALL_PROXY` or `all_proxy` environment variable to a value like `socks5://127.0.0.1:1080`.