11package azure
22
33import (
4+ "crypto/rsa"
5+ "crypto/x509"
6+ "fmt"
47 "net/url"
58 "os"
69 "strings"
@@ -9,6 +12,7 @@ import (
912 "github.com/Azure/go-autorest/autorest"
1013 "github.com/Azure/go-autorest/autorest/adal"
1114 "github.com/Azure/go-autorest/autorest/azure"
15+ "golang.org/x/crypto/pkcs12"
1216)
1317
1418func getAzureKVParams (secretConfig map [string ]interface {}, name string ) string {
@@ -19,7 +23,7 @@ func getAzureKVParams(secretConfig map[string]interface{}, name string) string {
1923 }
2024}
2125
22- func getAzureVaultClient (clientID , secretID , tenantID , envName string ) (keyvault.BaseClient , error ) {
26+ func getAzureVaultClient (clientID , secretID , certPath , certPassword , tenantID , envName string ) (keyvault.BaseClient , error ) {
2327 var environment * azure.Environment
2428 alternateEndpoint , _ := url .Parse (
2529 "https://login.windows.net/" + tenantID + "/oauth2/token" )
@@ -37,11 +41,44 @@ func getAzureVaultClient(clientID, secretID, tenantID, envName string) (keyvault
3741 }
3842 oauthconfig .AuthorizeEndpoint = * alternateEndpoint
3943
40- token , err := adal .NewServicePrincipalToken (
41- * oauthconfig , clientID , secretID , strings .TrimSuffix (environment .KeyVaultEndpoint , "/" ))
42- if err != nil {
43- return keyClient , err
44+ var token * adal.ServicePrincipalToken
45+ if secretID != "" {
46+ token , err = adal .NewServicePrincipalToken (
47+ * oauthconfig , clientID , secretID , strings .TrimSuffix (environment .KeyVaultEndpoint , "/" ))
48+ if err != nil {
49+ return keyClient , err
50+ }
51+ } else if certPath != "" && certPassword != "" {
52+ certData , err := os .ReadFile (certPath )
53+ if err != nil {
54+ return keyClient , fmt .Errorf ("reading the client certificate from file %s: %v" , certPath , err )
55+ }
56+ certificate , privateKey , err := decodePkcs12 (certData , certPassword )
57+ if err != nil {
58+ return keyClient , fmt .Errorf ("decoding the client certificate: %v" , err )
59+ }
60+ token , err = adal .NewServicePrincipalTokenFromCertificate (
61+ * oauthconfig , clientID , certificate , privateKey , strings .TrimSuffix (environment .KeyVaultEndpoint , "/" ))
62+ if err != nil {
63+ return keyClient , err
64+ }
4465 }
66+
4567 keyClient .Authorizer = autorest .NewBearerAuthorizer (token )
4668 return keyClient , nil
4769}
70+
71+ // decodePkcs12 decodes a PKCS#12 client certificate by extracting the public certificate and
72+ // the private RSA key
73+ func decodePkcs12 (pkcs []byte , password string ) (* x509.Certificate , * rsa.PrivateKey , error ) {
74+ privateKey , certificate , err := pkcs12 .Decode (pkcs , password )
75+ if err != nil {
76+ return nil , nil , fmt .Errorf ("decoding the PKCS#12 client certificate: %v" , err )
77+ }
78+ rsaPrivateKey , isRsaKey := privateKey .(* rsa.PrivateKey )
79+ if ! isRsaKey {
80+ return nil , nil , fmt .Errorf ("PKCS#12 certificate must contain a RSA private key" )
81+ }
82+
83+ return certificate , rsaPrivateKey , nil
84+ }
0 commit comments