mirror of
https://github.com/opentofu/opentofu.git
synced 2026-05-28 04:15:54 -04:00
azurerm: respect audience in request URL
Signed-off-by: Larry Bordowitz <laurence.bordowitz@gmail.com>
This commit is contained in:
parent
0af2e8d521
commit
561012e4a9
1 changed files with 26 additions and 7 deletions
|
|
@ -13,6 +13,7 @@ import (
|
|||
"net/http"
|
||||
|
||||
"github.com/Azure/azure-sdk-for-go/sdk/azcore"
|
||||
"github.com/Azure/azure-sdk-for-go/sdk/azcore/cloud"
|
||||
"github.com/Azure/azure-sdk-for-go/sdk/azidentity"
|
||||
"github.com/opentofu/opentofu/internal/httpclient"
|
||||
"github.com/opentofu/opentofu/internal/tfdiags"
|
||||
|
|
@ -53,9 +54,9 @@ func (cred *oidcAuth) Construct(ctx context.Context, config *Config) (azcore.Tok
|
|||
// a fresh OIDC token as needed, enabling proper token refresh behavior.
|
||||
func(ctx context.Context) (string, error) {
|
||||
client := httpclient.New(ctx)
|
||||
|
||||
|
||||
if config.OIDCToken == "" && config.OIDCTokenFilePath == "" {
|
||||
return getTokenFromRemote(client, config.OIDCAuthConfig)
|
||||
return getTokenFromRemote(client, config.OIDCAuthConfig, config.CloudConfig)
|
||||
}
|
||||
return consolidateToken(config)
|
||||
},
|
||||
|
|
@ -69,7 +70,7 @@ type TokenResponse struct {
|
|||
Value string `json:"value"`
|
||||
}
|
||||
|
||||
func getTokenFromRemote(client *http.Client, config OIDCAuthConfig) (string, error) {
|
||||
func getTokenFromRemote(client *http.Client, config OIDCAuthConfig, env cloud.Configuration) (string, error) {
|
||||
// GET from the request URL, using the bearer token
|
||||
req, err := http.NewRequest(http.MethodGet, config.OIDCRequestURL, nil)
|
||||
if err != nil {
|
||||
|
|
@ -79,9 +80,11 @@ func getTokenFromRemote(client *http.Client, config OIDCAuthConfig) (string, err
|
|||
req.Header.Add("Accept", "application/json; api-version=2.0")
|
||||
req.Header.Add("Content-Type", "application/json")
|
||||
|
||||
query := req.URL.Query()
|
||||
query.Set("audience", "api://AzureADTokenExchange")
|
||||
req.URL.RawQuery = query.Encode()
|
||||
if !req.URL.Query().Has("audience") {
|
||||
query := req.URL.Query()
|
||||
query.Set("audience", requestURLAudience(env))
|
||||
req.URL.RawQuery = query.Encode()
|
||||
}
|
||||
|
||||
// Read the response
|
||||
resp, err := client.Do(req)
|
||||
|
|
@ -105,6 +108,22 @@ func getTokenFromRemote(client *http.Client, config OIDCAuthConfig) (string, err
|
|||
return token.Value, nil
|
||||
}
|
||||
|
||||
// requestURLAudience ensures the audience is configured appropriately for
|
||||
// its target cloud authority
|
||||
//
|
||||
// Reference:
|
||||
// https://learn.microsoft.com/en-us/entra/workload-id/workload-identity-federation-config-app-trust-managed-identity
|
||||
func requestURLAudience(env cloud.Configuration) string {
|
||||
switch env.ActiveDirectoryAuthorityHost {
|
||||
case "https://login.chinacloudapi.cn/":
|
||||
return "api://AzureADTokenExchangeChina"
|
||||
case "https://login.microsoftonline.us/":
|
||||
return "api://AzureADTokenExchangeUSGov"
|
||||
default:
|
||||
return "api://AzureADTokenExchange"
|
||||
}
|
||||
}
|
||||
|
||||
func consolidateToken(config *Config) (string, error) {
|
||||
return consolidateFileAndValue(config.OIDCToken, config.OIDCTokenFilePath, "token", true)
|
||||
}
|
||||
|
|
@ -145,7 +164,7 @@ func (cred *oidcAuth) Validate(ctx context.Context, config *Config) tfdiags.Diag
|
|||
}
|
||||
if directTokenUnset {
|
||||
// check request URL and token
|
||||
_, err := getTokenFromRemote(httpclient.New(ctx), config.OIDCAuthConfig)
|
||||
_, err := getTokenFromRemote(httpclient.New(ctx), config.OIDCAuthConfig, config.CloudConfig)
|
||||
if err != nil {
|
||||
diags = diags.Append(tfdiags.Sourceless(
|
||||
tfdiags.Error,
|
||||
|
|
|
|||
Loading…
Reference in a new issue