github.com/jlmeeker/kismatic@v1.10.1-0.20180612190640-57f9005a1f1a/integration-tests/tls/cert.go (about) 1 package tls 2 3 import ( 4 "fmt" 5 "io/ioutil" 6 "os" 7 "path/filepath" 8 9 "github.com/cloudflare/cfssl/cli/genkey" 10 "github.com/cloudflare/cfssl/config" 11 "github.com/cloudflare/cfssl/csr" 12 "github.com/cloudflare/cfssl/helpers" 13 "github.com/cloudflare/cfssl/signer" 14 "github.com/cloudflare/cfssl/signer/local" 15 ) 16 17 // CA contains information about the Certificate Authority 18 type CA struct { 19 // Key is the CA's private key. 20 Key []byte 21 // Password is the CA's private key password. Can be empty if not password is set. 22 Password string 23 // Cert is the CA's public certificate. 24 Cert []byte 25 // ConfigFile contains a cfssl configuration file for the Certificate Authority 26 ConfigFile string 27 // Profile to be used when signing with this Certificate Authority 28 Profile string 29 } 30 31 // NewCert creates a new certificate/key pair using the CertificateAuthority provided 32 func NewCert(ca *CA, req csr.CertificateRequest) (key, cert []byte, err error) { 33 g := &csr.Generator{Validator: genkey.Validator} 34 csrBytes, key, err := g.ProcessRequest(&req) 35 if err != nil { 36 return nil, nil, fmt.Errorf("error processing CSR: %v", err) 37 } 38 // Get CA private key 39 caPriv, err := helpers.ParsePrivateKeyPEMWithPassword(ca.Key, []byte(ca.Password)) 40 if err != nil { 41 return nil, nil, fmt.Errorf("error parsing private key: %v", err) 42 } 43 // Parse CA Cert 44 caCert, err := helpers.ParseCertificatePEM(ca.Cert) 45 if err != nil { 46 return nil, nil, fmt.Errorf("error parsing CA cert: %v", err) 47 } 48 sigAlgo := signer.DefaultSigAlgo(caPriv) 49 // Get CA config from file 50 caConfig, err := config.LoadFile(ca.ConfigFile) 51 if err != nil { 52 return nil, nil, fmt.Errorf("error loading CA Config: %v", err) 53 } 54 // Create signer using CA 55 s, err := local.NewSigner(caPriv, caCert, sigAlgo, caConfig.Signing) 56 if err != nil { 57 return nil, nil, fmt.Errorf("error creating signer: %v", err) 58 } 59 // Generate cert using CA signer 60 signReq := signer.SignRequest{ 61 Request: string(csrBytes), 62 Profile: ca.Profile, 63 } 64 cert, err = s.Sign(signReq) 65 if err != nil { 66 return nil, nil, fmt.Errorf("error signing certificate: %v", err) 67 } 68 return key, cert, nil 69 } 70 71 // WriteCert writes cert and key files 72 func WriteCert(key, cert []byte, name, dir string) error { 73 // Create destination dir if it doesn't exist 74 err := CreateDir(dir, 0744) 75 if err != nil { 76 return err 77 } 78 // Write private key with read-only for user 79 err = ioutil.WriteFile(filepath.Join(dir, keyName(name)), key, 0600) 80 if err != nil { 81 return fmt.Errorf("error writing private key: %v", err) 82 } 83 // Write cert 84 err = ioutil.WriteFile(filepath.Join(dir, certName(name)), cert, 0644) 85 if err != nil { 86 return fmt.Errorf("error writing certificate: %v", err) 87 } 88 return nil 89 } 90 91 // CertKeyPairExists returns true if a key and matching certificate exist. 92 // Matching is defined as having the expected file names. No validation 93 // is performed on the actual bytes of the cert/key 94 func CertKeyPairExists(name, dir string) (bool, error) { 95 kn := keyName(name) 96 var err error 97 if _, err = os.Stat(filepath.Join(dir, kn)); os.IsNotExist(err) { 98 return false, nil 99 } 100 if err != nil { 101 return false, err 102 } 103 cn := certName(name) 104 if _, err = os.Stat(filepath.Join(dir, cn)); os.IsNotExist(err) { 105 return false, nil 106 } 107 if err != nil { 108 return false, err 109 } 110 return true, nil 111 } 112 113 func keyName(s string) string { return fmt.Sprintf("%s-key.pem", s) } 114 115 func certName(s string) string { return fmt.Sprintf("%s.pem", s) } 116 117 // CreateDir check if directory exists and create it 118 func CreateDir(dir string, perm os.FileMode) error { 119 if _, err := os.Stat(dir); os.IsNotExist(err) { 120 err := os.Mkdir(dir, perm) 121 if err != nil { 122 return fmt.Errorf("error creating destination dir: %v", err) 123 } 124 } 125 126 return nil 127 }