github.com/defanghe/fabric@v2.1.1+incompatible/internal/cryptogen/msp/msp.go (about) 1 /* 2 Copyright IBM Corp. All Rights Reserved. 3 4 SPDX-License-Identifier: Apache-2.0 5 */ 6 package msp 7 8 import ( 9 "crypto/x509" 10 "encoding/pem" 11 "os" 12 "path/filepath" 13 14 "github.com/hyperledger/fabric/internal/cryptogen/ca" 15 "github.com/hyperledger/fabric/internal/cryptogen/csp" 16 fabricmsp "github.com/hyperledger/fabric/msp" 17 "github.com/pkg/errors" 18 "gopkg.in/yaml.v2" 19 ) 20 21 const ( 22 CLIENT = iota 23 ORDERER 24 PEER 25 ADMIN 26 ) 27 28 const ( 29 CLIENTOU = "client" 30 PEEROU = "peer" 31 ADMINOU = "admin" 32 ORDEREROU = "orderer" 33 ) 34 35 var nodeOUMap = map[int]string{ 36 CLIENT: CLIENTOU, 37 PEER: PEEROU, 38 ADMIN: ADMINOU, 39 ORDERER: ORDEREROU, 40 } 41 42 func GenerateLocalMSP( 43 baseDir, 44 name string, 45 sans []string, 46 signCA *ca.CA, 47 tlsCA *ca.CA, 48 nodeType int, 49 nodeOUs bool, 50 ) error { 51 52 // create folder structure 53 mspDir := filepath.Join(baseDir, "msp") 54 tlsDir := filepath.Join(baseDir, "tls") 55 56 err := createFolderStructure(mspDir, true) 57 if err != nil { 58 return err 59 } 60 61 err = os.MkdirAll(tlsDir, 0755) 62 if err != nil { 63 return err 64 } 65 66 /* 67 Create the MSP identity artifacts 68 */ 69 // get keystore path 70 keystore := filepath.Join(mspDir, "keystore") 71 72 // generate private key 73 priv, err := csp.GeneratePrivateKey(keystore) 74 if err != nil { 75 return err 76 } 77 78 // generate X509 certificate using signing CA 79 var ous []string 80 if nodeOUs { 81 ous = []string{nodeOUMap[nodeType]} 82 } 83 cert, err := signCA.SignCertificate( 84 filepath.Join(mspDir, "signcerts"), 85 name, 86 ous, 87 nil, 88 &priv.PublicKey, 89 x509.KeyUsageDigitalSignature, 90 []x509.ExtKeyUsage{}, 91 ) 92 if err != nil { 93 return err 94 } 95 96 // write artifacts to MSP folders 97 98 // the signing CA certificate goes into cacerts 99 err = x509Export( 100 filepath.Join(mspDir, "cacerts", x509Filename(signCA.Name)), 101 signCA.SignCert, 102 ) 103 if err != nil { 104 return err 105 } 106 // the TLS CA certificate goes into tlscacerts 107 err = x509Export( 108 filepath.Join(mspDir, "tlscacerts", x509Filename(tlsCA.Name)), 109 tlsCA.SignCert, 110 ) 111 if err != nil { 112 return err 113 } 114 115 // generate config.yaml if required 116 if nodeOUs { 117 118 exportConfig(mspDir, filepath.Join("cacerts", x509Filename(signCA.Name)), true) 119 } 120 121 // the signing identity goes into admincerts. 122 // This means that the signing identity 123 // of this MSP is also an admin of this MSP 124 // NOTE: the admincerts folder is going to be 125 // cleared up anyway by copyAdminCert, but 126 // we leave a valid admin for now for the sake 127 // of unit tests 128 if !nodeOUs { 129 err = x509Export(filepath.Join(mspDir, "admincerts", x509Filename(name)), cert) 130 if err != nil { 131 return err 132 } 133 } 134 135 /* 136 Generate the TLS artifacts in the TLS folder 137 */ 138 139 // generate private key 140 tlsPrivKey, err := csp.GeneratePrivateKey(tlsDir) 141 if err != nil { 142 return err 143 } 144 145 // generate X509 certificate using TLS CA 146 _, err = tlsCA.SignCertificate( 147 filepath.Join(tlsDir), 148 name, 149 nil, 150 sans, 151 &tlsPrivKey.PublicKey, 152 x509.KeyUsageDigitalSignature|x509.KeyUsageKeyEncipherment, 153 []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth, 154 x509.ExtKeyUsageClientAuth}, 155 ) 156 if err != nil { 157 return err 158 } 159 err = x509Export(filepath.Join(tlsDir, "ca.crt"), tlsCA.SignCert) 160 if err != nil { 161 return err 162 } 163 164 // rename the generated TLS X509 cert 165 tlsFilePrefix := "server" 166 if nodeType == CLIENT || nodeType == ADMIN { 167 tlsFilePrefix = "client" 168 } 169 err = os.Rename(filepath.Join(tlsDir, x509Filename(name)), 170 filepath.Join(tlsDir, tlsFilePrefix+".crt")) 171 if err != nil { 172 return err 173 } 174 175 err = keyExport(tlsDir, filepath.Join(tlsDir, tlsFilePrefix+".key")) 176 if err != nil { 177 return err 178 } 179 180 return nil 181 } 182 183 func GenerateVerifyingMSP( 184 baseDir string, 185 signCA, 186 tlsCA *ca.CA, 187 nodeOUs bool, 188 ) error { 189 190 // create folder structure and write artifacts to proper locations 191 err := createFolderStructure(baseDir, false) 192 if err != nil { 193 return err 194 } 195 // the signing CA certificate goes into cacerts 196 err = x509Export( 197 filepath.Join(baseDir, "cacerts", x509Filename(signCA.Name)), 198 signCA.SignCert, 199 ) 200 if err != nil { 201 return err 202 } 203 // the TLS CA certificate goes into tlscacerts 204 err = x509Export( 205 filepath.Join(baseDir, "tlscacerts", x509Filename(tlsCA.Name)), 206 tlsCA.SignCert, 207 ) 208 if err != nil { 209 return err 210 } 211 212 // generate config.yaml if required 213 if nodeOUs { 214 exportConfig(baseDir, "cacerts/"+x509Filename(signCA.Name), true) 215 } 216 217 // create a throwaway cert to act as an admin cert 218 // NOTE: the admincerts folder is going to be 219 // cleared up anyway by copyAdminCert, but 220 // we leave a valid admin for now for the sake 221 // of unit tests 222 if nodeOUs { 223 return nil 224 } 225 226 ksDir := filepath.Join(baseDir, "keystore") 227 err = os.Mkdir(ksDir, 0755) 228 defer os.RemoveAll(ksDir) 229 if err != nil { 230 return errors.WithMessage(err, "failed to create keystore directory") 231 } 232 priv, err := csp.GeneratePrivateKey(ksDir) 233 if err != nil { 234 return err 235 } 236 _, err = signCA.SignCertificate( 237 filepath.Join(baseDir, "admincerts"), 238 signCA.Name, 239 nil, 240 nil, 241 &priv.PublicKey, 242 x509.KeyUsageDigitalSignature, 243 []x509.ExtKeyUsage{}, 244 ) 245 if err != nil { 246 return err 247 } 248 249 return nil 250 } 251 252 func createFolderStructure(rootDir string, local bool) error { 253 254 var folders []string 255 // create admincerts, cacerts, keystore and signcerts folders 256 folders = []string{ 257 filepath.Join(rootDir, "admincerts"), 258 filepath.Join(rootDir, "cacerts"), 259 filepath.Join(rootDir, "tlscacerts"), 260 } 261 if local { 262 folders = append(folders, filepath.Join(rootDir, "keystore"), 263 filepath.Join(rootDir, "signcerts")) 264 } 265 266 for _, folder := range folders { 267 err := os.MkdirAll(folder, 0755) 268 if err != nil { 269 return err 270 } 271 } 272 273 return nil 274 } 275 276 func x509Filename(name string) string { 277 return name + "-cert.pem" 278 } 279 280 func x509Export(path string, cert *x509.Certificate) error { 281 return pemExport(path, "CERTIFICATE", cert.Raw) 282 } 283 284 func keyExport(keystore, output string) error { 285 return os.Rename(filepath.Join(keystore, "priv_sk"), output) 286 } 287 288 func pemExport(path, pemType string, bytes []byte) error { 289 //write pem out to file 290 file, err := os.Create(path) 291 if err != nil { 292 return err 293 } 294 defer file.Close() 295 296 return pem.Encode(file, &pem.Block{Type: pemType, Bytes: bytes}) 297 } 298 299 func exportConfig(mspDir, caFile string, enable bool) error { 300 var config = &fabricmsp.Configuration{ 301 NodeOUs: &fabricmsp.NodeOUs{ 302 Enable: enable, 303 ClientOUIdentifier: &fabricmsp.OrganizationalUnitIdentifiersConfiguration{ 304 Certificate: caFile, 305 OrganizationalUnitIdentifier: CLIENTOU, 306 }, 307 PeerOUIdentifier: &fabricmsp.OrganizationalUnitIdentifiersConfiguration{ 308 Certificate: caFile, 309 OrganizationalUnitIdentifier: PEEROU, 310 }, 311 AdminOUIdentifier: &fabricmsp.OrganizationalUnitIdentifiersConfiguration{ 312 Certificate: caFile, 313 OrganizationalUnitIdentifier: ADMINOU, 314 }, 315 OrdererOUIdentifier: &fabricmsp.OrganizationalUnitIdentifiersConfiguration{ 316 Certificate: caFile, 317 OrganizationalUnitIdentifier: ORDEREROU, 318 }, 319 }, 320 } 321 322 configBytes, err := yaml.Marshal(config) 323 if err != nil { 324 return err 325 } 326 327 file, err := os.Create(filepath.Join(mspDir, "config.yaml")) 328 if err != nil { 329 return err 330 } 331 332 defer file.Close() 333 _, err = file.WriteString(string(configBytes)) 334 335 return err 336 }