github.com/hashicorp/vault/sdk@v0.11.0/helper/pluginutil/tls.go (about) 1 // Copyright (c) HashiCorp, Inc. 2 // SPDX-License-Identifier: MPL-2.0 3 4 package pluginutil 5 6 import ( 7 "context" 8 "crypto/ecdsa" 9 "crypto/elliptic" 10 "crypto/rand" 11 "crypto/tls" 12 "crypto/x509" 13 "crypto/x509/pkix" 14 "time" 15 16 "github.com/hashicorp/errwrap" 17 "github.com/hashicorp/go-uuid" 18 "github.com/hashicorp/vault/sdk/helper/certutil" 19 ) 20 21 // generateCert is used internally to create certificates for the plugin 22 // client and server. 23 func generateCert() ([]byte, *ecdsa.PrivateKey, error) { 24 key, err := ecdsa.GenerateKey(elliptic.P521(), rand.Reader) 25 if err != nil { 26 return nil, nil, err 27 } 28 29 host, err := uuid.GenerateUUID() 30 if err != nil { 31 return nil, nil, err 32 } 33 34 sn, err := certutil.GenerateSerialNumber() 35 if err != nil { 36 return nil, nil, err 37 } 38 39 template := &x509.Certificate{ 40 Subject: pkix.Name{ 41 CommonName: host, 42 }, 43 DNSNames: []string{host}, 44 ExtKeyUsage: []x509.ExtKeyUsage{ 45 x509.ExtKeyUsageClientAuth, 46 x509.ExtKeyUsageServerAuth, 47 }, 48 KeyUsage: x509.KeyUsageDigitalSignature | x509.KeyUsageKeyEncipherment | x509.KeyUsageKeyAgreement, 49 SerialNumber: sn, 50 NotBefore: time.Now().Add(-30 * time.Second), 51 NotAfter: time.Now().Add(262980 * time.Hour), 52 IsCA: true, 53 } 54 55 certBytes, err := x509.CreateCertificate(rand.Reader, template, template, key.Public(), key) 56 if err != nil { 57 return nil, nil, errwrap.Wrapf("unable to generate client certificate: {{err}}", err) 58 } 59 60 return certBytes, key, nil 61 } 62 63 // createClientTLSConfig creates a signed certificate and returns a configured 64 // TLS config. 65 func createClientTLSConfig(certBytes []byte, key *ecdsa.PrivateKey) (*tls.Config, error) { 66 clientCert, err := x509.ParseCertificate(certBytes) 67 if err != nil { 68 return nil, errwrap.Wrapf("error parsing generated plugin certificate: {{err}}", err) 69 } 70 71 cert := tls.Certificate{ 72 Certificate: [][]byte{certBytes}, 73 PrivateKey: key, 74 Leaf: clientCert, 75 } 76 77 clientCertPool := x509.NewCertPool() 78 clientCertPool.AddCert(clientCert) 79 80 tlsConfig := &tls.Config{ 81 Certificates: []tls.Certificate{cert}, 82 RootCAs: clientCertPool, 83 ClientCAs: clientCertPool, 84 ClientAuth: tls.RequireAndVerifyClientCert, 85 ServerName: clientCert.Subject.CommonName, 86 MinVersion: tls.VersionTLS12, 87 } 88 89 return tlsConfig, nil 90 } 91 92 // wrapServerConfig is used to create a server certificate and private key, then 93 // wrap them in an unwrap token for later retrieval by the plugin. 94 func wrapServerConfig(ctx context.Context, sys RunnerUtil, certBytes []byte, key *ecdsa.PrivateKey) (string, error) { 95 rawKey, err := x509.MarshalECPrivateKey(key) 96 if err != nil { 97 return "", err 98 } 99 100 wrapInfo, err := sys.ResponseWrapData(ctx, map[string]interface{}{ 101 "ServerCert": certBytes, 102 "ServerKey": rawKey, 103 }, time.Second*60, true) 104 if err != nil { 105 return "", err 106 } 107 108 return wrapInfo.Token, nil 109 }