Skip to content

Commit

Permalink
EnvironmentCredential supports cert passwords (#17099)
Browse files Browse the repository at this point in the history
  • Loading branch information
magodo authored Jun 7, 2022
1 parent 2e712cf commit fd8d667
Show file tree
Hide file tree
Showing 3 changed files with 42 additions and 3 deletions.
3 changes: 2 additions & 1 deletion sdk/azidentity/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -168,7 +168,8 @@ client := armresources.NewResourceGroupsClient("subscription ID", chain, nil)
|-|-
|`AZURE_CLIENT_ID`|ID of an Azure Active Directory application
|`AZURE_TENANT_ID`|ID of the application's Azure Active Directory tenant
|`AZURE_CLIENT_CERTIFICATE_PATH`|path to a certificate file including private key (without password protection)
|`AZURE_CLIENT_CERTIFICATE_PATH`|path to a certificate file including private key
|`AZURE_CLIENT_CERTIFICATE_PASSWORD`|password of the certificate file, if any

#### Username and password

Expand Down
10 changes: 8 additions & 2 deletions sdk/azidentity/environment_credential.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,9 @@ type EnvironmentCredentialOptions struct {
//
// AZURE_CLIENT_ID: the service principal's client ID
//
// AZURE_CLIENT_CERTIFICATE_PATH: path to a PEM or PKCS12 certificate file including the unencrypted private key.
// AZURE_CLIENT_CERTIFICATE_PATH: path to a PEM or PKCS12 certificate file including the private key.
//
// AZURE_CLIENT_CERTIFICATE_PASSWORD: (optional) password for the certificate file.
//
// User with username and password
//
Expand Down Expand Up @@ -85,7 +87,11 @@ func NewEnvironmentCredential(options *EnvironmentCredentialOptions) (*Environme
if err != nil {
return nil, fmt.Errorf(`failed to read certificate file "%s": %v`, certPath, err)
}
certs, key, err := ParseCertificates(certData, nil)
var password []byte
if v := os.Getenv("AZURE_CLIENT_CERTIFICATE_PASSWORD"); v != "" {
password = []byte(v)
}
certs, key, err := ParseCertificates(certData, password)
if err != nil {
return nil, fmt.Errorf(`failed to load certificate from "%s": %v`, certPath, err)
}
Expand Down
32 changes: 32 additions & 0 deletions sdk/azidentity/environment_credential_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,10 @@ package azidentity
import (
"context"
"errors"
"fmt"
"os"
"reflect"
"strings"
"testing"

"github.com/Azure/azure-sdk-for-go/sdk/azcore"
Expand Down Expand Up @@ -116,6 +118,36 @@ func TestEnvironmentCredential_ClientCertificatePathSet(t *testing.T) {
}
}

func TestEnvironmentCredential_ClientCertificatePassword(t *testing.T) {
for key, value := range map[string]string{
"AZURE_TENANT_ID": fakeTenantID,
azureClientID: fakeClientID,
"AZURE_CLIENT_CERTIFICATE_PATH": "testdata/certificate_encrypted_key.pfx",
} {
t.Setenv(key, value)
}
for _, correctPassword := range []bool{true, false} {
t.Run(fmt.Sprintf("%v", correctPassword), func(t *testing.T) {
password := "wrong password"
if correctPassword {
password = "password"
}
t.Setenv("AZURE_CLIENT_CERTIFICATE_PASSWORD", password)
cred, err := NewEnvironmentCredential(nil)
if correctPassword {
if err != nil {
t.Fatal(err)
}
if _, ok := cred.cred.(*ClientCertificateCredential); !ok {
t.Fatalf("expected *azidentity.ClientCertificateCredential, got %t", cred)
}
} else if err == nil || !strings.Contains(err.Error(), "password") {
t.Fatal("expected an error about the password")
}
})
}
}

func TestEnvironmentCredential_UsernameOnlySet(t *testing.T) {
resetEnvironmentVarsForTest()
err := os.Setenv("AZURE_TENANT_ID", fakeTenantID)
Expand Down

0 comments on commit fd8d667

Please sign in to comment.