Skip to content

Commit 3c002ec

Browse files
committed
migrate from adal to azidentity
adal is is out of support since March 31, 2023. This PR migrates from adal to azidentity for azure key vault Signed-off-by: sp98 <sapillai@redhat.com>
1 parent 5f4b25c commit 3c002ec

File tree

6 files changed

+186
-60
lines changed

6 files changed

+186
-60
lines changed

azure/azure_kv.go

Lines changed: 38 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,10 @@ import (
44
"context"
55
"encoding/json"
66
"errors"
7+
"strings"
78
"time"
89

9-
"github.com/Azure/azure-sdk-for-go/services/keyvault/2016-10-01/keyvault"
10-
"github.com/Azure/go-autorest/autorest/to"
10+
"github.com/Azure/azure-sdk-for-go/sdk/keyvault/azsecrets"
1111
"github.com/libopenstorage/secrets"
1212
"github.com/portworx/sched-ops/task"
1313
)
@@ -21,6 +21,10 @@ const (
2121
AzureClientID = "AZURE_CLIENT_ID"
2222
// AzureClientSecret of service principal account
2323
AzureClientSecret = "AZURE_CLIENT_SECRET"
24+
// AzureClientCertPath is path of the client certificate
25+
AzureClientCertPath = "AZURE_CLIENT_CERT_PATH"
26+
// AzureClientCertPassword is the password of the private key
27+
AzureClientCertPassword = "AZURE_CIENT_CERT_PASSWORD"
2428
// AzureEnviornment to connect
2529
AzureEnviornment = "AZURE_ENVIRONMENT"
2630
// AzureVaultURI of azure key vault
@@ -37,6 +41,7 @@ var (
3741
ErrAzureTenantIDNotSet = errors.New("AZURE_TENANT_ID not set.")
3842
ErrAzureClientIDNotSet = errors.New("AZURE_CLIENT_ID not set.")
3943
ErrAzureSecretIDNotSet = errors.New("AZURE_SECRET_ID not set.")
44+
ErrAzureAuthMedhodNotSet = errors.New("AZURE_SECRET_ID or AZURE_CLIENT_CERT_PATH not set")
4045
ErrAzureVaultURLNotSet = errors.New("AZURE_VAULT_URL not set.")
4146
ErrAzureEnvironmentNotset = errors.New("AZURE_ENVIRONMENT not set.")
4247
ErrAzureConfigMissing = errors.New("AzureConfig is not provided")
@@ -45,7 +50,7 @@ var (
4550
)
4651

4752
type azureSecrets struct {
48-
kv keyvault.BaseClient
53+
kv azsecrets.Client
4954
baseURL string
5055
}
5156

@@ -62,9 +67,9 @@ func New(
6267
return nil, ErrAzureClientIDNotSet
6368
}
6469
secretID := getAzureKVParams(secretConfig, AzureClientSecret)
65-
if secretID == "" {
66-
return nil, ErrAzureSecretIDNotSet
67-
}
70+
clientCertPath := getAzureKVParams(secretConfig, AzureClientCertPath)
71+
clientCertPassword := getAzureKVParams(secretConfig, AzureClientCertPassword)
72+
6873
envName := getAzureKVParams(secretConfig, AzureEnviornment)
6974
if envName == "" {
7075
// we set back to default AzurePublicCloud
@@ -75,13 +80,24 @@ func New(
7580
return nil, ErrAzureVaultURLNotSet
7681
}
7782

78-
client, err := getAzureVaultClient(clientID, secretID, tenantID, envName)
79-
if err != nil {
80-
return nil, err
83+
var client *azsecrets.Client
84+
var err error
85+
if secretID != "" {
86+
client, err = getAzureVaultClient(clientID, secretID, tenantID, vaultURL)
87+
if err != nil {
88+
return nil, err
89+
}
90+
} else if clientCertPath != "" {
91+
client, err = getAzureVaultClientWithCert(clientID, tenantID, vaultURL, clientCertPath, clientCertPassword)
92+
if err != nil {
93+
return nil, err
94+
}
95+
} else {
96+
return nil, ErrAzureAuthMedhodNotSet
8197
}
8298

8399
return &azureSecrets{
84-
kv: client,
100+
kv: *client,
85101
baseURL: vaultURL,
86102
}, nil
87103
}
@@ -98,8 +114,13 @@ func (az *azureSecrets) GetSecret(
98114
}
99115

100116
t := func() (interface{}, bool, error) {
101-
secretResp, err := az.kv.GetSecret(ctx, az.baseURL, secretID, "")
117+
// passing empty version to always get the latest version of the secret.
118+
secretResp, err := az.kv.GetSecret(ctx, secretID, "", nil)
102119
if err != nil {
120+
// don't retry if Secret is not present
121+
if strings.Contains(err.Error(), "SecretNotFound") {
122+
return nil, false, secrets.ErrSecretNotFound
123+
}
103124
return nil, true, err
104125
}
105126
return secretResp, false, nil
@@ -109,7 +130,7 @@ func (az *azureSecrets) GetSecret(
109130
return nil, secrets.NoVersion, err
110131
}
111132

112-
secretResp, ok := resp.(keyvault.SecretBundle)
133+
secretResp, ok := resp.(azsecrets.GetSecretResponse)
113134
if !ok || secretResp.Value == nil {
114135
return nil, secrets.NoVersion, ErrInvalidSecretResp
115136
}
@@ -133,7 +154,7 @@ func (az *azureSecrets) PutSecret(
133154
ctx, cancel := context.WithTimeout(context.Background(), defaultTimeout)
134155
defer cancel()
135156

136-
var secretResp keyvault.SecretBundle
157+
var secretResp azsecrets.SecretBundle
137158
if secretName == "" {
138159
return secrets.NoVersion, secrets.ErrEmptySecretId
139160
}
@@ -146,10 +167,10 @@ func (az *azureSecrets) PutSecret(
146167
return secrets.NoVersion, err
147168
}
148169

170+
valueStr := string(value)
149171
t := func() (interface{}, bool, error) {
150-
secretResp, err = az.kv.SetSecret(ctx, az.baseURL, secretName, keyvault.SecretSetParameters{
151-
Value: to.StringPtr(string(value)),
152-
})
172+
params := azsecrets.SetSecretParameters{Value: &valueStr}
173+
az.kv.SetSecret(ctx, secretName, params, nil)
153174
if err != nil {
154175
return nil, true, err
155176
}
@@ -169,7 +190,7 @@ func (az *azureSecrets) DeleteSecret(
169190
if secretName == "" {
170191
return secrets.ErrEmptySecretId
171192
}
172-
_, err := az.kv.DeleteSecret(ctx, az.baseURL, secretName)
193+
_, err := az.kv.DeleteSecret(ctx, secretName, nil)
173194

174195
return err
175196
}

azure/azure_kv_helper.go

Lines changed: 37 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,11 @@
11
package azure
22

33
import (
4-
"net/url"
4+
"fmt"
55
"os"
6-
"strings"
76

8-
"github.com/Azure/azure-sdk-for-go/services/keyvault/2016-10-01/keyvault"
9-
"github.com/Azure/go-autorest/autorest"
10-
"github.com/Azure/go-autorest/autorest/adal"
11-
"github.com/Azure/go-autorest/autorest/azure"
7+
"github.com/Azure/azure-sdk-for-go/sdk/azidentity"
8+
"github.com/Azure/azure-sdk-for-go/sdk/keyvault/azsecrets"
129
)
1310

1411
func getAzureKVParams(secretConfig map[string]interface{}, name string) string {
@@ -19,29 +16,46 @@ func getAzureKVParams(secretConfig map[string]interface{}, name string) string {
1916
}
2017
}
2118

22-
func getAzureVaultClient(clientID, secretID, tenantID, envName string) (keyvault.BaseClient, error) {
23-
var environment *azure.Environment
24-
alternateEndpoint, _ := url.Parse(
25-
"https://login.windows.net/" + tenantID + "/oauth2/token")
19+
func getAzureVaultClient(clientID, secretID, tenantID, vaultURL string) (*azsecrets.Client, error) {
20+
cred, err := azidentity.NewClientSecretCredential(tenantID, clientID, secretID, nil)
21+
if err != nil {
22+
return nil, fmt.Errorf("failed to get client secret credentials. %v", err)
23+
}
24+
client, err := azsecrets.NewClient(vaultURL, cred, nil)
25+
if err != nil {
26+
return nil, fmt.Errorf("failed to get client to access azure kv secrets. %v", err)
27+
}
28+
29+
return client, nil
30+
}
31+
32+
func getAzureVaultClientWithCert(clientID, tenantID, vaultURL, certPath, certPassword string) (*azsecrets.Client, error) {
33+
certData, err := os.ReadFile(certPath)
34+
if err != nil {
35+
return nil, fmt.Errorf("failed read certificate from path %q. %v", certPath, err)
36+
}
2637

27-
keyClient := keyvault.New()
28-
env, err := azure.EnvironmentFromName(envName)
38+
var passphrase []byte
39+
if certPassword == "" {
40+
passphrase = nil
41+
} else {
42+
passphrase = []byte(certPassword)
43+
}
44+
45+
certs, key, err := azidentity.ParseCertificates(certData, passphrase)
2946
if err != nil {
30-
return keyClient, err
47+
return nil, fmt.Errorf("failed load certificate and private key. %v", err)
3148
}
32-
environment = &env
33-
oauthconfig, err := adal.NewOAuthConfig(
34-
environment.ActiveDirectoryEndpoint, tenantID)
49+
50+
cred, err := azidentity.NewClientCertificateCredential(tenantID, clientID, certs, key, nil)
3551
if err != nil {
36-
return keyClient, err
52+
return nil, fmt.Errorf("failed to construct client certificate credentials. %v", err)
3753
}
38-
oauthconfig.AuthorizeEndpoint = *alternateEndpoint
3954

40-
token, err := adal.NewServicePrincipalToken(
41-
*oauthconfig, clientID, secretID, strings.TrimSuffix(environment.KeyVaultEndpoint, "/"))
55+
client, err := azsecrets.NewClient(vaultURL, cred, nil)
4256
if err != nil {
43-
return keyClient, err
57+
return nil, fmt.Errorf("failed to get client to access azure kv secrets. %v", err)
4458
}
45-
keyClient.Authorizer = autorest.NewBearerAuthorizer(token)
46-
return keyClient, nil
59+
60+
return client, nil
4761
}

azure/azure_kv_test.go

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -11,26 +11,24 @@ func TestNew(t *testing.T) {
1111
os.Unsetenv("AZURE_TENANT_ID")
1212
os.Unsetenv("AZURE_CLIENT_ID")
1313
os.Unsetenv("AZURE_CLIENT_SECRET")
14+
os.Unsetenv("AZURE_CLIENT_CERT_PATH")
1415
os.Unsetenv("AZURE_ENVIRONMENT")
1516
os.Unsetenv("AZURE_VAULT_URL")
1617

1718
// nil secret config
1819
_, err := New(nil)
19-
assert.Equal(t, err, ErrAzureTenantIDNotSet)
20+
assert.Equal(t, ErrAzureTenantIDNotSet, err)
2021
os.Setenv("AZURE_TENANT_ID", "invalid_tenant_id")
2122

2223
_, err = New(nil)
23-
assert.Equal(t, err, ErrAzureClientIDNotSet)
24+
assert.Equal(t, ErrAzureClientIDNotSet, err)
2425
os.Setenv("AZURE_CLIENT_ID", "invalid-client-id")
2526

2627
_, err = New(nil)
27-
assert.Equal(t, err, ErrAzureSecretIDNotSet)
28-
os.Setenv("AZURE_CLIENT_SECRET", "invalid-secret-id")
29-
30-
_, err = New(nil)
31-
assert.Equal(t, err, ErrAzureVaultURLNotSet)
28+
assert.Equal(t, ErrAzureVaultURLNotSet, err)
3229
os.Setenv("AZURE_VAULT_URL", "invalid-vault-url")
3330

3431
_, err = New(nil)
35-
assert.NoError(t, err, "Unepxected error on New")
32+
assert.Equal(t, ErrAzureAuthMedhodNotSet, err)
33+
os.Setenv("AZURE_CLIENT_SECRET", "invalid-secret-id")
3634
}

go.mod

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,21 +18,22 @@ require (
1818
github.com/portworx/kvdb v0.0.0-20200929023115-b312c7519467
1919
github.com/portworx/sched-ops v1.20.4-rc1
2020
github.com/sirupsen/logrus v1.9.0
21-
github.com/stretchr/testify v1.8.0
21+
github.com/stretchr/testify v1.8.4
2222
google.golang.org/api v0.83.0
2323
k8s.io/client-go v12.0.0+incompatible
2424
)
2525

2626
require (
27+
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.5.1
28+
github.com/Azure/azure-sdk-for-go/sdk/keyvault/azsecrets v0.12.0
29+
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/resources/armsubscriptions v1.3.0
2730
github.com/Azure/go-autorest/autorest/validation v0.3.1 // indirect
2831
github.com/cenkalti/backoff v2.2.1+incompatible // indirect
2932
github.com/cenkalti/backoff/v3 v3.2.2 // indirect
3033
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
3134
github.com/emicklei/go-restful/v3 v3.9.0 // indirect
3235
github.com/go-openapi/jsonreference v0.20.0 // indirect
3336
github.com/go-test/deep v1.0.8 // indirect
34-
github.com/golang-jwt/jwt/v4 v4.3.0 // indirect
35-
github.com/google/uuid v1.3.0 // indirect
3637
github.com/hashicorp/go-retryablehttp v0.7.1 // indirect
3738
github.com/hashicorp/hcl v1.0.1-vault-5 // indirect
3839
github.com/imdario/mergo v0.3.13 // indirect

0 commit comments

Comments
 (0)