github.com/IBM-Blockchain/fabric-operator@v1.0.4/pkg/initializer/ca/tls/tls.go (about) 1 /* 2 * Copyright contributors to the Hyperledger Fabric Operator project 3 * 4 * SPDX-License-Identifier: Apache-2.0 5 * 6 * Licensed under the Apache License, Version 2.0 (the "License"); 7 * you may not use this file except in compliance with the License. 8 * You may obtain a copy of the License at: 9 * 10 * http://www.apache.org/licenses/LICENSE-2.0 11 * 12 * Unless required by applicable law or agreed to in writing, software 13 * distributed under the License is distributed on an "AS IS" BASIS, 14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 * See the License for the specific language governing permissions and 16 * limitations under the License. 17 */ 18 19 package tls 20 21 import ( 22 "crypto/ecdsa" 23 "crypto/rand" 24 "crypto/x509" 25 "crypto/x509/pkix" 26 "encoding/pem" 27 "math/big" 28 "net" 29 "os" 30 "path/filepath" 31 "time" 32 33 "github.com/IBM-Blockchain/fabric-operator/pkg/util" 34 "github.com/cloudflare/cfssl/csr" 35 "github.com/hyperledger/fabric-ca/api" 36 cautil "github.com/hyperledger/fabric-ca/util" 37 "github.com/hyperledger/fabric/bccsp/factory" 38 ) 39 40 type TLS struct { 41 CAHomeDir string 42 CSP *factory.FactoryOpts 43 } 44 45 func (t *TLS) GenerateSelfSignedTLSCrypto(csr *api.CSRInfo) ([]byte, error) { 46 err := os.RemoveAll(filepath.Join(t.CAHomeDir, "tls")) 47 if err != nil { 48 return nil, err 49 } 50 51 csp, err := cautil.InitBCCSP(&t.CSP, "msp", filepath.Join(t.CAHomeDir, "tls")) 52 if err != nil { 53 return nil, err 54 } 55 56 cr := NewCertificateRequest(csr) 57 privKey, signer, err := cautil.BCCSPKeyRequestGenerate(cr, csp) 58 if err != nil { 59 return nil, err 60 } 61 62 notBefore := time.Now() 63 notBefore.Add(-5 * time.Minute) 64 notAfter := notBefore.Add(time.Hour * 24 * 365) // Valid for one year 65 66 serialNumberLimit := new(big.Int).Lsh(big.NewInt(1), 128) 67 serialNumber, err := rand.Int(rand.Reader, serialNumberLimit) 68 if err != nil { 69 return nil, err 70 } 71 72 subject := pkix.Name{ 73 CommonName: csr.CN, 74 SerialNumber: csr.SerialNumber, 75 } 76 if len(csr.Names) != 0 { 77 for _, name := range csr.Names { 78 subject.Country = append(subject.Country, name.C) 79 subject.Province = append(subject.Province, name.ST) 80 subject.Locality = append(subject.Locality, name.L) 81 subject.Organization = append(subject.Organization, name.O) 82 subject.OrganizationalUnit = append(subject.OrganizationalUnit, name.OU) 83 } 84 } 85 86 template := x509.Certificate{ 87 SerialNumber: serialNumber, 88 Subject: subject, 89 NotBefore: notBefore, 90 NotAfter: notAfter, 91 92 KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature, 93 ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth}, 94 BasicConstraintsValid: true, 95 } 96 97 for _, h := range csr.Hosts { 98 ip := net.ParseIP(h) 99 if ip != nil { 100 template.IPAddresses = append(template.IPAddresses, ip) 101 } else { 102 template.DNSNames = append(template.DNSNames, h) 103 } 104 } 105 106 pubKey, err := privKey.PublicKey() 107 if err != nil { 108 return nil, err 109 } 110 pubKeyBytes, err := pubKey.Bytes() 111 if err != nil { 112 return nil, err 113 } 114 pub, err := x509.ParsePKIXPublicKey(pubKeyBytes) 115 if err != nil { 116 return nil, err 117 } 118 ecdsaPubKey := pub.(*ecdsa.PublicKey) 119 120 certBytes, err := x509.CreateCertificate(rand.Reader, &template, &template, ecdsaPubKey, signer) 121 if err != nil { 122 return nil, err 123 } 124 125 return certBytes, nil 126 } 127 128 func (t *TLS) WriteCryptoToFile(cert []byte, certName string) error { 129 certPath := filepath.Join(t.CAHomeDir, "tls", certName) 130 err := util.EnsureDir(filepath.Dir(certPath)) 131 if err != nil { 132 return err 133 } 134 135 certOut, err := os.Create(filepath.Clean(certPath)) 136 if err != nil { 137 return err 138 } 139 err = pem.Encode(certOut, &pem.Block{Type: "CERTIFICATE", Bytes: cert}) 140 if err != nil { 141 return err 142 } 143 err = certOut.Close() 144 if err != nil { 145 return err 146 } 147 148 return nil 149 } 150 151 func NewCertificateRequest(req *api.CSRInfo) *csr.CertificateRequest { 152 cr := csr.CertificateRequest{} 153 if req != nil && req.Names != nil { 154 cr.Names = req.Names 155 } 156 if req != nil && req.Hosts != nil { 157 cr.Hosts = req.Hosts 158 } else { 159 // Default requested hosts are local hostname 160 hostname, err := os.Hostname() 161 if err == nil && hostname != "" { 162 cr.Hosts = make([]string, 1) 163 cr.Hosts[0] = hostname 164 } 165 } 166 if req != nil && req.KeyRequest != nil { 167 cr.KeyRequest = newCfsslKeyRequest(req.KeyRequest) 168 } 169 if req != nil { 170 cr.CA = req.CA 171 cr.SerialNumber = req.SerialNumber 172 } 173 return &cr 174 } 175 176 func newCfsslKeyRequest(bkr *api.KeyRequest) *csr.KeyRequest { 177 return &csr.KeyRequest{A: bkr.Algo, S: bkr.Size} 178 }