@@ -12,6 +12,7 @@ import (
12
12
"crypto/tls"
13
13
"crypto/x509"
14
14
"encoding/base64"
15
+ "encoding/pem"
15
16
"errors"
16
17
"fmt"
17
18
"io/ioutil"
@@ -25,6 +26,7 @@ import (
25
26
"github.com/jhump/protoreflect/desc"
26
27
"github.com/jhump/protoreflect/desc/protoprint"
27
28
"github.com/jhump/protoreflect/dynamic"
29
+ "golang.org/x/crypto/pkcs12"
28
30
"google.golang.org/grpc"
29
31
"google.golang.org/grpc/credentials"
30
32
"google.golang.org/grpc/credentials/insecure"
@@ -515,7 +517,7 @@ func makeTemplate(md *desc.MessageDescriptor, path []*desc.MessageDescriptor) pr
515
517
//
516
518
// Deprecated: Use grpcurl.ClientTLSConfig and credentials.NewTLS instead.
517
519
func ClientTransportCredentials (insecureSkipVerify bool , cacertFile , clientCertFile , clientKeyFile string ) (credentials.TransportCredentials , error ) {
518
- tlsConf , err := ClientTLSConfig (insecureSkipVerify , cacertFile , clientCertFile , clientKeyFile )
520
+ tlsConf , err := ClientTLSConfig (insecureSkipVerify , cacertFile , clientCertFile , clientKeyFile , "" , "" )
519
521
if err != nil {
520
522
return nil , err
521
523
}
@@ -527,12 +529,18 @@ func ClientTransportCredentials(insecureSkipVerify bool, cacertFile, clientCertF
527
529
// given properties. If cacertFile is blank, only standard trusted certs are used to
528
530
// verify the server certs. If clientCertFile is blank, the client will not use a client
529
531
// certificate. If clientCertFile is not blank then clientKeyFile must not be blank.
530
- func ClientTLSConfig (insecureSkipVerify bool , cacertFile , clientCertFile , clientKeyFile string ) (* tls.Config , error ) {
532
+ func ClientTLSConfig (insecureSkipVerify bool , cacertFile , clientCertFile , clientKeyFile , clientCertType , clientPass string ) (* tls.Config , error ) {
531
533
var tlsConf tls.Config
532
534
533
535
if clientCertFile != "" {
534
536
// Load the client certificates from disk
535
- certificate , err := tls .LoadX509KeyPair (clientCertFile , clientKeyFile )
537
+ var certificate tls.Certificate
538
+ var err error
539
+ if strings .EqualFold (clientCertType , "p12" ) {
540
+ certificate , err = loadClientCertP12 (clientCertFile , clientPass )
541
+ } else {
542
+ certificate , err = tls .LoadX509KeyPair (clientCertFile , clientKeyFile )
543
+ }
536
544
if err != nil {
537
545
return nil , fmt .Errorf ("could not load client key pair: %v" , err )
538
546
}
@@ -560,6 +568,27 @@ func ClientTLSConfig(insecureSkipVerify bool, cacertFile, clientCertFile, client
560
568
return & tlsConf , nil
561
569
}
562
570
571
+ func loadClientCertP12 (pfxFile , pfxPassword string ) (tls.Certificate , error ) {
572
+ b , err := os .ReadFile (pfxFile )
573
+ if err != nil {
574
+ return tls.Certificate {}, fmt .Errorf ("os.ReadFile err: %w" , err )
575
+ }
576
+ pemBlocks , err := pkcs12 .ToPEM (b , pfxPassword )
577
+ if err != nil {
578
+ return tls.Certificate {}, fmt .Errorf ("pkcs12.ToPEM err: %w" , err )
579
+ }
580
+
581
+ var pemBytes []byte
582
+ for _ , block := range pemBlocks {
583
+ pemBytes = append (pemBytes , pem .EncodeToMemory (block )... )
584
+ }
585
+ certificate , err := tls .X509KeyPair (pemBytes , pemBytes )
586
+ if err != nil {
587
+ return tls.Certificate {}, err
588
+ }
589
+ return certificate , nil
590
+ }
591
+
563
592
// ServerTransportCredentials builds transport credentials for a gRPC server using the
564
593
// given properties. If cacertFile is blank, the server will not request client certs
565
594
// unless requireClientCerts is true. When requireClientCerts is false and cacertFile is
0 commit comments