Skip to content

Commit

Permalink
GH-3963: Allow user to specify audience for OIDC authentication (#3970)
Browse files Browse the repository at this point in the history
This PR is a copy of #3965 by @robcao, to make CI tests run. Original
description:

-----

This pull request is a potential implementation for
#3963

It adds a new configuration variable for the auth_azidentity module,
ARM_OIDC_AUDIENCE.

When specified, the value of ARM_OIDC_AUDIENCE will be used when making
a request for a federated token. If not specified, the audience will
default to api://AzureADTokenExchange like currently.

Co-authored-by: Robert Cao <[email protected]>
  • Loading branch information
thomas11 and robcao authored Feb 20, 2025
1 parent 0e2299b commit 68c1a11
Show file tree
Hide file tree
Showing 2 changed files with 27 additions and 1 deletion.
9 changes: 8 additions & 1 deletion provider/pkg/provider/auth_azidentity.go
Original file line number Diff line number Diff line change
Expand Up @@ -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")
Expand Down Expand Up @@ -235,6 +240,7 @@ type authConfiguration struct {
auxTenants []string

useOidc bool
oidcAudience string
oidcToken string
oidcTokenFilePath string
oidcTokenRequestToken string
Expand Down Expand Up @@ -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"),
Expand Down
19 changes: 19 additions & 0 deletions provider/pkg/provider/auth_azidentity_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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)
Expand All @@ -69,6 +71,7 @@ func TestGetAuthConfig(t *testing.T) {
"clientId": "conf",
"clientSecret": "conf",
"environment": "usgov",
"oidcAudience": "conf",
"oidcToken": "conf",
"oidcTokenFilePath": "conf",
"oidcRequestToken": "conf",
Expand All @@ -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)
Expand All @@ -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)
Expand Down Expand Up @@ -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{
{
Expand Down

0 comments on commit 68c1a11

Please sign in to comment.