github.com/sealerio/sealer@v0.11.1-0.20240507115618-f4f89c5853ae/pkg/clustercert/cert/readwriter.go (about) 1 // Copyright © 2022 Alibaba Group Holding Ltd. 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 cert 16 17 import ( 18 "crypto" 19 "crypto/ecdsa" 20 "crypto/rsa" 21 "crypto/x509" 22 "fmt" 23 24 "github.com/pkg/errors" 25 certutil "k8s.io/client-go/util/cert" 26 "k8s.io/client-go/util/keyutil" 27 ) 28 29 // CertificateFileManger Asymmetric encryption, like ca.crt and ca.key 30 type CertificateFileManger struct { 31 certName string 32 certPath string 33 } 34 35 func (c CertificateFileManger) Write(cert *x509.Certificate, key crypto.Signer) error { 36 err := c.writeCert(cert) 37 if err != nil { 38 return err 39 } 40 41 err = c.writeKey(key) 42 if err != nil { 43 return err 44 } 45 46 return nil 47 } 48 49 func (c CertificateFileManger) writeKey(key crypto.Signer) error { 50 if key == nil { 51 return errors.New("private key cannot be nil when writing to file") 52 } 53 54 privateKeyPath := PathForKey(c.certPath, c.certName) 55 encoded, err := keyutil.MarshalPrivateKeyToPEM(key) 56 if err != nil { 57 return fmt.Errorf("unable to marshal private key to PEM %v", err) 58 } 59 if err := keyutil.WriteKey(privateKeyPath, encoded); err != nil { 60 return fmt.Errorf("unable to write private key to file %s %v", privateKeyPath, err) 61 } 62 63 return nil 64 } 65 66 func (c CertificateFileManger) writeCert(cert *x509.Certificate) error { 67 if cert == nil { 68 return errors.New("certificate cannot be nil when writing to file") 69 } 70 71 certificatePath := PathForCert(c.certPath, c.certName) 72 if err := certutil.WriteCert(certificatePath, EncodeCertPEM(cert)); err != nil { 73 return fmt.Errorf("unable to write certificate to file %s %v", certificatePath, err) 74 } 75 76 return nil 77 } 78 79 func (c CertificateFileManger) Read() (cert *x509.Certificate, key crypto.Signer, err error) { 80 key, err = c.readKey() 81 if err != nil { 82 return 83 } 84 85 cert, err = c.readCert() 86 if err != nil { 87 return 88 } 89 90 return 91 } 92 93 func (c CertificateFileManger) readKey() (crypto.Signer, error) { 94 // Parse the private key from a file 95 privateKey, err := keyutil.PrivateKeyFromFile(PathForKey(c.certPath, c.certName)) 96 if err != nil { 97 return nil, fmt.Errorf("couldn't load the private key file (%s): %v", privateKey, err) 98 } 99 100 // Allow RSA and ECDSA formats only 101 var key crypto.Signer 102 switch k := privateKey.(type) { 103 case *rsa.PrivateKey: 104 key = k 105 case *ecdsa.PrivateKey: 106 key = k 107 default: 108 return nil, fmt.Errorf("couldn't convert the private key file %v", err) 109 } 110 111 return key, nil 112 } 113 114 func (c CertificateFileManger) readCert() (cert *x509.Certificate, err error) { 115 certs, err := certutil.CertsFromFile(PathForCert(c.certPath, c.certName)) 116 if err != nil { 117 return nil, err 118 } 119 return certs[0], nil 120 } 121 122 func NewCertificateFileManger(certPath string, certName string) CertificateFileManger { 123 return CertificateFileManger{ 124 certName: certName, 125 certPath: certPath, 126 } 127 }