github.com/argoproj-labs/argocd-operator@v0.10.0/controllers/argoutil/tls.go (about) 1 // Copyright 2019 ArgoCD Operator Developers 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package argoutil 16 17 import ( 18 "crypto/rand" 19 "crypto/rsa" 20 "crypto/x509" 21 "crypto/x509/pkix" 22 "encoding/pem" 23 "errors" 24 "fmt" 25 "math" 26 "math/big" 27 "time" 28 29 tlsutil "github.com/operator-framework/operator-sdk/pkg/tls" 30 31 "github.com/argoproj-labs/argocd-operator/common" 32 ) 33 34 // NewPrivateKey returns randomly generated RSA private key. 35 func NewPrivateKey() (*rsa.PrivateKey, error) { 36 return rsa.GenerateKey(rand.Reader, common.ArgoCDDefaultRSAKeySize) 37 } 38 39 // EncodePrivateKeyPEM encodes the given private key pem and returns bytes (base64). 40 func EncodePrivateKeyPEM(key *rsa.PrivateKey) []byte { 41 return pem.EncodeToMemory(&pem.Block{ 42 Type: "RSA PRIVATE KEY", 43 Bytes: x509.MarshalPKCS1PrivateKey(key), 44 }) 45 } 46 47 // EncodeCertificatePEM encodes the given certificate pem and returns bytes (base64). 48 func EncodeCertificatePEM(cert *x509.Certificate) []byte { 49 return pem.EncodeToMemory(&pem.Block{ 50 Type: "CERTIFICATE", 51 Bytes: cert.Raw, 52 }) 53 } 54 55 // ParsePEMEncodedCert parses a certificate from the given pemdata 56 func ParsePEMEncodedCert(pemdata []byte) (*x509.Certificate, error) { 57 decoded, _ := pem.Decode(pemdata) 58 if decoded == nil { 59 return nil, errors.New("no PEM data found") 60 } 61 return x509.ParseCertificate(decoded.Bytes) 62 } 63 64 // ParsePEMEncodedPrivateKey parses a private key from given pemdata 65 func ParsePEMEncodedPrivateKey(pemdata []byte) (*rsa.PrivateKey, error) { 66 decoded, _ := pem.Decode(pemdata) 67 if decoded == nil { 68 return nil, errors.New("no PEM data found") 69 } 70 return x509.ParsePKCS1PrivateKey(decoded.Bytes) 71 } 72 73 // NewSelfSignedCACertificate returns a self-signed CA certificate based on given configuration and private key. 74 // The certificate has one-year lease. 75 func NewSelfSignedCACertificate(name string, key *rsa.PrivateKey) (*x509.Certificate, error) { 76 serial, err := rand.Int(rand.Reader, new(big.Int).SetInt64(math.MaxInt64)) 77 if err != nil { 78 return nil, err 79 } 80 now := time.Now() 81 tmpl := x509.Certificate{ 82 SerialNumber: serial, 83 NotBefore: now.UTC(), 84 NotAfter: now.Add(common.ArgoCDDuration365Days).UTC(), 85 KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature | x509.KeyUsageCertSign, 86 BasicConstraintsValid: true, 87 IsCA: true, 88 Subject: pkix.Name{CommonName: fmt.Sprintf("argocd-operator@%s", name)}, 89 } 90 certDERBytes, err := x509.CreateCertificate(rand.Reader, &tmpl, &tmpl, key.Public(), key) 91 if err != nil { 92 return nil, err 93 } 94 return x509.ParseCertificate(certDERBytes) 95 } 96 97 // NewSignedCertificate signs a certificate using the given private key, CA and returns a signed certificate. 98 // The certificate could be used for both client and server auth. 99 // The certificate has one-year lease. 100 func NewSignedCertificate(cfg *tlsutil.CertConfig, dnsNames []string, key *rsa.PrivateKey, caCert *x509.Certificate, caKey *rsa.PrivateKey) (*x509.Certificate, error) { 101 serial, err := rand.Int(rand.Reader, new(big.Int).SetInt64(math.MaxInt64)) 102 if err != nil { 103 return nil, err 104 } 105 eku := []x509.ExtKeyUsage{} 106 switch cfg.CertType { 107 case tlsutil.ClientCert: 108 eku = append(eku, x509.ExtKeyUsageClientAuth) 109 case tlsutil.ServingCert: 110 eku = append(eku, x509.ExtKeyUsageServerAuth) 111 case tlsutil.ClientAndServingCert: 112 eku = append(eku, x509.ExtKeyUsageClientAuth, x509.ExtKeyUsageServerAuth) 113 } 114 certTmpl := x509.Certificate{ 115 Subject: pkix.Name{ 116 CommonName: cfg.CommonName, 117 Organization: cfg.Organization, 118 }, 119 DNSNames: dnsNames, 120 SerialNumber: serial, 121 NotBefore: caCert.NotBefore, 122 NotAfter: time.Now().Add(common.ArgoCDDuration365Days).UTC(), 123 KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature, 124 ExtKeyUsage: eku, 125 } 126 certDERBytes, err := x509.CreateCertificate(rand.Reader, &certTmpl, caCert, key.Public(), caKey) 127 if err != nil { 128 return nil, err 129 } 130 return x509.ParseCertificate(certDERBytes) 131 }