@@ -44,11 +44,13 @@ var (
44
44
)
45
45
46
46
const (
47
- resourceIDField = "resourceId"
48
- clientIDField = "clientId"
49
- tenantIDField = "tenantId"
50
- clientSecretField = "clientSecret"
51
- accountKeyField = "accountKey"
47
+ resourceIDField = "resourceId"
48
+ clientIDField = "clientId"
49
+ tenantIDField = "tenantId"
50
+ clientSecretField = "clientSecret"
51
+ clientCertificateField = "clientCertificate"
52
+ clientCertificatePasswordField = "clientCertificatePassword"
53
+ accountKeyField = "accountKey"
52
54
)
53
55
54
56
// BlobClient is a minimal Azure Blob client for fetching objects.
@@ -62,13 +64,17 @@ type BlobClient struct {
62
64
// order:
63
65
//
64
66
// - azidentity.ManagedIdentityCredential for a Resource ID, when a
65
- // resourceIDField is found.
66
- // - azidentity.ManagedIdentityCredential for a User ID, when a clientIDField
67
- // but no tenantIDField found.
68
- // - azidentity.ClientSecretCredential when a tenantIDField, clientIDField and
69
- // clientSecretField are found.
70
- // - azblob.SharedKeyCredential when an accountKeyField is found. The Account
71
- // Name is extracted from the endpoint specified on the Bucket object.
67
+ // `resourceId` field is found.
68
+ // - azidentity.ManagedIdentityCredential for a User ID, when a `clientId`
69
+ // field but no `tenantId` is found.
70
+ // - azidentity.ClientCertificateCredential when `tenantId`,
71
+ // `clientCertificate` (and optionally `clientCertificatePassword`) fields
72
+ // are found.
73
+ // - azidentity.ClientSecretCredential when `tenantId`, `clientId` and
74
+ // `clientSecret` fields are found.
75
+ // - azblob.SharedKeyCredential when an `accountKey` field is found.
76
+ // The account name is extracted from the endpoint specified on the Bucket
77
+ // object.
72
78
//
73
79
// If no credentials are found, a simple client without credentials is
74
80
// returned.
@@ -119,6 +125,9 @@ func ValidateSecret(secret *corev1.Secret) error {
119
125
if _ , hasClientSecret := secret .Data [clientSecretField ]; hasClientSecret {
120
126
valid = true
121
127
}
128
+ if _ , hasClientCertificate := secret .Data [clientCertificateField ]; hasClientCertificate {
129
+ valid = true
130
+ }
122
131
}
123
132
}
124
133
if _ , hasResourceID := secret .Data [resourceIDField ]; hasResourceID {
@@ -132,8 +141,8 @@ func ValidateSecret(secret *corev1.Secret) error {
132
141
}
133
142
134
143
if ! valid {
135
- return fmt .Errorf ("invalid '%s' secret data: requires a '%s', '%s', or '%s' field, or a combination of '%s', '%s' and '%s'" ,
136
- secret .Name , resourceIDField , clientIDField , accountKeyField , tenantIDField , clientIDField , clientSecretField )
144
+ return fmt .Errorf ("invalid '%s' secret data: requires a '%s', '%s', or '%s' field, a combination of '%s', '%s' and '%s', or '%s', '%s' and '%s'" ,
145
+ secret .Name , resourceIDField , clientIDField , accountKeyField , tenantIDField , clientIDField , clientSecretField , tenantIDField , clientIDField , clientCertificateField )
137
146
}
138
147
return nil
139
148
}
@@ -275,6 +284,13 @@ func tokenCredentialFromSecret(secret *corev1.Secret) (azcore.TokenCredential, e
275
284
ID : azidentity .ClientID (clientID ),
276
285
})
277
286
}
287
+ if clientCertificate , hasClientCertificate := secret .Data [clientCertificateField ]; hasClientCertificate {
288
+ certs , key , err := azidentity .ParseCertificates (clientCertificate , secret .Data [clientCertificatePasswordField ])
289
+ if err != nil {
290
+ return nil , fmt .Errorf ("failed to parse client certificates: %w" , err )
291
+ }
292
+ return azidentity .NewClientCertificateCredential (string (tenantID ), string (clientID ), certs , key , nil )
293
+ }
278
294
if clientSecret , hasClientSecret := secret .Data [clientSecretField ]; hasClientSecret {
279
295
return azidentity .NewClientSecretCredential (string (tenantID ), string (clientID ), string (clientSecret ), nil )
280
296
}
0 commit comments