diff --git a/sdk/internal/CHANGELOG.md b/sdk/internal/CHANGELOG.md index 2819d6fafc66..3ca4af2a81e6 100644 --- a/sdk/internal/CHANGELOG.md +++ b/sdk/internal/CHANGELOG.md @@ -1,14 +1,9 @@ # Release History -## 1.9.2 (Unreleased) +## 1.10.0 (2024-07-16) ### Features Added - -### Breaking Changes - -### Bugs Fixed - -### Other Changes +* `test/credential.New` supports federated authentication in Azure Pipelines ## 1.9.1 (2024-07-02) diff --git a/sdk/internal/go.mod b/sdk/internal/go.mod index 26d662000422..8709c784cbe5 100644 --- a/sdk/internal/go.mod +++ b/sdk/internal/go.mod @@ -6,7 +6,7 @@ require ( github.com/Azure/azure-sdk-for-go/sdk/azcore v1.12.0 github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.7.0 github.com/stretchr/testify v1.9.0 - golang.org/x/net v0.26.0 + golang.org/x/net v0.27.0 golang.org/x/text v0.16.0 ) @@ -20,8 +20,8 @@ require ( github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c // indirect github.com/pmezard/go-difflib v1.0.0 // indirect github.com/rogpeppe/go-internal v1.12.0 // indirect - golang.org/x/crypto v0.24.0 // indirect - golang.org/x/sys v0.21.0 // indirect + golang.org/x/crypto v0.25.0 // indirect + golang.org/x/sys v0.22.0 // indirect gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/sdk/internal/go.sum b/sdk/internal/go.sum index a17d3a0f9838..3f32721973a9 100644 --- a/sdk/internal/go.sum +++ b/sdk/internal/go.sum @@ -30,13 +30,13 @@ github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4= github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= -golang.org/x/crypto v0.24.0 h1:mnl8DM0o513X8fdIkmyFE/5hTYxbwYOjDS/+rK6qpRI= -golang.org/x/crypto v0.24.0/go.mod h1:Z1PMYSOR5nyMcyAVAIQSKCDwalqy85Aqn1x3Ws4L5DM= -golang.org/x/net v0.26.0 h1:soB7SVo0PWrY4vPW/+ay0jKDNScG2X9wFeYlXIvJsOQ= -golang.org/x/net v0.26.0/go.mod h1:5YKkiSynbBIh3p6iOc/vibscux0x38BZDkn8sCUPxHE= +golang.org/x/crypto v0.25.0 h1:ypSNr+bnYL2YhwoMt2zPxHFmbAN1KZs/njMG3hxUp30= +golang.org/x/crypto v0.25.0/go.mod h1:T+wALwcMOSE0kXgUAnPAHqTLW+XHgcELELW8VaDgm/M= +golang.org/x/net v0.27.0 h1:5K3Njcw06/l2y9vpGCSdcxWOYHOUk3dVNGDXN+FvAys= +golang.org/x/net v0.27.0/go.mod h1:dDi0PyhWNoiUOrAS8uXv/vnScO4wnHQO4mj9fn/RytE= golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.21.0 h1:rF+pYz3DAGSQAxAu1CbC7catZg4ebC4UIeIhKxBZvws= -golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.22.0 h1:RI27ohtqKCnwULzJLqkv897zojh5/DwS/ENaMzUOaWI= +golang.org/x/sys v0.22.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4= golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= diff --git a/sdk/internal/test/credential/credential.go b/sdk/internal/test/credential/credential.go index 19fe0757d8c9..40fd112204ab 100644 --- a/sdk/internal/test/credential/credential.go +++ b/sdk/internal/test/credential/credential.go @@ -18,11 +18,22 @@ var recordMode = recording.GetRecordMode() type NewOptions struct{} -// New constructs an [azcore.TokenCredential] for use in tests +// New constructs a credential for use in tests. In playback mode, it returns [Fake], which always +// provides valid tokens. In live and record modes, it returns a credential based on the environment: +// - [azidentity.AzurePipelinesCredential] when running in an Azure Pipelines AzurePowerShell task +// - [azidentity.ClientSecretCredential], if New-TestResources.ps1 provided service principal details +// - [azidentity.DefaultAzureCredential] otherwise func New(*NewOptions) (azcore.TokenCredential, error) { if recordMode == recording.PlaybackMode { return &Fake{}, nil } + accessToken := os.Getenv("SYSTEM_ACCESSTOKEN") + clientID := os.Getenv("AZURESUBSCRIPTION_CLIENT_ID") + connectionID := os.Getenv("AZURESUBSCRIPTION_SERVICE_CONNECTION_ID") + tenant := os.Getenv("AZURESUBSCRIPTION_TENANT_ID") + if accessToken != "" && clientID != "" && connectionID != "" && tenant != "" { + return azidentity.NewAzurePipelinesCredential(tenant, clientID, connectionID, accessToken, nil) + } if s := os.Getenv("AZURE_SERVICE_DIRECTORY"); s != "" { // New-TestResources.ps1 has configured this environment, possibly with service principal details clientID := os.Getenv(s + "_CLIENT_ID") diff --git a/sdk/internal/test/credential/credential_test.go b/sdk/internal/test/credential/credential_test.go index fbe9de2f16ab..dcbbbf95ae37 100644 --- a/sdk/internal/test/credential/credential_test.go +++ b/sdk/internal/test/credential/credential_test.go @@ -16,21 +16,43 @@ import ( func TestNew(t *testing.T) { before := recordMode - for _, pipeline := range []bool{true, false} { - name := "dev/" - if pipeline { - name = "pipeline/" - } + for _, test := range []struct { + name string + env map[string]string + expected any + }{ + { + name: "pipeline/SP/", + env: map[string]string{ + "AZURE_SERVICE_DIRECTORY": t.Name(), + t.Name() + "_CLIENT_ID": "clientID", + t.Name() + "_CLIENT_SECRET": "secret", + t.Name() + "_TENANT_ID": "tenant", + }, + expected: &azidentity.ClientSecretCredential{}, + }, + { + name: "pipeline/WIF/", + env: map[string]string{ + "AZURESUBSCRIPTION_CLIENT_ID": "clientID", + "AZURESUBSCRIPTION_SERVICE_CONNECTION_ID": "connectionID", + "AZURESUBSCRIPTION_TENANT_ID": "tenant", + "SYSTEM_ACCESSTOKEN": "token", + "SYSTEM_OIDCREQUESTURI": "https://localhost", + }, + expected: &azidentity.AzurePipelinesCredential{}, + }, + { + name: "dev/", + expected: &azidentity.DefaultAzureCredential{}, + }, + } { for _, mode := range []string{recording.LiveMode, recording.PlaybackMode, recording.RecordingMode} { - t.Run(name+mode, func(t *testing.T) { + t.Run(test.name+mode, func(t *testing.T) { recordMode = mode defer func() { recordMode = before }() - if pipeline { - // set environment variables as would New-TestResources.ps1 - t.Setenv("AZURE_SERVICE_DIRECTORY", t.Name()) - for _, v := range []string{"_CLIENT_ID", "_CLIENT_SECRET", "_TENANT_ID"} { - t.Setenv(t.Name()+v, recording.SanitizedValue) - } + for k, v := range test.env { + t.Setenv(k, v) } cred, err := New(nil) require.NoError(t, err) @@ -41,11 +63,7 @@ func TestNew(t *testing.T) { require.Equal(t, recording.SanitizedValue, tk.Token) require.True(t, tk.ExpiresOn.After(time.Now())) } else { - if pipeline { - require.IsType(t, &azidentity.ClientSecretCredential{}, cred) - } else { - require.IsType(t, &azidentity.DefaultAzureCredential{}, cred) - } + require.IsType(t, test.expected, cred) } }) } diff --git a/sdk/internal/version.go b/sdk/internal/version.go index 40b75718817e..242047628e2b 100644 --- a/sdk/internal/version.go +++ b/sdk/internal/version.go @@ -9,5 +9,5 @@ package internal const ( // version is the semantic version (see http://semver.org) of this module. //lint:ignore U1000 reason: "this constant is used by release automation" - version = "v1.9.2" + version = "v1.10.0" )