diff --git a/provider/pkg/provider/auth_azidentity.go b/provider/pkg/provider/auth_azidentity.go index cd05edfd0129..8af47cf56ab2 100644 --- a/provider/pkg/provider/auth_azidentity.go +++ b/provider/pkg/provider/auth_azidentity.go @@ -170,8 +170,13 @@ func getOidcTokenExchangeAssertion(authConf *authConfiguration) func(ctx context if err != nil { return "", fmt.Errorf("githubAssertion: cannot parse URL query") } + // see https://docs.github.com/en/actions/security-for-github-actions/security-hardening-your-deployments/configuring-openid-connect-in-azure#adding-the-federated-credentials-to-azure - query.Set("audience", "api://AzureADTokenExchange") + audience := "api://AzureADTokenExchange" + if authConf.oidcAudience != "" { + audience = authConf.oidcAudience + } + query.Set("audience", audience) req.URL.RawQuery = query.Encode() req.Header.Set("Accept", "application/json") @@ -235,6 +240,7 @@ type authConfiguration struct { auxTenants []string useOidc bool + oidcAudience string oidcToken string oidcTokenFilePath string oidcTokenRequestToken string @@ -275,6 +281,7 @@ func (k *azureNativeProvider) readAuthConfig() (*authConfiguration, error) { useMsi: k.getConfig("useMsi", "ARM_USE_MSI") == "true", useOidc: k.getConfig("useOidc", "ARM_USE_OIDC") == "true", + oidcAudience: k.getConfig("oidcAudience", "ARM_OIDC_AUDIENCE"), oidcToken: k.getConfig("oidcToken", "ARM_OIDC_TOKEN"), oidcTokenFilePath: k.getConfig("oidcTokenFilePath", "ARM_OIDC_TOKEN_FILE_PATH"), oidcTokenRequestToken: k.getConfig("oidcRequestToken", "ACTIONS_ID_TOKEN_REQUEST_TOKEN"), diff --git a/provider/pkg/provider/auth_azidentity_test.go b/provider/pkg/provider/auth_azidentity_test.go index c95ee061b721..838348f45fb5 100644 --- a/provider/pkg/provider/auth_azidentity_test.go +++ b/provider/pkg/provider/auth_azidentity_test.go @@ -29,6 +29,7 @@ func TestGetAuthConfig(t *testing.T) { t.Setenv("ARM_CLIENT_CERTIFICATE_PATH", value) t.Setenv("ARM_CLIENT_ID", value) t.Setenv("ARM_CLIENT_SECRET", value) + t.Setenv("ARM_OIDC_AUDIENCE", value) t.Setenv("ARM_OIDC_TOKEN", value) t.Setenv("ARM_OIDC_TOKEN_FILE_PATH", value) t.Setenv("ACTIONS_ID_TOKEN_REQUEST_TOKEN", value) @@ -49,6 +50,7 @@ func TestGetAuthConfig(t *testing.T) { require.Empty(t, c.clientCertPath) require.Empty(t, c.clientId) require.Empty(t, c.clientSecret) + require.Empty(t, c.oidcAudience) require.Empty(t, c.oidcToken) require.Empty(t, c.oidcTokenFilePath) require.Empty(t, c.oidcTokenRequestToken) @@ -69,6 +71,7 @@ func TestGetAuthConfig(t *testing.T) { "clientId": "conf", "clientSecret": "conf", "environment": "usgov", + "oidcAudience": "conf", "oidcToken": "conf", "oidcTokenFilePath": "conf", "oidcRequestToken": "conf", @@ -88,6 +91,7 @@ func TestGetAuthConfig(t *testing.T) { require.Equal(t, "conf", c.clientCertPath) require.Equal(t, "conf", c.clientId) require.Equal(t, "conf", c.clientSecret) + require.Equal(t, "conf", c.oidcAudience) require.Equal(t, "conf", c.oidcToken) require.Equal(t, "conf", c.oidcTokenFilePath) require.Equal(t, "conf", c.oidcTokenRequestToken) @@ -111,6 +115,7 @@ func TestGetAuthConfig(t *testing.T) { require.Equal(t, "env", c.clientCertPath) require.Equal(t, "env", c.clientId) require.Equal(t, "env", c.clientSecret) + require.Equal(t, "env", c.oidcAudience) require.Equal(t, "env", c.oidcToken) require.Equal(t, "env", c.oidcTokenFilePath) require.Equal(t, "env", c.oidcTokenRequestToken) @@ -239,6 +244,20 @@ func TestNewCredential(t *testing.T) { require.IsType(t, &azidentity.ClientAssertionCredential{}, cred) }) + t.Run("OIDC with token exchange URL and custom audience", func(t *testing.T) { + conf := &authConfiguration{ + useOidc: true, + oidcAudience: "api://oidc-audience", + oidcTokenRequestToken: "oidc-token", + oidcTokenRequestUrl: "oidc-token-url", + clientId: "client-id", + tenantId: "tenant-id", + } + cred, err := newSingleMethodAuthCredential(conf) + require.NoError(t, err) + require.IsType(t, &azidentity.ClientAssertionCredential{}, cred) + }) + t.Run("Incomplete OIDC conf", func(t *testing.T) { for _, conf := range []*authConfiguration{ {