github.com/verrazzano/verrazzano-monitoring-operator@v0.0.30/pkg/vmo/certificate.go (about) 1 // Copyright (c) 2020, 2021, Oracle and/or its affiliates. 2 // Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. 3 4 package vmo 5 6 import ( 7 "bytes" 8 cryptorand "crypto/rand" 9 "crypto/rsa" 10 "crypto/x509" 11 "crypto/x509/pkix" 12 "encoding/pem" 13 "fmt" 14 "math/big" 15 "os" 16 "time" 17 ) 18 19 const ( 20 // OperatorName is the resource name for the Verrazzano monitoring operator 21 OperatorName = "verrazzano-monitoring-operator" 22 // OperatorNamespace is the resource namespace for the Verrazzano monitoring operator 23 OperatorNamespace = "verrazzano-system" 24 ) 25 26 // CreateCertificates creates the needed certificates for the validating webhook 27 func CreateCertificates(certDir string) (*bytes.Buffer, error) { 28 var caPEM, serverCertPEM, serverPrivKeyPEM *bytes.Buffer 29 30 commonName := fmt.Sprintf("%s.%s.svc", OperatorName, OperatorNamespace) 31 serialNumber, err := newSerialNumber() 32 if err != nil { 33 return nil, err 34 } 35 36 // CA config 37 ca := &x509.Certificate{ 38 DNSNames: []string{commonName}, 39 SerialNumber: serialNumber, 40 Subject: pkix.Name{ 41 CommonName: commonName, 42 }, 43 NotBefore: time.Now(), 44 NotAfter: time.Now().AddDate(1, 0, 0), 45 IsCA: true, 46 ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth, x509.ExtKeyUsageServerAuth}, 47 KeyUsage: x509.KeyUsageDigitalSignature | x509.KeyUsageCertSign, 48 BasicConstraintsValid: true, 49 } 50 51 // CA private key 52 caPrivKey, err := rsa.GenerateKey(cryptorand.Reader, 4096) 53 if err != nil { 54 return nil, err 55 } 56 57 // Self signed CA certificate 58 caBytes, err := x509.CreateCertificate(cryptorand.Reader, ca, ca, &caPrivKey.PublicKey, caPrivKey) 59 if err != nil { 60 return nil, err 61 } 62 63 // PEM encode CA cert 64 caPEM = new(bytes.Buffer) 65 _ = pem.Encode(caPEM, &pem.Block{ 66 Type: "CERTIFICATE", 67 Bytes: caBytes, 68 }) 69 70 serialNumber, err = newSerialNumber() 71 if err != nil { 72 return nil, err 73 } 74 75 // server cert config 76 cert := &x509.Certificate{ 77 DNSNames: []string{commonName}, 78 SerialNumber: serialNumber, 79 Subject: pkix.Name{ 80 CommonName: commonName, 81 }, 82 NotBefore: time.Now(), 83 NotAfter: time.Now().AddDate(1, 0, 0), 84 IsCA: true, 85 SubjectKeyId: []byte{1, 2, 3, 4, 6}, 86 ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth, x509.ExtKeyUsageServerAuth}, 87 KeyUsage: x509.KeyUsageDigitalSignature, 88 } 89 90 // server private key 91 serverPrivKey, err := rsa.GenerateKey(cryptorand.Reader, 4096) 92 if err != nil { 93 return nil, err 94 } 95 96 // sign the server cert 97 serverCertBytes, err := x509.CreateCertificate(cryptorand.Reader, cert, ca, &serverPrivKey.PublicKey, caPrivKey) 98 if err != nil { 99 return nil, err 100 } 101 102 // PEM encode the server cert and key 103 serverCertPEM = new(bytes.Buffer) 104 _ = pem.Encode(serverCertPEM, &pem.Block{ 105 Type: "CERTIFICATE", 106 Bytes: serverCertBytes, 107 }) 108 109 serverPrivKeyPEM = new(bytes.Buffer) 110 _ = pem.Encode(serverPrivKeyPEM, &pem.Block{ 111 Type: "RSA PRIVATE KEY", 112 Bytes: x509.MarshalPKCS1PrivateKey(serverPrivKey), 113 }) 114 115 err = os.MkdirAll(certDir, 0666) 116 if err != nil { 117 return nil, err 118 } 119 120 err = writeFile(fmt.Sprintf("%s/tls.crt", certDir), serverCertPEM) 121 if err != nil { 122 return nil, err 123 } 124 125 err = writeFile(fmt.Sprintf("%s/tls.key", certDir), serverPrivKeyPEM) 126 if err != nil { 127 return nil, err 128 } 129 130 return caPEM, nil 131 } 132 133 // newSerialNumber returns a new random serial number suitable for use in a certificate. 134 func newSerialNumber() (*big.Int, error) { 135 // A serial number can be up to 20 octets in size. 136 return cryptorand.Int(cryptorand.Reader, new(big.Int).Lsh(big.NewInt(1), 8*20)) 137 } 138 139 // writeFile writes data in the file at the given path 140 func writeFile(filepath string, pem *bytes.Buffer) error { 141 f, err := os.Create(filepath) 142 if err != nil { 143 return err 144 } 145 defer f.Close() 146 147 _, err = f.Write(pem.Bytes()) 148 if err != nil { 149 return err 150 } 151 152 return nil 153 }