From 0737c1ac60ca2703522086cc1137e2dc5eb9e9b7 Mon Sep 17 00:00:00 2001 From: Tom Bamford Date: Tue, 9 Apr 2024 16:48:29 +0100 Subject: [PATCH 1/6] dependencies: updating to `v0.20240411.1104331` of `github.com/hashicorp/go-azure-sdk/sdk` --- go.mod | 4 +- go.sum | 8 +- .../sdk/auth/azure_cli_authorizer.go | 24 ++- .../sdk/auth/shared_key_authorizer.go | 14 +- .../sdk/environments/azure_china.go | 33 ++-- .../sdk/environments/azure_gov.go | 25 ++- .../sdk/environments/azure_public.go | 24 +-- .../sdk/environments/azure_public_canary.go | 2 +- .../sdk/environments/endpoint_refresh.go | 63 ++++--- .../sdk/environments/environment.go | 7 +- .../sdk/environments/from_endpoint.go | 6 +- .../go-azure-sdk/sdk/environments/helpers.go | 67 ++++---- .../sdk/environments/interfaces.go | 15 ++ .../sdk/internal/azurecli/azcli.go | 86 +++++++--- .../sdk/internal/metadata/client.go | 155 +++++------------- .../sdk/internal/metadata/models.go | 25 +-- vendor/modules.txt | 4 +- 17 files changed, 299 insertions(+), 263 deletions(-) diff --git a/go.mod b/go.mod index d5a8ac9103..0f2df39e73 100644 --- a/go.mod +++ b/go.mod @@ -2,8 +2,8 @@ module github.com/hashicorp/terraform-provider-azuread require ( github.com/google/go-cmp v0.5.9 - github.com/hashicorp/go-azure-helpers v0.66.1 - github.com/hashicorp/go-azure-sdk/sdk v0.20240125.1122928 + github.com/hashicorp/go-azure-helpers v0.66.2 + github.com/hashicorp/go-azure-sdk/sdk v0.20240411.1104331 github.com/hashicorp/go-cty v1.4.1-0.20200414143053-d3edf31b6320 github.com/hashicorp/go-multierror v1.1.1 github.com/hashicorp/go-uuid v1.0.3 diff --git a/go.sum b/go.sum index 65e2d8bae0..5ca070eb3b 100644 --- a/go.sum +++ b/go.sum @@ -49,10 +49,10 @@ github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeN github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I= github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= -github.com/hashicorp/go-azure-helpers v0.66.1 h1:SokAckK9hvQ9PZO2TmZY/CGru8KWJ4A7hcRUggHMEus= -github.com/hashicorp/go-azure-helpers v0.66.1/go.mod h1:kJxXrFtJKJdOEqvad8pllAe7dhP4DbN8J6sqFZe47+4= -github.com/hashicorp/go-azure-sdk/sdk v0.20240125.1122928 h1:RzRXiA9rVdERF7Y4ELqcaqlbM7oyqizqKu7+CfLVzZY= -github.com/hashicorp/go-azure-sdk/sdk v0.20240125.1122928/go.mod h1:6jgkzx26qtPndLSW5u7pKIw4m3iiFiLnHlp7yDQ2Crc= +github.com/hashicorp/go-azure-helpers v0.66.2 h1:+Pzuo7pdKl0hBXXr5ymmhs4Q40tHAo2nAvHq4WgSjx8= +github.com/hashicorp/go-azure-helpers v0.66.2/go.mod h1:kJxXrFtJKJdOEqvad8pllAe7dhP4DbN8J6sqFZe47+4= +github.com/hashicorp/go-azure-sdk/sdk v0.20240411.1104331 h1:LYQI0A1rWPjrMa0J8N8MA5ZjFfHNaVpoPY1vmzrS/C8= +github.com/hashicorp/go-azure-sdk/sdk v0.20240411.1104331/go.mod h1:POOjeoqNp+mvlLBuibJTziUAkBZ7FxXGeGestwemL/w= github.com/hashicorp/go-checkpoint v0.5.0 h1:MFYpPZCnQqQTE18jFwSII6eUQrD/oxMFp3mlgcqk5mU= github.com/hashicorp/go-checkpoint v0.5.0/go.mod h1:7nfLNL10NsxqO4iWuW6tWW0HjZuDrwkBuEQsVcpCOgg= github.com/hashicorp/go-cleanhttp v0.5.0/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= diff --git a/vendor/github.com/hashicorp/go-azure-sdk/sdk/auth/azure_cli_authorizer.go b/vendor/github.com/hashicorp/go-azure-sdk/sdk/auth/azure_cli_authorizer.go index ac697ea301..ba1853eca6 100644 --- a/vendor/github.com/hashicorp/go-azure-sdk/sdk/auth/azure_cli_authorizer.go +++ b/vendor/github.com/hashicorp/go-azure-sdk/sdk/auth/azure_cli_authorizer.go @@ -65,9 +65,29 @@ func (a *AzureCliAuthorizer) Token(_ context.Context, _ *http.Request) (*oauth2. } azArgs = append(azArgs, "--scope", *scope) + accountType, err := azurecli.GetAccountType() + if err != nil { + return nil, fmt.Errorf("determining account type: %+v", err) + } + + accountName, err := azurecli.GetAccountName() + if err != nil { + return nil, fmt.Errorf("determining account name: %+v", err) + } + + tenantIdRequired := true + // Try to detect if we're running in Cloud Shell - if cloudShell := os.Getenv("AZUREPS_HOST_ENVIRONMENT"); !strings.HasPrefix(cloudShell, "cloud-shell/") { - // Seemingly not, so we'll append the tenant ID to the az args + if cloudShell := os.Getenv("AZUREPS_HOST_ENVIRONMENT"); strings.HasPrefix(cloudShell, "cloud-shell/") { + tenantIdRequired = false + } + + // Try to detect whether authenticated principal is a managed identity + if accountType != nil && accountName != nil && *accountType == "servicePrincipal" && (*accountName == "systemAssignedIdentity" || *accountName == "userAssignedIdentity") { + tenantIdRequired = false + } + + if tenantIdRequired { azArgs = append(azArgs, "--tenant", a.conf.TenantID) } diff --git a/vendor/github.com/hashicorp/go-azure-sdk/sdk/auth/shared_key_authorizer.go b/vendor/github.com/hashicorp/go-azure-sdk/sdk/auth/shared_key_authorizer.go index 3a9ff1ea7b..b4cf159438 100644 --- a/vendor/github.com/hashicorp/go-azure-sdk/sdk/auth/shared_key_authorizer.go +++ b/vendor/github.com/hashicorp/go-azure-sdk/sdk/auth/shared_key_authorizer.go @@ -13,6 +13,7 @@ import ( "net/http" "net/url" "sort" + "strconv" "strings" "time" @@ -68,7 +69,6 @@ const ( storageEmulatorAccountName string = "devstoreaccount1" headerContentEncoding = "Content-Encoding" - headerContentLength = "Content-Length" headerContentMD5 = "Content-MD5" headerContentLanguage = "Content-Language" headerContentType = "Content-Type" @@ -96,7 +96,7 @@ func buildSharedKey(accName string, accKey []byte, req *http.Request, keyType Sh date := time.Now().UTC().Format(http.TimeFormat) req.Header.Set(headerXMSDate, date) } - canString, err := buildCanonicalizedString(req.Method, req.Header, canRes, keyType) + canString, err := buildCanonicalizedString(req.Method, req.ContentLength, req.Header, canRes, keyType) if err != nil { return "", err } @@ -168,10 +168,10 @@ func getCanonicalizedAccountName(accountName string) string { return strings.TrimSuffix(accountName, "-secondary") } -func buildCanonicalizedString(verb string, headers http.Header, canonicalizedResource string, keyType SharedKeyType) (string, error) { - contentLength := headers.Get(headerContentLength) - if contentLength == "0" { - contentLength = "" +func buildCanonicalizedString(verb string, contentLength int64, headers http.Header, canonicalizedResource string, keyType SharedKeyType) (string, error) { + var contentLengthString string + if contentLength > 0 { + contentLengthString = strconv.Itoa(int(contentLength)) } date := headers.Get(headerDate) if v := headers.Get(headerXMSDate); v != "" { @@ -188,7 +188,7 @@ func buildCanonicalizedString(verb string, headers http.Header, canonicalizedRes verb, headers.Get(headerContentEncoding), headers.Get(headerContentLanguage), - contentLength, + contentLengthString, headers.Get(headerContentMD5), headers.Get(headerContentType), date, diff --git a/vendor/github.com/hashicorp/go-azure-sdk/sdk/environments/azure_china.go b/vendor/github.com/hashicorp/go-azure-sdk/sdk/environments/azure_china.go index 423288aa5f..056ef77b62 100644 --- a/vendor/github.com/hashicorp/go-azure-sdk/sdk/environments/azure_china.go +++ b/vendor/github.com/hashicorp/go-azure-sdk/sdk/environments/azure_china.go @@ -17,32 +17,27 @@ func AzureChina() *Environment { LoginEndpoint: "https://login.chinacloudapi.cn", Tenant: "common", } - env.ResourceManager = ResourceManagerAPI("https://management.chinacloudapi.cn").withResourceIdentifier("https://management.chinacloudapi.cn") - env.MicrosoftGraph = MicrosoftGraphAPI("https://microsoftgraph.chinacloudapi.cn").withResourceIdentifier("https://microsoftgraph.chinacloudapi.cn") + env.ResourceManager = ResourceManagerAPI("https://management.chinacloudapi.cn") + env.MicrosoftGraph = MicrosoftGraphAPI("https://microsoftgraph.chinacloudapi.cn") - // DataLake, ManagedHSM and OperationalInsights are not available env.ApiManagement = ApiManagementAPI("azure-api.cn") env.AppConfiguration = AppConfigurationAPI("azconfig.azure.cn") - env.Batch = BatchAPI("https://batch.chinacloudapi.cn").withResourceIdentifier("https://batch.chinacloudapi.cn") + env.Batch = BatchAPI("https://batch.chinacloudapi.cn") env.ContainerRegistry = ContainerRegistryAPI("azurecr.cn") env.CosmosDB = CosmosDBAPI("documents.azure.cn") - env.KeyVault = KeyVaultAPI("vault.azure.cn").withResourceIdentifier("https://vault.azure.cn") - env.MariaDB = MariaDBAPI("mariadb.database.chinacloudapi.cn").withResourceIdentifier("https://ossrdbms-aad.database.chinacloudapi.cn") - env.MySql = MySqlAPI("mysql.database.chinacloudapi.cn").withResourceIdentifier("https://ossrdbms-aad.database.chinacloudapi.cn") - env.OperationalInsights = OperationalInsightsAPI().withResourceIdentifier("https://api.loganalytics.azure.cn") - env.Postgresql = PostgresqlAPI("postgres.database.chinacloudapi.cn").withResourceIdentifier("https://ossrdbms-aad.database.chinacloudapi.cn") - env.ServiceBus = ServiceBusAPI("https://servicebus.chinacloudapi.cn", "servicebus.chinacloudapi.cn") - env.Sql = SqlAPI("database.chinacloudapi.cn").withResourceIdentifier("https://database.chinacloudapi.cn") - env.Storage = StorageAPI("core.chinacloudapi.cn").withResourceIdentifier("https://storage.azure.com") - env.Synapse = SynapseAPI("dev.azuresynapse.azure.cn") + env.KeyVault = KeyVaultAPI("vault.azure.cn").WithResourceIdentifier("https://vault.azure.cn") + env.ManagedHSM = ManagedHSMAPI("https://managedhsm.azure.cn", "managedhsm.azure.cn") + env.MariaDB = MariaDBAPI("mariadb.database.chinacloudapi.cn").WithResourceIdentifier("https://ossrdbms-aad.database.chinacloudapi.cn") + env.MySql = MySqlAPI("mysql.database.chinacloudapi.cn").WithResourceIdentifier("https://ossrdbms-aad.database.chinacloudapi.cn") + env.OperationalInsights = OperationalInsightsAPI().WithResourceIdentifier("https://api.loganalytics.azure.cn") + env.Postgresql = PostgresqlAPI("postgres.database.chinacloudapi.cn").WithResourceIdentifier("https://ossrdbms-aad.database.chinacloudapi.cn") + env.ServiceBus = ServiceBusAPI("https://servicebus.chinacloudapi.cn", "servicebus.chinacloudapi.cn").WithResourceIdentifier("https://servicebus.chinacloudapi.cn") + env.Sql = SqlAPI("database.chinacloudapi.cn").WithResourceIdentifier("https://database.chinacloudapi.cn") + env.Storage = StorageAPI("core.chinacloudapi.cn").WithResourceIdentifier("https://storage.azure.com") + env.Synapse = SynapseAPI("dev.azuresynapse.azure.cn").WithResourceIdentifier("https://dev.azuresynapse.azure.cn") env.TrafficManager = TrafficManagerAPI("trafficmanager.cn") - // @tombuildsstuff: DataLake doesn't appear to be available? - - // Managed HSM expected "H2 2023" per: - // https://azure.microsoft.com/en-gb/explore/global-infrastructure/products-by-region/?regions=china-non-regional,china-east,china-east-2,china-east-3,china-north,china-north-2,china-north-3&products=all - // presumably this'll be - // env.ManagedHSM = ManagedHSMAPI("https://managedhsm.azure.cn", "managedhsm.azure.cn") + // Services not currently available: Attestation, CDNFrontDoor, DataLake, IOTCentral return &env } diff --git a/vendor/github.com/hashicorp/go-azure-sdk/sdk/environments/azure_gov.go b/vendor/github.com/hashicorp/go-azure-sdk/sdk/environments/azure_gov.go index ef4d02c049..2331705e81 100644 --- a/vendor/github.com/hashicorp/go-azure-sdk/sdk/environments/azure_gov.go +++ b/vendor/github.com/hashicorp/go-azure-sdk/sdk/environments/azure_gov.go @@ -17,28 +17,27 @@ func AzureUSGovernment() *Environment { LoginEndpoint: "https://login.microsoftonline.us", Tenant: "common", } - env.ResourceManager = ResourceManagerAPI("https://management.usgovcloudapi.net").withResourceIdentifier("https://management.usgovcloudapi.net") - env.MicrosoftGraph = MicrosoftGraphAPI("https://graph.microsoft.us").withResourceIdentifier("https://graph.microsoft.us") + env.ResourceManager = ResourceManagerAPI("https://management.usgovcloudapi.net") + env.MicrosoftGraph = MicrosoftGraphAPI("https://graph.microsoft.us") env.ApiManagement = ApiManagementAPI("azure-api.us") env.AppConfiguration = AppConfigurationAPI("azconfig.azure.us") - env.Batch = BatchAPI("https://batch.core.usgovcloudapi.net").withResourceIdentifier("https://batch.core.usgovcloudapi.net") + env.Batch = BatchAPI("https://batch.core.usgovcloudapi.net") env.ContainerRegistry = ContainerRegistryAPI("azurecr.us") env.CosmosDB = CosmosDBAPI("documents.azure.us") - env.KeyVault = KeyVaultAPI("vault.usgovcloudapi.net").withResourceIdentifier("https://vault.usgovcloudapi.net") + env.KeyVault = KeyVaultAPI("vault.usgovcloudapi.net").WithResourceIdentifier("https://vault.usgovcloudapi.net") env.ManagedHSM = ManagedHSMAPI("https://managedhsm.usgovcloudapi.net", "managedhsm.usgovcloudapi.net") - env.MariaDB = MariaDBAPI("mariadb.database.usgovcloudapi.net").withResourceIdentifier("https://ossrdbms-aad.database.usgovcloudapi.net") - env.MySql = MySqlAPI("mysql.database.usgovcloudapi.net").withResourceIdentifier("https://ossrdbms-aad.database.usgovcloudapi.net") - env.OperationalInsights = OperationalInsightsAPI().withResourceIdentifier("https://api.loganalytics.us") - env.Postgresql = PostgresqlAPI("postgres.database.usgovcloudapi.net").withResourceIdentifier("https://ossrdbms-aad.database.usgovcloudapi.net") - env.ServiceBus = ServiceBusAPI("https://servicebus.usgovcloudapi.net", "servicebus.usgovcloudapi.net") - env.Sql = SqlAPI("database.usgovcloudapi.net").withResourceIdentifier("https://database.usgovcloudapi.net") + env.MariaDB = MariaDBAPI("mariadb.database.usgovcloudapi.net").WithResourceIdentifier("https://ossrdbms-aad.database.usgovcloudapi.net") + env.MySql = MySqlAPI("mysql.database.usgovcloudapi.net").WithResourceIdentifier("https://ossrdbms-aad.database.usgovcloudapi.net") + env.OperationalInsights = OperationalInsightsAPI().WithResourceIdentifier("https://api.loganalytics.us") + env.Postgresql = PostgresqlAPI("postgres.database.usgovcloudapi.net").WithResourceIdentifier("https://ossrdbms-aad.database.usgovcloudapi.net") + env.ServiceBus = ServiceBusAPI("https://servicebus.usgovcloudapi.net", "servicebus.usgovcloudapi.net").WithResourceIdentifier("https://servicebus.usgovcloudapi.net") + env.Sql = SqlAPI("database.usgovcloudapi.net").WithResourceIdentifier("https://database.usgovcloudapi.net") env.Storage = StorageAPI("core.usgovcloudapi.net") - env.Synapse = SynapseAPI("dev.azuresynapse.usgovcloudapi.net").withResourceIdentifier("https://dev.azuresynapse.usgovcloudapi.net") + env.Synapse = SynapseAPI("dev.azuresynapse.usgovcloudapi.net").WithResourceIdentifier("https://dev.azuresynapse.usgovcloudapi.net") env.TrafficManager = TrafficManagerAPI("usgovtrafficmanager.net") - // CDNFrontDoor doesn't appear to be available - // DataLake doesn't appear to be available + // Services not currently available: Attestation, CDNFrontDoor, DataLake, IOTCentral return &env } diff --git a/vendor/github.com/hashicorp/go-azure-sdk/sdk/environments/azure_public.go b/vendor/github.com/hashicorp/go-azure-sdk/sdk/environments/azure_public.go index 23dafb3b9f..737fbdb268 100644 --- a/vendor/github.com/hashicorp/go-azure-sdk/sdk/environments/azure_public.go +++ b/vendor/github.com/hashicorp/go-azure-sdk/sdk/environments/azure_public.go @@ -22,23 +22,23 @@ func AzurePublic() *Environment { env.ApiManagement = ApiManagementAPI("azure-api.net") env.AppConfiguration = AppConfigurationAPI("azconfig.io") - env.Attestation = AttestationAPI("https://attest.azure.net") + env.Attestation = AttestationAPI("https://attest.azure.net", "attest.azure.net") env.Batch = BatchAPI("https://batch.core.windows.net") env.CDNFrontDoor = CDNFrontDoorAPI("azurefd.net") env.ContainerRegistry = ContainerRegistryAPI("azurecr.io") - env.CosmosDB = CosmosDBAPI("documents.azure.com") - env.DataLake = DataLakeAPI("azuredatalakestore.net") - env.IoTCentral = IoTCentral("azureiotcentral.com") - env.KeyVault = KeyVaultAPI("vault.azure.net") + env.CosmosDB = CosmosDBAPI("documents.azure.com").WithResourceIdentifier("https://cosmos.azure.com") + env.DataLake = DataLakeAPI("azuredatalakestore.net").WithResourceIdentifier("https://datalake.azure.net") + env.IoTCentral = IoTCentral("azureiotcentral.com").WithResourceIdentifier("https://apps.azureiotcentral.com") + env.KeyVault = KeyVaultAPI("vault.azure.net").WithResourceIdentifier("https://vault.azure.net") env.ManagedHSM = ManagedHSMAPI("https://managedhsm.azure.net", "managedhsm.azure.net") - env.MariaDB = MariaDBAPI("mariadb.database.azure.com") - env.MySql = MySqlAPI("mysql.database.azure.com") - env.OperationalInsights = OperationalInsightsAPI() - env.Postgresql = PostgresqlAPI("postgres.database.azure.com") - env.ServiceBus = ServiceBusAPI("https://servicebus.windows.net", "servicebus.windows.net") - env.Sql = SqlAPI("database.windows.net") + env.MariaDB = MariaDBAPI("mariadb.database.azure.com").WithResourceIdentifier("https://ossrdbms-aad.database.windows.net") + env.MySql = MySqlAPI("mysql.database.azure.com").WithResourceIdentifier("https://ossrdbms-aad.database.windows.net") + env.OperationalInsights = OperationalInsightsAPI().WithResourceIdentifier("https://api.loganalytics.io") + env.Postgresql = PostgresqlAPI("postgres.database.azure.com").WithResourceIdentifier("https://ossrdbms-aad.database.windows.net") + env.ServiceBus = ServiceBusAPI("https://servicebus.windows.net", "servicebus.windows.net").WithResourceIdentifier("https://servicebus.azure.net") + env.Sql = SqlAPI("database.windows.net").WithResourceIdentifier("https://database.windows.net") env.Storage = StorageAPI("core.windows.net") - env.Synapse = SynapseAPI("dev.azuresynapse.net") + env.Synapse = SynapseAPI("dev.azuresynapse.net").WithResourceIdentifier("https://dev.azuresynapse.net") env.TrafficManager = TrafficManagerAPI("trafficmanager.net") return &env diff --git a/vendor/github.com/hashicorp/go-azure-sdk/sdk/environments/azure_public_canary.go b/vendor/github.com/hashicorp/go-azure-sdk/sdk/environments/azure_public_canary.go index 475a656384..7cd5cc7d94 100644 --- a/vendor/github.com/hashicorp/go-azure-sdk/sdk/environments/azure_public_canary.go +++ b/vendor/github.com/hashicorp/go-azure-sdk/sdk/environments/azure_public_canary.go @@ -7,6 +7,6 @@ func AzurePublicCanary() *Environment { // Canary is Azure Public with a different Microsoft Graph endpoint env := AzurePublic() env.Name = "Canary" - env.MicrosoftGraph = MicrosoftGraphAPI("https://canary.graph.microsoft.com").withResourceIdentifier("https://canary.graph.microsoft.com") + env.MicrosoftGraph = MicrosoftGraphAPI("https://canary.graph.microsoft.com").WithResourceIdentifier("https://canary.graph.microsoft.com") return env } diff --git a/vendor/github.com/hashicorp/go-azure-sdk/sdk/environments/endpoint_refresh.go b/vendor/github.com/hashicorp/go-azure-sdk/sdk/environments/endpoint_refresh.go index a0a7fc9ac0..d4f2314c0f 100644 --- a/vendor/github.com/hashicorp/go-azure-sdk/sdk/environments/endpoint_refresh.go +++ b/vendor/github.com/hashicorp/go-azure-sdk/sdk/environments/endpoint_refresh.go @@ -17,7 +17,7 @@ func (e *Environment) RefreshMetaDataFromEndpoint(ctx context.Context) error { } client := metadata.NewClientWithEndpoint(*endpoint) - config, err := client.GetMetaData(ctx, e.Name) + config, err := client.GetMetaData(ctx) if err != nil { return fmt.Errorf("retrieving MetaData from endpoint: %+v", err) } @@ -30,7 +30,14 @@ func (e *Environment) RefreshMetaDataFromEndpoint(ctx context.Context) error { } func (e *Environment) updateFromMetaData(config *metadata.MetaData) error { - // Auth Endpoints + // The following supported services are missing from metadata and cannot be configured: + // - API Management (domain suffix is missing) + // - App Configuration (domain suffix and resource identifier are missing) + // - CosmosDB (domain suffix is missing) + // - IOT Central (domain suffix and resource identifier are missing) + // - Service Bus (domain suffix and resource identifier are missing) + // - Traffic Manager (domain suffix is missing) + if e.Authorization == nil { e.Authorization = &Authorization{} } @@ -46,34 +53,52 @@ func (e *Environment) updateFromMetaData(config *metadata.MetaData) error { if config.Authentication.Tenant != "" { e.Authorization.Tenant = config.Authentication.Tenant } - if config.ResourceManagerEndpoint != "" { - e.ResourceManager = ResourceManagerAPI(config.ResourceManagerEndpoint) + + if config.DnsSuffixes.Attestation != "" && config.ResourceIdentifiers.Attestation != "" { + e.Attestation = AttestationAPI(config.ResourceIdentifiers.Attestation, config.DnsSuffixes.Attestation) } - if config.ResourceIdentifiers.MicrosoftGraph != "" { - e.MicrosoftGraph = MicrosoftGraphAPI(config.ResourceIdentifiers.MicrosoftGraph) + if config.ResourceIdentifiers.Batch != "" { + e.Batch = BatchAPI(config.ResourceIdentifiers.Batch) } - - // Dns Suffixes if config.DnsSuffixes.FrontDoor != "" { e.CDNFrontDoor = CDNFrontDoorAPI(config.DnsSuffixes.FrontDoor) } + if config.DnsSuffixes.ContainerRegistry != "" { + e.ContainerRegistry = ContainerRegistryAPI(config.DnsSuffixes.ContainerRegistry) + } + if config.DnsSuffixes.DataLakeStore != "" && config.ResourceIdentifiers.DataLake != "" { + e.DataLake = DataLakeAPI(config.DnsSuffixes.DataLakeStore).WithResourceIdentifier(config.ResourceIdentifiers.DataLake) + } if config.DnsSuffixes.KeyVault != "" { - e.KeyVault = KeyVaultAPI(config.DnsSuffixes.KeyVault) + // Key Vault resource ID is missing in metadata, so make a best-effort guess from the domain suffix + e.KeyVault = KeyVaultAPI(config.DnsSuffixes.KeyVault).WithResourceIdentifier(fmt.Sprintf("https://%s", config.DnsSuffixes.KeyVault)) } if config.DnsSuffixes.ManagedHSM != "" { - e.ManagedHSM = ManagedHSMAPI(fmt.Sprintf("https://%s", config.DnsSuffixes.ManagedHSM), config.DnsSuffixes.ManagedHSM) + // Managed HSM resource ID is missing in metadata, so make a best-effort guess from the domain suffix + mHsmEndpoint := fmt.Sprintf("https://%s", config.DnsSuffixes.ManagedHSM) + e.ManagedHSM = ManagedHSMAPI(mHsmEndpoint, config.DnsSuffixes.ManagedHSM).WithResourceIdentifier(mHsmEndpoint) + } + if config.DnsSuffixes.MariaDB != "" && config.ResourceIdentifiers.OSSRDBMS != "" { + e.MariaDB = MariaDBAPI(config.DnsSuffixes.MariaDB).WithResourceIdentifier(config.ResourceIdentifiers.OSSRDBMS) + } + if config.ResourceIdentifiers.MicrosoftGraph != "" { + e.MicrosoftGraph = MicrosoftGraphAPI(config.ResourceIdentifiers.MicrosoftGraph) + } + if config.DnsSuffixes.MySql != "" && config.ResourceIdentifiers.OSSRDBMS != "" { + e.MySql = MySqlAPI(config.DnsSuffixes.MySql).WithResourceIdentifier(config.ResourceIdentifiers.OSSRDBMS) } - if config.DnsSuffixes.MariaDB != "" { - e.MariaDB = MariaDBAPI(config.DnsSuffixes.MariaDB) + if config.ResourceIdentifiers.LogAnalytics != "" { + e.OperationalInsights = OperationalInsightsAPI().WithResourceIdentifier(config.ResourceIdentifiers.LogAnalytics) } - if config.DnsSuffixes.MySql != "" { - e.MySql = MySqlAPI(config.DnsSuffixes.MySql) + if config.DnsSuffixes.Postgresql != "" && config.ResourceIdentifiers.OSSRDBMS != "" { + e.Postgresql = PostgresqlAPI(config.DnsSuffixes.Postgresql).WithResourceIdentifier(config.ResourceIdentifiers.OSSRDBMS) } - if config.DnsSuffixes.Postgresql != "" { - e.Postgresql = PostgresqlAPI(config.DnsSuffixes.Postgresql) + if config.ResourceManagerEndpoint != "" { + e.ResourceManager = ResourceManagerAPI(config.ResourceManagerEndpoint) } if config.DnsSuffixes.SqlServer != "" { - e.Sql = SqlAPI(config.DnsSuffixes.SqlServer) + // SQL resource ID is missing in metadata, so make a best-effort guess from the domain suffix + e.Sql = SqlAPI(config.DnsSuffixes.SqlServer).WithResourceIdentifier(fmt.Sprintf("https://%s", config.DnsSuffixes.SqlServer)) } if config.DnsSuffixes.Storage != "" { e.Storage = StorageAPI(config.DnsSuffixes.Storage) @@ -81,8 +106,8 @@ func (e *Environment) updateFromMetaData(config *metadata.MetaData) error { if config.DnsSuffixes.StorageSync != "" { e.StorageSync = StorageSyncAPI(config.DnsSuffixes.StorageSync) } - if config.DnsSuffixes.Synapse != "" { - e.Synapse = SynapseAPI(config.DnsSuffixes.Synapse) + if config.DnsSuffixes.Synapse != "" && config.ResourceIdentifiers.Synapse != "" { + e.Synapse = SynapseAPI(config.DnsSuffixes.Synapse).WithResourceIdentifier(config.ResourceIdentifiers.Synapse) } return nil diff --git a/vendor/github.com/hashicorp/go-azure-sdk/sdk/environments/environment.go b/vendor/github.com/hashicorp/go-azure-sdk/sdk/environments/environment.go index 3c33b9b4c1..95ee694aa7 100644 --- a/vendor/github.com/hashicorp/go-azure-sdk/sdk/environments/environment.go +++ b/vendor/github.com/hashicorp/go-azure-sdk/sdk/environments/environment.go @@ -160,9 +160,10 @@ func NewApiEndpoint(name, endpoint string, appId *string) *ApiEndpoint { } } -func (e *ApiEndpoint) withResourceIdentifier(identifier string) *ApiEndpoint { - e.resourceIdentifier = pointer.To(identifier) - return e +func (e *ApiEndpoint) WithResourceIdentifier(identifier string) Api { + newApi := *e + newApi.resourceIdentifier = pointer.To(identifier) + return &newApi } func (e *ApiEndpoint) Available() bool { diff --git a/vendor/github.com/hashicorp/go-azure-sdk/sdk/environments/from_endpoint.go b/vendor/github.com/hashicorp/go-azure-sdk/sdk/environments/from_endpoint.go index 1d0debe5dd..e6efd39b87 100644 --- a/vendor/github.com/hashicorp/go-azure-sdk/sdk/environments/from_endpoint.go +++ b/vendor/github.com/hashicorp/go-azure-sdk/sdk/environments/from_endpoint.go @@ -11,11 +11,11 @@ import ( ) // FromEndpoint attempts to load an environment from the given Endpoint. -func FromEndpoint(ctx context.Context, endpoint, name string) (*Environment, error) { +func FromEndpoint(ctx context.Context, endpoint string) (*Environment, error) { env := baseEnvironmentWithName("FromEnvironment") client := metadata.NewClientWithEndpoint(endpoint) - config, err := client.GetMetaData(ctx, name) + config, err := client.GetMetaData(ctx) if err != nil { return nil, fmt.Errorf("retrieving metadata from endpoint %q: %+v", endpoint, err) } @@ -35,7 +35,7 @@ func FromEndpoint(ctx context.Context, endpoint, name string) (*Environment, err } env.MicrosoftGraph = MicrosoftGraphAPI(config.ResourceIdentifiers.MicrosoftGraph) - if err := env.updateFromMetaData(config); err != nil { + if err = env.updateFromMetaData(config); err != nil { return nil, fmt.Errorf("updating Environment from MetaData: %+v", err) } diff --git a/vendor/github.com/hashicorp/go-azure-sdk/sdk/environments/helpers.go b/vendor/github.com/hashicorp/go-azure-sdk/sdk/environments/helpers.go index 81cf19d57b..64ed4bd111 100644 --- a/vendor/github.com/hashicorp/go-azure-sdk/sdk/environments/helpers.go +++ b/vendor/github.com/hashicorp/go-azure-sdk/sdk/environments/helpers.go @@ -5,7 +5,7 @@ package environments import "github.com/hashicorp/go-azure-helpers/lang/pointer" -func applicationIdOnly(name, applicationId string) Api { +func applicationIdOnly(name, applicationId string) *ApiEndpoint { return &ApiEndpoint{ domainSuffix: nil, endpoint: nil, @@ -15,7 +15,7 @@ func applicationIdOnly(name, applicationId string) Api { } } -func ApiManagementAPI(domainSuffix string) Api { +func ApiManagementAPI(domainSuffix string) *ApiEndpoint { return &ApiEndpoint{ domainSuffix: pointer.To(domainSuffix), endpoint: nil, @@ -25,7 +25,7 @@ func ApiManagementAPI(domainSuffix string) Api { } } -func AppConfigurationAPI(domainSuffix string) Api { +func AppConfigurationAPI(domainSuffix string) *ApiEndpoint { return &ApiEndpoint{ domainSuffix: pointer.To(domainSuffix), endpoint: nil, @@ -35,27 +35,29 @@ func AppConfigurationAPI(domainSuffix string) Api { } } -func AttestationAPI(endpoint string) Api { +func AttestationAPI(endpoint, domainSuffix string) *ApiEndpoint { + // endpoint and resource ID are the same, only the resource ID is returned in metadata return &ApiEndpoint{ - domainSuffix: nil, + domainSuffix: pointer.To(domainSuffix), endpoint: pointer.To(endpoint), appId: pointer.To(attestationServiceAppId), name: "AttestationService", - resourceIdentifier: nil, + resourceIdentifier: pointer.To(endpoint), } } -func BatchAPI(endpoint string) *ApiEndpoint { +func BatchAPI(resourceId string) *ApiEndpoint { + // endpoint and resource ID are the same, only the resource ID is returned in metadata return &ApiEndpoint{ domainSuffix: nil, - endpoint: pointer.To(endpoint), + endpoint: pointer.To(resourceId), appId: pointer.To(batchAppId), name: "Batch", - resourceIdentifier: pointer.To(endpoint), + resourceIdentifier: pointer.To(resourceId), } } -func CDNFrontDoorAPI(domainSuffix string) Api { +func CDNFrontDoorAPI(domainSuffix string) *ApiEndpoint { return &ApiEndpoint{ domainSuffix: pointer.To(domainSuffix), endpoint: nil, @@ -65,7 +67,7 @@ func CDNFrontDoorAPI(domainSuffix string) Api { } } -func ContainerRegistryAPI(domainSuffix string) Api { +func ContainerRegistryAPI(domainSuffix string) *ApiEndpoint { return &ApiEndpoint{ domainSuffix: pointer.To(domainSuffix), endpoint: nil, @@ -75,33 +77,33 @@ func ContainerRegistryAPI(domainSuffix string) Api { } } -func CosmosDBAPI(domainSuffix string) Api { +func CosmosDBAPI(domainSuffix string) *ApiEndpoint { return &ApiEndpoint{ domainSuffix: pointer.To(domainSuffix), endpoint: nil, appId: pointer.To(cosmosDBAppId), name: "AzureCosmosDb", - resourceIdentifier: pointer.To("https://cosmos.azure.com"), + resourceIdentifier: nil, } } -func DataLakeAPI(domainSuffix string) Api { +func DataLakeAPI(domainSuffix string) *ApiEndpoint { return &ApiEndpoint{ domainSuffix: pointer.To(domainSuffix), endpoint: nil, appId: pointer.To(dataLakeAppId), name: "DataLake", - resourceIdentifier: pointer.To("https://datalake.azure.net"), + resourceIdentifier: nil, } } -func IoTCentral(domainSuffix string) Api { +func IoTCentral(domainSuffix string) *ApiEndpoint { return &ApiEndpoint{ domainSuffix: pointer.To(domainSuffix), endpoint: nil, appId: pointer.To(iotCentralAppId), name: "IoTCentral", - resourceIdentifier: pointer.To("https://apps.azureiotcentral.com"), + resourceIdentifier: nil, } } @@ -111,11 +113,12 @@ func KeyVaultAPI(domainSuffix string) *ApiEndpoint { endpoint: nil, appId: pointer.To(keyVaultAppId), name: "AzureKeyVault", - resourceIdentifier: pointer.To("https://vault.azure.net"), + resourceIdentifier: nil, } } -func ManagedHSMAPI(endpoint, domainSuffix string) Api { +func ManagedHSMAPI(endpoint, domainSuffix string) *ApiEndpoint { + // endpoint and resource ID are the same, only the domainSuffix is returned in metadata return &ApiEndpoint{ domainSuffix: pointer.To(domainSuffix), endpoint: pointer.To(endpoint), @@ -131,17 +134,17 @@ func MariaDBAPI(domainSuffix string) *ApiEndpoint { endpoint: nil, appId: pointer.To(ossRDBMSAppId), name: "OssRdbms", - resourceIdentifier: pointer.To("https://ossrdbms-aad.database.windows.net"), + resourceIdentifier: nil, } } -func MicrosoftGraphAPI(endpoint string) *ApiEndpoint { +func MicrosoftGraphAPI(resourceId string) *ApiEndpoint { + // endpoint and resource ID are the same, only the resource ID is returned in metadata return &ApiEndpoint{ - domainSuffix: nil, - endpoint: pointer.To(endpoint), + endpoint: pointer.To(resourceId), appId: pointer.To(microsoftGraphAppId), name: "MicrosoftGraph", - resourceIdentifier: pointer.To(endpoint), + resourceIdentifier: pointer.To(resourceId), } } @@ -151,7 +154,7 @@ func MySqlAPI(domainSuffix string) *ApiEndpoint { endpoint: nil, appId: pointer.To(ossRDBMSAppId), name: "OssRdbms", - resourceIdentifier: pointer.To("https://ossrdbms-aad.database.windows.net"), + resourceIdentifier: nil, } } @@ -161,7 +164,7 @@ func OperationalInsightsAPI() *ApiEndpoint { endpoint: nil, appId: pointer.To(logAnalyticsAppId), name: "OperationalInsights", - resourceIdentifier: pointer.To("https://api.loganalytics.io"), + resourceIdentifier: nil, } } @@ -171,11 +174,12 @@ func PostgresqlAPI(domainSuffix string) *ApiEndpoint { endpoint: nil, appId: pointer.To(ossRDBMSAppId), name: "OssRdbms", - resourceIdentifier: pointer.To("https://ossrdbms-aad.database.windows.net"), + resourceIdentifier: nil, } } func ResourceManagerAPI(endpoint string) *ApiEndpoint { + // endpoint and resource ID are the same, only the endpoint is returned in metadata return &ApiEndpoint{ domainSuffix: nil, endpoint: pointer.To(endpoint), @@ -191,7 +195,7 @@ func ServiceBusAPI(endpoint, domainSuffix string) Api { endpoint: pointer.To(endpoint), appId: pointer.To(serviceBusAppId), name: "ServiceBus", - resourceIdentifier: pointer.To(endpoint), + resourceIdentifier: nil, } } @@ -201,11 +205,14 @@ func SqlAPI(domainSuffix string) *ApiEndpoint { endpoint: nil, appId: pointer.To(sqlDatabaseAppId), name: "AzureSqlDatabase", - resourceIdentifier: pointer.To("https://database.windows.net"), + resourceIdentifier: nil, } } func StorageAPI(domainSuffix string) *ApiEndpoint { + // The default resource identifier for Azure Storage is the same for all public and sovereign clouds. This can be + // changed to scope the token for authorizing against a single storage account. + // https://learn.microsoft.com/en-us/azure/storage/blobs/authorize-access-azure-active-directory#microsoft-authentication-library-msal return &ApiEndpoint{ domainSuffix: pointer.To(domainSuffix), endpoint: nil, @@ -231,7 +238,7 @@ func SynapseAPI(domainSuffix string) *ApiEndpoint { endpoint: nil, appId: pointer.To(synapseAppId), name: "Synapse", - resourceIdentifier: pointer.To("https://dev.azuresynapse.net"), + resourceIdentifier: nil, } } diff --git a/vendor/github.com/hashicorp/go-azure-sdk/sdk/environments/interfaces.go b/vendor/github.com/hashicorp/go-azure-sdk/sdk/environments/interfaces.go index 58e5e50bb4..599759eef9 100644 --- a/vendor/github.com/hashicorp/go-azure-sdk/sdk/environments/interfaces.go +++ b/vendor/github.com/hashicorp/go-azure-sdk/sdk/environments/interfaces.go @@ -4,10 +4,25 @@ package environments type Api interface { + // AppId is a GUID that identifies the application/API in the cloud environment AppId() (*string, bool) + + // Available returns whether the application/API is supported in the cloud environment Available() bool + + // DomainSuffix is the specific domain suffix for constructing endpoints for a data plane API in the cloud environment DomainSuffix() (*string, bool) + + // Endpoint is the common endpoint for the application/API in the cloud environment Endpoint() (*string, bool) + + // Name returns the name of the application/API Name() string + + // ResourceIdentifier is a URI that identifies the application/API in the cloud environment and + // is used for constructing scopes/roles when authorizing connections. ResourceIdentifier() (*string, bool) + + // WithResourceIdentifier overrides the default resource ID for the API and is useful for APIs that offer multiple authorization scopes + WithResourceIdentifier(string) Api } diff --git a/vendor/github.com/hashicorp/go-azure-sdk/sdk/internal/azurecli/azcli.go b/vendor/github.com/hashicorp/go-azure-sdk/sdk/internal/azurecli/azcli.go index caaffd8f48..bb225d1818 100644 --- a/vendor/github.com/hashicorp/go-azure-sdk/sdk/internal/azurecli/azcli.go +++ b/vendor/github.com/hashicorp/go-azure-sdk/sdk/internal/azurecli/azcli.go @@ -15,6 +15,33 @@ import ( "github.com/hashicorp/go-version" ) +type azAccount struct { + EnvironmentName *string `json:"environmentName"` + HomeTenantId *string `json:"homeTenantId"` + Id *string `json:"id"` + Default *bool `json:"isDefault"` + Name *string `json:"name"` + State *string `json:"state"` + TenantId *string `json:"tenantId"` + + ManagedByTenants *[]struct { + TenantId *string `json:"tenantId"` + } `json:"managedByTenants"` + + User *struct { + AssignedIdentityInfo *string `json:"assignedIdentityInfo"` + Name *string `json:"name"` + Type *string `json:"type"` + } +} + +type azVersion struct { + AzureCli *string `json:"azure-cli,omitempty"` + AzureCliCore *string `json:"azure-cli-core,omitempty"` + AzureCliTelemetry *string `json:"azure-cli-telemetry,omitempty"` + Extensions *interface{} `json:"extensions,omitempty"` +} + // CheckAzVersion tries to determine the version of Azure CLI in the path and checks for a compatible version func CheckAzVersion() error { currentVersion, err := getAzVersion() @@ -60,39 +87,60 @@ func ValidateTenantID(tenantId string) (bool, error) { // GetDefaultTenantID tries to determine the default tenant func GetDefaultTenantID() (*string, error) { - var account struct { - TenantID string `json:"tenantId"` - } - if err := JSONUnmarshalAzCmd(true, &account, "account", "show"); err != nil { + account, err := getAzAccount() + if err != nil { return nil, fmt.Errorf("obtaining tenant ID: %s", err) } - - return &account.TenantID, nil + return account.TenantId, nil } // GetDefaultSubscriptionID tries to determine the default subscription func GetDefaultSubscriptionID() (*string, error) { - var account struct { - SubscriptionID string `json:"id"` - } - err := JSONUnmarshalAzCmd(true, &account, "account", "show") + account, err := getAzAccount() if err != nil { return nil, fmt.Errorf("obtaining subscription ID: %s", err) } + return account.Id, nil +} + +// GetAccountName returns the name of the authenticated principal +func GetAccountName() (*string, error) { + account, err := getAzAccount() + if err != nil { + return nil, fmt.Errorf("obtaining account name: %s", err) + } + if account.User == nil { + return nil, fmt.Errorf("account details were nil: %s", err) + } + return account.User.Name, nil +} - return &account.SubscriptionID, nil +// GetAccountType returns the account type of the authenticated principal +func GetAccountType() (*string, error) { + account, err := getAzAccount() + if err != nil { + return nil, fmt.Errorf("obtaining account type: %s", err) + } + if account.User == nil { + return nil, fmt.Errorf("account details were nil: %s", err) + } + return account.User.Type, nil +} + +// getAzAccount returns the output of `az account show` +func getAzAccount() (*azAccount, error) { + var account azAccount + if err := JSONUnmarshalAzCmd(true, &account, "account", "show"); err != nil { + return nil, fmt.Errorf("obtaining account details: %s", err) + } + return &account, nil } // getAzVersion tries to determine the version of Azure CLI in the path. func getAzVersion() (*string, error) { - var cliVersion *struct { - AzureCli *string `json:"azure-cli,omitempty"` - AzureCliCore *string `json:"azure-cli-core,omitempty"` - AzureCliTelemetry *string `json:"azure-cli-telemetry,omitempty"` - Extensions *interface{} `json:"extensions,omitempty"` - } - err := JSONUnmarshalAzCmd(true, &cliVersion, "version") - if err != nil { + var cliVersion azVersion + + if err := JSONUnmarshalAzCmd(true, &cliVersion, "version"); err != nil { return nil, fmt.Errorf("could not parse Azure CLI version: %v", err) } diff --git a/vendor/github.com/hashicorp/go-azure-sdk/sdk/internal/metadata/client.go b/vendor/github.com/hashicorp/go-azure-sdk/sdk/internal/metadata/client.go index 3c80fa11da..c9bc16f722 100644 --- a/vendor/github.com/hashicorp/go-azure-sdk/sdk/internal/metadata/client.go +++ b/vendor/github.com/hashicorp/go-azure-sdk/sdk/internal/metadata/client.go @@ -30,55 +30,9 @@ func NewClientWithEndpoint(endpoint string) *Client { } // GetMetaData connects to the ARM metadata service at the configured endpoint, to retrieve information about the -// current environment. Sometimes an endpoint will not support the latest schema, in such cases it will not be -// possible to configure all services but a best effort will be made to request and parse an earlier schema version. -// `name` is used when falling back to an earlier schema version where multiple environments are returned and the -// desired one must be matched by name. -func (c *Client) GetMetaData(ctx context.Context, name string) (*MetaData, error) { - metadata, err := c.getMetaDataFrom2022API(ctx, name) - if err != nil { - log.Printf("[DEBUG] Falling back to ARM Metadata version 2019-05-01 for %s", c.endpoint) - metadata, err = c.getMetaDataFrom2019API(ctx, name) - if err != nil { - return nil, fmt.Errorf("retrieving metadata from the 2022-09-01 and 2019-05-01 APIs: %+v", err) - } - } - - return &MetaData{ - Authentication: Authentication{ - Audiences: metadata.Authentication.Audiences, - LoginEndpoint: metadata.Authentication.LoginEndpoint, - IdentityProvider: metadata.Authentication.IdentityProvider, - Tenant: metadata.Authentication.Tenant, - }, - DnsSuffixes: DnsSuffixes{ - Attestation: metadata.Suffixes.AttestationEndpoint, - FrontDoor: metadata.Suffixes.AzureFrontDoorEndpointSuffix, - KeyVault: metadata.Suffixes.KeyVaultDns, - ManagedHSM: metadata.Suffixes.MhsmDns, - MariaDB: metadata.Suffixes.MariadbServerEndpoint, - MySql: metadata.Suffixes.MysqlServerEndpoint, - Postgresql: metadata.Suffixes.PostgresqlServerEndpoint, - SqlServer: metadata.Suffixes.SqlServerHostname, - Storage: metadata.Suffixes.Storage, - StorageSync: metadata.Suffixes.StorageSyncEndpointSuffix, - Synapse: metadata.Suffixes.SynapseAnalytics, - }, - Name: metadata.Name, - ResourceIdentifiers: ResourceIdentifiers{ - Attestation: normalizeResourceId(metadata.AttestationResourceId), - Batch: normalizeResourceId(metadata.Batch), - LogAnalytics: normalizeResourceId(metadata.LogAnalyticsResourceId), - Media: normalizeResourceId(metadata.Media), - MicrosoftGraph: normalizeResourceId(metadata.MicrosoftGraphResourceId), - OSSRDBMS: normalizeResourceId(metadata.OssrDbmsResourceId), - Synapse: normalizeResourceId(metadata.SynapseAnalyticsResourceId), - }, - ResourceManagerEndpoint: metadata.ResourceManager, - }, nil -} - -func (c *Client) getMetaDataFrom2022API(ctx context.Context, name string) (*metaDataResponse, error) { +// current environment. We currently only support the 2019-05-01 metadata schema, since earlier versions do not +// reference some mandatory services, notably Microsoft Graph. +func (c *Client) GetMetaData(ctx context.Context) (*MetaData, error) { tlsConfig := tls.Config{ MinVersion: tls.VersionTLS12, } @@ -122,78 +76,47 @@ func (c *Client) getMetaDataFrom2022API(ctx context.Context, name string) (*meta // Trim away a BOM if present respBody = bytes.TrimPrefix(respBody, []byte("\xef\xbb\xbf")) - var model *metaDataResponse - if err := json.Unmarshal(respBody, &model); err != nil { + var metadata *metaDataResponse + if err := json.Unmarshal(respBody, &metadata); err != nil { log.Printf("[DEBUG] Unrecognised metadata response for %s: %s", uri, respBody) return nil, fmt.Errorf("unmarshaling response: %+v", err) } - return model, nil -} - -func (c *Client) getMetaDataFrom2019API(ctx context.Context, name string) (*metaDataResponse, error) { - tlsConfig := tls.Config{ - MinVersion: tls.VersionTLS12, - } - client := &http.Client{ - Transport: &http.Transport{ - Proxy: http.ProxyFromEnvironment, - DialContext: func(ctx context.Context, network, addr string) (net.Conn, error) { - d := &net.Dialer{Resolver: &net.Resolver{}} - return d.DialContext(ctx, network, addr) - }, - TLSClientConfig: &tlsConfig, - MaxIdleConns: 100, - IdleConnTimeout: 90 * time.Second, - TLSHandshakeTimeout: 10 * time.Second, - ExpectContinueTimeout: 1 * time.Second, - ForceAttemptHTTP2: true, - MaxIdleConnsPerHost: runtime.GOMAXPROCS(0) + 1, + return &MetaData{ + Authentication: Authentication{ + Audiences: metadata.Authentication.Audiences, + LoginEndpoint: metadata.Authentication.LoginEndpoint, + IdentityProvider: metadata.Authentication.IdentityProvider, + Tenant: metadata.Authentication.Tenant, }, - } - uri := fmt.Sprintf("%s/metadata/endpoints?api-version=2019-05-01", c.endpoint) - req, err := http.NewRequestWithContext(ctx, http.MethodGet, uri, nil) - if err != nil { - return nil, fmt.Errorf("preparing request: %+v", err) - } - - resp, err := client.Do(req) - if err != nil { - return nil, fmt.Errorf("performing request: %+v", err) - } - - if resp.StatusCode != http.StatusOK { - return nil, fmt.Errorf("performing request: expected 200 OK but got %d %s", resp.StatusCode, resp.Status) - } - - respBody, err := io.ReadAll(resp.Body) - if err != nil { - return nil, fmt.Errorf("parsing response body: %+v", err) - } - resp.Body.Close() - - // Trim away a BOM if present - respBody = bytes.TrimPrefix(respBody, []byte("\xef\xbb\xbf")) - - var model *[]metaDataResponse - if err := json.Unmarshal(respBody, &model); err != nil { - log.Printf("[DEBUG] Unrecognised metadata response for %s: %s", uri, respBody) - return nil, fmt.Errorf("unmarshaling response: %+v", err) - } - - if model == nil { - return nil, fmt.Errorf("unmarshaling response: no environments returned") - } - - // This version returns an array of environments, we are only interested in one - var env metaDataResponse - for _, e := range *model { - if name == "" || e.Name == name { - env = e - break - } - } - return &env, nil + DnsSuffixes: DnsSuffixes{ + Attestation: metadata.Suffixes.AttestationEndpoint, + ContainerRegistry: metadata.Suffixes.AcrLoginServer, + DataLakeStore: metadata.Suffixes.AzureDataLakeStoreFileSystem, + FrontDoor: metadata.Suffixes.AzureFrontDoorEndpointSuffix, + KeyVault: metadata.Suffixes.KeyVaultDns, + ManagedHSM: metadata.Suffixes.MhsmDns, + MariaDB: metadata.Suffixes.MariadbServerEndpoint, + MySql: metadata.Suffixes.MysqlServerEndpoint, + Postgresql: metadata.Suffixes.PostgresqlServerEndpoint, + SqlServer: metadata.Suffixes.SqlServerHostname, + Storage: metadata.Suffixes.Storage, + StorageSync: metadata.Suffixes.StorageSyncEndpointSuffix, + Synapse: metadata.Suffixes.SynapseAnalytics, + }, + Name: metadata.Name, + ResourceIdentifiers: ResourceIdentifiers{ + Attestation: normalizeResourceId(metadata.AttestationResourceId), + Batch: normalizeResourceId(metadata.Batch), + DataLake: normalizeResourceId(metadata.ActiveDirectoryDataLake), + LogAnalytics: normalizeResourceId(metadata.LogAnalyticsResourceId), + Media: normalizeResourceId(metadata.Media), + MicrosoftGraph: normalizeResourceId(metadata.MicrosoftGraphResourceId), + OSSRDBMS: normalizeResourceId(metadata.OssrDbmsResourceId), + Synapse: normalizeResourceId(metadata.SynapseAnalyticsResourceId), + }, + ResourceManagerEndpoint: metadata.ResourceManager, + }, nil } type metaDataResponse struct { diff --git a/vendor/github.com/hashicorp/go-azure-sdk/sdk/internal/metadata/models.go b/vendor/github.com/hashicorp/go-azure-sdk/sdk/internal/metadata/models.go index ebad1ceb90..b6120a759f 100644 --- a/vendor/github.com/hashicorp/go-azure-sdk/sdk/internal/metadata/models.go +++ b/vendor/github.com/hashicorp/go-azure-sdk/sdk/internal/metadata/models.go @@ -19,22 +19,25 @@ type Authentication struct { } type DnsSuffixes struct { - Attestation string - FrontDoor string - KeyVault string - ManagedHSM string - MariaDB string - MySql string - Postgresql string - SqlServer string - Storage string - StorageSync string - Synapse string + Attestation string + ContainerRegistry string + DataLakeStore string + FrontDoor string + KeyVault string + ManagedHSM string + MariaDB string + MySql string + Postgresql string + SqlServer string + Storage string + StorageSync string + Synapse string } type ResourceIdentifiers struct { Attestation string Batch string + DataLake string LogAnalytics string Media string MicrosoftGraph string diff --git a/vendor/modules.txt b/vendor/modules.txt index 33a4516731..4799664e88 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -60,11 +60,11 @@ github.com/google/go-cmp/cmp/internal/value # github.com/hashicorp/errwrap v1.1.0 ## explicit github.com/hashicorp/errwrap -# github.com/hashicorp/go-azure-helpers v0.66.1 +# github.com/hashicorp/go-azure-helpers v0.66.2 ## explicit; go 1.21 github.com/hashicorp/go-azure-helpers/lang/pointer github.com/hashicorp/go-azure-helpers/resourcemanager/resourceids -# github.com/hashicorp/go-azure-sdk/sdk v0.20240125.1122928 +# github.com/hashicorp/go-azure-sdk/sdk v0.20240411.1104331 ## explicit; go 1.21 github.com/hashicorp/go-azure-sdk/sdk/auth github.com/hashicorp/go-azure-sdk/sdk/claims From 352421f88494694b2722c31932f3b9e720ba6e09 Mon Sep 17 00:00:00 2001 From: Tom Bamford Date: Wed, 10 Apr 2024 21:29:21 +0100 Subject: [PATCH 2/6] provider: `environments.FromEndpoint()` no longer needs an environment name --- internal/acceptance/testclient/client.go | 2 +- internal/acceptance/testing.go | 2 +- internal/provider/provider.go | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/internal/acceptance/testclient/client.go b/internal/acceptance/testclient/client.go index d2478b8b87..239cf692a9 100644 --- a/internal/acceptance/testclient/client.go +++ b/internal/acceptance/testclient/client.go @@ -38,7 +38,7 @@ func Build(tenantId string) (*clients.Client, error) { } if metadataHost != "" { - if env, err = environments.FromEndpoint(ctx, fmt.Sprintf("https://%s", metadataHost), envName); err != nil { + if env, err = environments.FromEndpoint(ctx, fmt.Sprintf("https://%s", metadataHost)); err != nil { return nil, fmt.Errorf("building test client: %+v", err) } } else if env, err = environments.FromName(envName); err != nil { diff --git a/internal/acceptance/testing.go b/internal/acceptance/testing.go index 9dbae93d04..250ce595ab 100644 --- a/internal/acceptance/testing.go +++ b/internal/acceptance/testing.go @@ -56,7 +56,7 @@ func GetAuthConfig(t *testing.T) *auth.Credentials { ) if metadataHost != "" { - if env, err = environments.FromEndpoint(ctx, fmt.Sprintf("https://%s", metadataHost), envName); err != nil { + if env, err = environments.FromEndpoint(ctx, fmt.Sprintf("https://%s", metadataHost)); err != nil { t.Fatalf("building test client: %+v", err) return nil } diff --git a/internal/provider/provider.go b/internal/provider/provider.go index 5fe6d8ce21..34e1027d49 100644 --- a/internal/provider/provider.go +++ b/internal/provider/provider.go @@ -298,7 +298,7 @@ func providerConfigure(p *schema.Provider) schema.ConfigureContextFunc { ) if metadataHost != "" { - if env, err = environments.FromEndpoint(ctx, fmt.Sprintf("https://%s", metadataHost), envName); err != nil { + if env, err = environments.FromEndpoint(ctx, fmt.Sprintf("https://%s", metadataHost)); err != nil { return nil, pluginsdk.DiagFromErr(err) } } else if env, err = environments.FromName(envName); err != nil { From 8470fa4705d126221ee8027a6b9339cafe283f33 Mon Sep 17 00:00:00 2001 From: Tom Bamford Date: Thu, 11 Apr 2024 11:38:48 +0100 Subject: [PATCH 3/6] provider: move helpers to own source file, log the metdata configuration mode, tidy up provider tests --- internal/provider/helpers.go | 117 ++++++++++++++++++++ internal/provider/provider.go | 169 +++++++++-------------------- internal/provider/provider_test.go | 156 +++++++++++++++++--------- 3 files changed, 273 insertions(+), 169 deletions(-) create mode 100644 internal/provider/helpers.go diff --git a/internal/provider/helpers.go b/internal/provider/helpers.go new file mode 100644 index 0000000000..e0408ef898 --- /dev/null +++ b/internal/provider/helpers.go @@ -0,0 +1,117 @@ +package provider + +import ( + "encoding/base64" + "fmt" + "log" + "os" + "strings" + + "github.com/hashicorp/terraform-provider-azuread/internal/tf/pluginsdk" +) + +// logEntry avoids log entries showing up in test output +func logEntry(f string, v ...interface{}) { + if os.Getenv("TF_LOG") == "" { + return + } + + if os.Getenv("TF_ACC") != "" { + return + } + + log.Printf(f, v...) +} + +func decodeCertificate(clientCertificate string) ([]byte, error) { + var pfx []byte + if clientCertificate != "" { + out := make([]byte, base64.StdEncoding.DecodedLen(len(clientCertificate))) + n, err := base64.StdEncoding.Decode(out, []byte(clientCertificate)) + if err != nil { + return pfx, fmt.Errorf("could not decode client certificate data: %v", err) + } + pfx = out[:n] + } + return pfx, nil +} + +func getOidcToken(d *pluginsdk.ResourceData) (*string, error) { + idToken := d.Get("oidc_token").(string) + + if path := d.Get("oidc_token_file_path").(string); path != "" { + fileTokenRaw, err := os.ReadFile(path) + + if err != nil { + return nil, fmt.Errorf("reading OIDC Token from file %q: %v", path, err) + } + + fileToken := strings.TrimSpace(string(fileTokenRaw)) + + if idToken != "" && idToken != fileToken { + return nil, fmt.Errorf("mismatch between supplied OIDC token and supplied OIDC token file contents - please either remove one or ensure they match") + } + + idToken = fileToken + } + + return &idToken, nil +} + +func getClientId(d *pluginsdk.ResourceData) (*string, error) { + clientId := strings.TrimSpace(d.Get("client_id").(string)) + + if path := d.Get("client_id_file_path").(string); path != "" { + fileClientIdRaw, err := os.ReadFile(path) + + if err != nil { + return nil, fmt.Errorf("reading Client ID from file %q: %v", path, err) + } + + fileClientId := strings.TrimSpace(string(fileClientIdRaw)) + + if clientId != "" && clientId != fileClientId { + return nil, fmt.Errorf("mismatch between supplied Client ID and supplied Client ID file contents - please either remove one or ensure they match") + } + + clientId = fileClientId + } + + return &clientId, nil +} + +func getClientSecret(d *pluginsdk.ResourceData) (*string, error) { + clientSecret := strings.TrimSpace(d.Get("client_secret").(string)) + + if path := d.Get("client_secret_file_path").(string); path != "" { + fileSecretRaw, err := os.ReadFile(path) + + if err != nil { + return nil, fmt.Errorf("reading Client Secret from file %q: %v", path, err) + } + + fileSecret := strings.TrimSpace(string(fileSecretRaw)) + + if clientSecret != "" && clientSecret != fileSecret { + return nil, fmt.Errorf("mismatch between supplied Client Secret and supplied Client Secret file contents - please either remove one or ensure they match") + } + + clientSecret = fileSecret + } + + return &clientSecret, nil +} + +func getTenantId(d *pluginsdk.ResourceData) (*string, error) { + tenantId := strings.TrimSpace(d.Get("tenant_id").(string)) + + if d.Get("use_aks_workload_identity").(bool) && os.Getenv("AZURE_TENANT_ID") != "" { + aksTenantId := os.Getenv("AZURE_TENANT_ID") + if tenantId != "" && tenantId != aksTenantId { + return nil, fmt.Errorf("mismatch between supplied Tenant ID and that provided by AKS Workload Identity - please remove, ensure they match, or disable use_aks_workload_identity") + } + tenantId = aksTenantId + } + + return &tenantId, nil +} diff --git a/internal/provider/provider.go b/internal/provider/provider.go index 34e1027d49..3c2e847f3d 100644 --- a/internal/provider/provider.go +++ b/internal/provider/provider.go @@ -5,11 +5,7 @@ package provider import ( "context" - "encoding/base64" "fmt" - "log" - "os" - "strings" "github.com/hashicorp/go-azure-sdk/sdk/auth" "github.com/hashicorp/go-azure-sdk/sdk/environments" @@ -39,25 +35,12 @@ type ServiceRegistration interface { // AzureADProvider returns a schema.Provider. func AzureADProvider() *schema.Provider { - // avoids this showing up in test output - var debugLog = func(f string, v ...interface{}) { - if os.Getenv("TF_LOG") == "" { - return - } - - if os.Getenv("TF_ACC") != "" { - return - } - - log.Printf(f, v...) - } - dataSources := make(map[string]*pluginsdk.Resource) resources := make(map[string]*pluginsdk.Resource) // first handle the typed services for _, service := range SupportedTypedServices() { - debugLog("[DEBUG] Registering Data Sources for %q..", service.Name()) + logEntry("[DEBUG] Registering Data Sources for %q..", service.Name()) for _, ds := range service.DataSources() { key := ds.ResourceType() if existing := dataSources[key]; existing != nil { @@ -73,7 +56,7 @@ func AzureADProvider() *schema.Provider { dataSources[key] = dataSource } - debugLog("[DEBUG] Registering Resources for %q..", service.Name()) + logEntry("[DEBUG] Registering Resources for %q..", service.Name()) for _, r := range service.Resources() { key := r.ResourceType() if existing := resources[key]; existing != nil { @@ -91,7 +74,7 @@ func AzureADProvider() *schema.Provider { // then handle the untyped services for _, service := range SupportedUntypedServices() { - debugLog("[DEBUG] Registering Data Sources for %q..", service.Name()) + logEntry("[DEBUG] Registering Data Sources for %q..", service.Name()) for k, v := range service.SupportedDataSources() { if existing := dataSources[k]; existing != nil { panic(fmt.Sprintf("An existing Data Source exists for %q", k)) @@ -100,7 +83,7 @@ func AzureADProvider() *schema.Provider { dataSources[k] = v } - debugLog("[DEBUG] Registering Resources for %q..", service.Name()) + logEntry("[DEBUG] Registering Resources for %q..", service.Name()) for k, v := range service.SupportedResources() { if existing := resources[k]; existing != nil { panic(fmt.Sprintf("An existing Resource exists for %q", k)) @@ -137,7 +120,7 @@ func AzureADProvider() *schema.Provider { Type: pluginsdk.TypeString, Required: true, DefaultFunc: pluginsdk.EnvDefaultFunc("ARM_ENVIRONMENT", "global"), - Description: "The cloud environment which should be used. Possible values are: `global` (also `public`), `usgovernmentl4` (also `usgovernment`), `usgovernmentl5` (also `dod`), and `china`. Defaults to `global`", + Description: "The cloud environment which should be used. Possible values are: `global` (also `public`), `usgovernmentl4` (also `usgovernment`), `usgovernmentl5` (also `dod`), and `china`. Defaults to `global`. Not used and should not be specified when `metadata_host` is specified.", }, "metadata_host": { @@ -220,6 +203,14 @@ func AzureADProvider() *schema.Provider { Description: "The URL for the OIDC provider from which to request an ID token. For use when authenticating as a Service Principal using OpenID Connect.", }, + // Azure AKS Workload Identity fields + "use_aks_workload_identity": { + Type: schema.TypeBool, + Optional: true, + DefaultFunc: schema.EnvDefaultFunc("ARM_USE_AKS_WORKLOAD_IDENTITY", false), + Description: "Allow Azure AKS Workload Identity to be used for Authentication.", + }, + // CLI authentication specific fields "use_cli": { Type: pluginsdk.TypeBool, @@ -280,6 +271,11 @@ func providerConfigure(p *schema.Provider) schema.ConfigureContextFunc { } } + idToken, err := getOidcToken(d) + if err != nil { + return nil, pluginsdk.DiagFromErr(err) + } + clientSecret, err := getClientSecret(d) if err != nil { return nil, pluginsdk.DiagFromErr(err) @@ -290,6 +286,11 @@ func providerConfigure(p *schema.Provider) schema.ConfigureContextFunc { return nil, pluginsdk.DiagFromErr(err) } + tenantId, err := getTenantId(d) + if err != nil { + return nil, pluginsdk.DiagFromErr(err) + } + var ( env *environments.Environment @@ -298,11 +299,15 @@ func providerConfigure(p *schema.Provider) schema.ConfigureContextFunc { ) if metadataHost != "" { + logEntry("[DEBUG] Configuring cloud environment from Metadata Service at %q", metadataHost) if env, err = environments.FromEndpoint(ctx, fmt.Sprintf("https://%s", metadataHost)); err != nil { return nil, pluginsdk.DiagFromErr(err) } - } else if env, err = environments.FromName(envName); err != nil { - return nil, pluginsdk.DiagFromErr(err) + } else { + logEntry("[DEBUG] Configuring built-in cloud environment by name: %q", envName) + if env, err = environments.FromName(envName); err != nil { + return nil, pluginsdk.DiagFromErr(err) + } } if env.MicrosoftGraph == nil { @@ -311,29 +316,34 @@ func providerConfigure(p *schema.Provider) schema.ConfigureContextFunc { return nil, pluginsdk.DiagErrorf("Microsoft Graph endpoint could not be determined for the specified environment") } - idToken, err := oidcToken(d) - if err != nil { - return nil, pluginsdk.DiagFromErr(err) - } + var ( + enableAzureCli = d.Get("use_cli").(bool) + enableManagedIdentity = d.Get("use_msi").(bool) + enableOidc = d.Get("use_oidc").(bool) || d.Get("use_aks_workload_identity").(bool) + ) authConfig := &auth.Credentials{ - Environment: *env, - TenantID: d.Get("tenant_id").(string), - ClientID: *clientId, - ClientCertificateData: certData, - ClientCertificatePassword: d.Get("client_certificate_password").(string), - ClientCertificatePath: d.Get("client_certificate_path").(string), - ClientSecret: *clientSecret, + Environment: *env, + ClientID: *clientId, + TenantID: *tenantId, + + ClientCertificateData: certData, + ClientCertificatePassword: d.Get("client_certificate_password").(string), + ClientCertificatePath: d.Get("client_certificate_path").(string), + ClientSecret: *clientSecret, + OIDCAssertionToken: *idToken, GitHubOIDCTokenRequestURL: d.Get("oidc_request_url").(string), GitHubOIDCTokenRequestToken: d.Get("oidc_request_token").(string), + + CustomManagedIdentityEndpoint: d.Get("msi_endpoint").(string), + + EnableAuthenticatingUsingAzureCLI: enableAzureCli, EnableAuthenticatingUsingClientCertificate: true, EnableAuthenticatingUsingClientSecret: true, - EnableAuthenticationUsingOIDC: d.Get("use_oidc").(bool), - EnableAuthenticationUsingGitHubOIDC: d.Get("use_oidc").(bool), - EnableAuthenticatingUsingAzureCLI: d.Get("use_cli").(bool), - EnableAuthenticatingUsingManagedIdentity: d.Get("use_msi").(bool), - CustomManagedIdentityEndpoint: d.Get("msi_endpoint").(string), + EnableAuthenticatingUsingManagedIdentity: enableManagedIdentity, + EnableAuthenticationUsingGitHubOIDC: enableOidc, + EnableAuthenticationUsingOIDC: enableOidc, } // only one pid can be interpreted currently @@ -367,82 +377,3 @@ func buildClient(ctx context.Context, p *schema.Provider, authConfig *auth.Crede return client, nil } - -func decodeCertificate(clientCertificate string) ([]byte, error) { - var pfx []byte - if clientCertificate != "" { - out := make([]byte, base64.StdEncoding.DecodedLen(len(clientCertificate))) - n, err := base64.StdEncoding.Decode(out, []byte(clientCertificate)) - if err != nil { - return pfx, fmt.Errorf("could not decode client certificate data: %v", err) - } - pfx = out[:n] - } - return pfx, nil -} - -func oidcToken(d *pluginsdk.ResourceData) (*string, error) { - idToken := d.Get("oidc_token").(string) - - if path := d.Get("oidc_token_file_path").(string); path != "" { - fileTokenRaw, err := os.ReadFile(path) - - if err != nil { - return nil, fmt.Errorf("reading OIDC Token from file %q: %v", path, err) - } - - fileToken := strings.TrimSpace(string(fileTokenRaw)) - - if idToken != "" && idToken != fileToken { - return nil, fmt.Errorf("mismatch between supplied OIDC token and supplied OIDC token file contents - please either remove one or ensure they match") - } - - idToken = fileToken - } - - return &idToken, nil -} - -func getClientId(d *pluginsdk.ResourceData) (*string, error) { - clientId := strings.TrimSpace(d.Get("client_id").(string)) - - if path := d.Get("client_id_file_path").(string); path != "" { - fileClientIdRaw, err := os.ReadFile(path) - - if err != nil { - return nil, fmt.Errorf("reading Client ID from file %q: %v", path, err) - } - - fileClientId := strings.TrimSpace(string(fileClientIdRaw)) - - if clientId != "" && clientId != fileClientId { - return nil, fmt.Errorf("mismatch between supplied Client ID and supplied Client ID file contents - please either remove one or ensure they match") - } - - clientId = fileClientId - } - - return &clientId, nil -} - -func getClientSecret(d *pluginsdk.ResourceData) (*string, error) { - clientSecret := strings.TrimSpace(d.Get("client_secret").(string)) - - if path := d.Get("client_secret_file_path").(string); path != "" { - fileSecretRaw, err := os.ReadFile(path) - - if err != nil { - return nil, fmt.Errorf("reading Client Secret from file %q: %v", path, err) - } - - fileSecret := strings.TrimSpace(string(fileSecretRaw)) - - if clientSecret != "" && clientSecret != fileSecret { - return nil, fmt.Errorf("mismatch between supplied Client Secret and supplied Client Secret file contents - please either remove one or ensure they match") - } - - clientSecret = fileSecret - } - - return &clientSecret, nil -} diff --git a/internal/provider/provider_test.go b/internal/provider/provider_test.go index ee5f7a09e3..904e80b712 100644 --- a/internal/provider/provider_test.go +++ b/internal/provider/provider_test.go @@ -11,7 +11,6 @@ import ( "github.com/hashicorp/go-azure-sdk/sdk/auth" "github.com/hashicorp/go-azure-sdk/sdk/environments" - "github.com/hashicorp/terraform-plugin-sdk/v2/diag" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "github.com/hashicorp/terraform-plugin-sdk/v2/terraform" "github.com/hashicorp/terraform-provider-azuread/internal/clients" @@ -44,10 +43,14 @@ func TestAccProvider_cliAuth(t *testing.T) { t.Fatalf("configuring environment %q: %v", envName, err) } - authConfig := &auth.Credentials{ - Environment: *env, - TenantID: d.Get("tenant_id").(string), + tenantId, err := getTenantId(d) + if err != nil { + return nil, pluginsdk.DiagFromErr(err) + } + authConfig := &auth.Credentials{ + Environment: *env, + TenantID: *tenantId, EnableAuthenticatingUsingAzureCLI: true, } @@ -82,14 +85,23 @@ func TestAccProvider_clientCertificateAuth(t *testing.T) { t.Fatalf("configuring environment %q: %v", envName, err) } - authConfig := &auth.Credentials{ - Environment: *env, - TenantID: d.Get("tenant_id").(string), - ClientID: d.Get("client_id").(string), + clientId, err := getClientId(d) + if err != nil { + return nil, pluginsdk.DiagFromErr(err) + } + tenantId, err := getTenantId(d) + if err != nil { + return nil, pluginsdk.DiagFromErr(err) + } + + authConfig := &auth.Credentials{ + Environment: *env, + TenantID: *tenantId, + ClientID: *clientId, + ClientCertificatePath: d.Get("client_certificate_path").(string), + ClientCertificatePassword: d.Get("client_certificate_password").(string), EnableAuthenticatingUsingClientCertificate: true, - ClientCertificatePath: d.Get("client_certificate_path").(string), - ClientCertificatePassword: d.Get("client_certificate_password").(string), } return buildClient(ctx, provider, authConfig, "") @@ -122,7 +134,7 @@ func TestAccProvider_clientCertificateInlineAuth(t *testing.T) { var err error certData, err = decodeCertificate(encodedCert) if err != nil { - return nil, diag.FromErr(err) + return nil, pluginsdk.DiagFromErr(err) } } @@ -132,14 +144,23 @@ func TestAccProvider_clientCertificateInlineAuth(t *testing.T) { t.Fatalf("configuring environment %q: %v", envName, err) } - authConfig := &auth.Credentials{ - Environment: *env, - TenantID: d.Get("tenant_id").(string), - ClientID: d.Get("client_id").(string), + clientId, err := getClientId(d) + if err != nil { + return nil, pluginsdk.DiagFromErr(err) + } + tenantId, err := getTenantId(d) + if err != nil { + return nil, pluginsdk.DiagFromErr(err) + } + + authConfig := &auth.Credentials{ + Environment: *env, + TenantID: *tenantId, + ClientID: *clientId, + ClientCertificateData: certData, + ClientCertificatePassword: d.Get("client_certificate_password").(string), EnableAuthenticatingUsingClientCertificate: true, - ClientCertificateData: certData, - ClientCertificatePassword: d.Get("client_certificate_password").(string), } return buildClient(ctx, provider, authConfig, "") @@ -191,21 +212,25 @@ func testAccProvider_clientSecretAuthFromEnvironment(t *testing.T) { clientId, err := getClientId(d) if err != nil { - return nil, diag.FromErr(err) + return nil, pluginsdk.DiagFromErr(err) } clientSecret, err := getClientSecret(d) if err != nil { - return nil, diag.FromErr(err) + return nil, pluginsdk.DiagFromErr(err) } - authConfig := &auth.Credentials{ - Environment: *env, - TenantID: d.Get("tenant_id").(string), - ClientID: *clientId, + tenantId, err := getTenantId(d) + if err != nil { + return nil, pluginsdk.DiagFromErr(err) + } - EnableAuthenticatingUsingClientSecret: true, + authConfig := &auth.Credentials{ + Environment: *env, + TenantID: *tenantId, + ClientID: *clientId, ClientSecret: *clientSecret, + EnableAuthenticatingUsingClientSecret: true, } return buildClient(ctx, provider, authConfig, "") @@ -252,21 +277,25 @@ func testAccProvider_clientSecretAuthFromFiles(t *testing.T) { clientId, err := getClientId(d) if err != nil { - return nil, diag.FromErr(err) + return nil, pluginsdk.DiagFromErr(err) } clientSecret, err := getClientSecret(d) if err != nil { - return nil, diag.FromErr(err) + return nil, pluginsdk.DiagFromErr(err) } - authConfig := &auth.Credentials{ - Environment: *env, - TenantID: d.Get("tenant_id").(string), - ClientID: *clientId, + tenantId, err := getTenantId(d) + if err != nil { + return nil, pluginsdk.DiagFromErr(err) + } - EnableAuthenticatingUsingClientSecret: true, + authConfig := &auth.Credentials{ + Environment: *env, + TenantID: *tenantId, + ClientID: *clientId, ClientSecret: *clientSecret, + EnableAuthenticatingUsingClientSecret: true, } return buildClient(ctx, provider, authConfig, "") @@ -312,18 +341,27 @@ func testAccProvider_genericOidcAuthFromEnvironment(t *testing.T) { t.Fatalf("configuring environment %q: %v", envName, err) } - idToken, err := oidcToken(d) + idToken, err := getOidcToken(d) if err != nil { - return nil, diag.FromErr(err) + return nil, pluginsdk.DiagFromErr(err) } - authConfig := &auth.Credentials{ - Environment: *env, - TenantID: d.Get("tenant_id").(string), - ClientID: d.Get("client_id").(string), + clientId, err := getClientId(d) + if err != nil { + return nil, pluginsdk.DiagFromErr(err) + } - EnableAuthenticationUsingOIDC: true, + tenantId, err := getTenantId(d) + if err != nil { + return nil, pluginsdk.DiagFromErr(err) + } + + authConfig := &auth.Credentials{ + Environment: *env, + TenantID: *tenantId, + ClientID: *clientId, OIDCAssertionToken: *idToken, + EnableAuthenticationUsingOIDC: true, } return buildClient(ctx, provider, authConfig, "") @@ -364,18 +402,27 @@ func testAccProvider_genericOidcAuthFromFiles(t *testing.T) { t.Fatalf("configuring environment %q: %v", envName, err) } - idToken, err := oidcToken(d) + idToken, err := getOidcToken(d) if err != nil { - return nil, diag.FromErr(err) + return nil, pluginsdk.DiagFromErr(err) } - authConfig := &auth.Credentials{ - Environment: *env, - TenantID: d.Get("tenant_id").(string), - ClientID: d.Get("client_id").(string), + clientId, err := getClientId(d) + if err != nil { + return nil, pluginsdk.DiagFromErr(err) + } - EnableAuthenticationUsingOIDC: true, + tenantId, err := getTenantId(d) + if err != nil { + return nil, pluginsdk.DiagFromErr(err) + } + + authConfig := &auth.Credentials{ + Environment: *env, + TenantID: *tenantId, + ClientID: *clientId, OIDCAssertionToken: *idToken, + EnableAuthenticationUsingOIDC: true, } return buildClient(ctx, provider, authConfig, "") @@ -415,14 +462,23 @@ func TestAccProvider_githubOidcAuth(t *testing.T) { t.Fatalf("configuring environment %q: %v", envName, err) } - authConfig := &auth.Credentials{ - Environment: *env, - TenantID: d.Get("tenant_id").(string), - ClientID: d.Get("client_id").(string), + clientId, err := getClientId(d) + if err != nil { + return nil, pluginsdk.DiagFromErr(err) + } - EnableAuthenticationUsingGitHubOIDC: true, + tenantId, err := getTenantId(d) + if err != nil { + return nil, pluginsdk.DiagFromErr(err) + } + + authConfig := &auth.Credentials{ + Environment: *env, + TenantID: *tenantId, + ClientID: *clientId, GitHubOIDCTokenRequestToken: d.Get("oidc_request_token").(string), GitHubOIDCTokenRequestURL: d.Get("oidc_request_url").(string), + EnableAuthenticationUsingGitHubOIDC: true, } return buildClient(ctx, provider, authConfig, "") From b9e75d26a4f7967c49b04dbf4c4e6aeebe0fb164 Mon Sep 17 00:00:00 2001 From: Tom Bamford Date: Thu, 11 Apr 2024 11:57:19 +0100 Subject: [PATCH 4/6] Changelog for #1353 --- CHANGELOG.md | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index a1aa732c1e..091a959133 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,13 @@ +## 2.48.0 (Unreleased) + +ENHAHCEMENTS: + +* dependencies: updating to `v0.20240411.1104331` of `github.com/hashicorp/go-azure-sdk/sdk` [GH-1353] + +BUG FIXES: + +* provider: fix an issue where the provider was not correctly configured when using a custom metadata host [GH-1353] + ## 2.47.0 (December 14, 2023) BUG FIXES: From bc599837d7e96de4ffd77b509d2310018e556621 Mon Sep 17 00:00:00 2001 From: Tom Bamford Date: Thu, 11 Apr 2024 11:57:33 +0100 Subject: [PATCH 5/6] typo fix --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 091a959133..87c5d03c2b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,6 @@ ## 2.48.0 (Unreleased) -ENHAHCEMENTS: +ENHANCEMENTS: * dependencies: updating to `v0.20240411.1104331` of `github.com/hashicorp/go-azure-sdk/sdk` [GH-1353] From 0d6e12c0f7b7547972f2c97eddaf421d7586eb79 Mon Sep 17 00:00:00 2001 From: Tom Bamford Date: Thu, 11 Apr 2024 23:36:30 +0100 Subject: [PATCH 6/6] v2.48.0 --- CHANGELOG.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 87c5d03c2b..f642af1567 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,12 +1,12 @@ -## 2.48.0 (Unreleased) +## 2.48.0 (April 11, 2024) ENHANCEMENTS: -* dependencies: updating to `v0.20240411.1104331` of `github.com/hashicorp/go-azure-sdk/sdk` [GH-1353] +* dependencies: updating to `v0.20240411.1104331` of `github.com/hashicorp/go-azure-sdk/sdk` ([#1353](https://github.com/hashicorp/terraform-provider-azuread/issues/1353)) BUG FIXES: -* provider: fix an issue where the provider was not correctly configured when using a custom metadata host [GH-1353] +* provider: fix an issue where the provider was not correctly configured when using a custom metadata host ([#1353](https://github.com/hashicorp/terraform-provider-azuread/issues/1353)) ## 2.47.0 (December 14, 2023)