github.com/darrenli6/fabric-sdk-example@v0.0.0-20220109053535-94b13b56df8c/msp/configbuilder.go (about)

     1  /*
     2  Copyright IBM Corp. 2017 All Rights Reserved.
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8  		 http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  package msp
    18  
    19  import (
    20  	"fmt"
    21  	"io/ioutil"
    22  
    23  	"github.com/golang/protobuf/proto"
    24  
    25  	"encoding/pem"
    26  	"path/filepath"
    27  
    28  	"os"
    29  
    30  	"github.com/hyperledger/fabric/bccsp"
    31  	"github.com/hyperledger/fabric/bccsp/factory"
    32  	"github.com/hyperledger/fabric/protos/msp"
    33  	"gopkg.in/yaml.v2"
    34  )
    35  
    36  type OrganizationalUnitIdentifiersConfiguration struct {
    37  	Certificate                  string `yaml:"Certificate,omitempty"`
    38  	OrganizationalUnitIdentifier string `yaml:"OrganizationalUnitIdentifier,omitempty"`
    39  }
    40  
    41  type Configuration struct {
    42  	OrganizationalUnitIdentifiers []*OrganizationalUnitIdentifiersConfiguration `yaml:"OrganizationalUnitIdentifiers,omitempty"`
    43  }
    44  
    45  func readFile(file string) ([]byte, error) {
    46  	fileCont, err := ioutil.ReadFile(file)
    47  	if err != nil {
    48  		return nil, fmt.Errorf("Could not read file %s, err %s", file, err)
    49  	}
    50  
    51  	return fileCont, nil
    52  }
    53  
    54  func readPemFile(file string) ([]byte, error) {
    55  	bytes, err := readFile(file)
    56  	if err != nil {
    57  		return nil, err
    58  	}
    59  
    60  	b, _ := pem.Decode(bytes)
    61  	if b == nil { // TODO: also check that the type is what we expect (cert vs key..)
    62  		return nil, fmt.Errorf("No pem content for file %s", file)
    63  	}
    64  
    65  	return bytes, nil
    66  }
    67  
    68  func getPemMaterialFromDir(dir string) ([][]byte, error) {
    69  	mspLogger.Debugf("Reading directory %s", dir)
    70  
    71  	_, err := os.Stat(dir)
    72  	if os.IsNotExist(err) {
    73  		return nil, err
    74  	}
    75  
    76  	content := make([][]byte, 0)
    77  	files, err := ioutil.ReadDir(dir)
    78  	if err != nil {
    79  		return nil, fmt.Errorf("Could not read directory %s, err %s", err, dir)
    80  	}
    81  
    82  	for _, f := range files {
    83  		if f.IsDir() {
    84  			continue
    85  		}
    86  
    87  		fullName := filepath.Join(dir, string(filepath.Separator), f.Name())
    88  		mspLogger.Debugf("Inspecting file %s", fullName)
    89  
    90  		item, err := readPemFile(fullName)
    91  		if err != nil {
    92  			mspLogger.Warningf("Failed readgin file %s: %s", fullName, err)
    93  			continue
    94  		}
    95  
    96  		content = append(content, item)
    97  	}
    98  
    99  	return content, nil
   100  }
   101  
   102  const (
   103  	cacerts              = "cacerts"
   104  	admincerts           = "admincerts"
   105  	signcerts            = "signcerts"
   106  	keystore             = "keystore"
   107  	intermediatecerts    = "intermediatecerts"
   108  	crlsfolder           = "crls"
   109  	configfilename       = "config.yaml"
   110  	tlscacerts           = "tlscacerts"
   111  	tlsintermediatecerts = "tlsintermediatecerts"
   112  )
   113  
   114  func SetupBCCSPKeystoreConfig(bccspConfig *factory.FactoryOpts, keystoreDir string) *factory.FactoryOpts {
   115  	if bccspConfig == nil {
   116  		bccspConfig = factory.GetDefaultOpts()
   117  	}
   118  
   119  	if bccspConfig.ProviderName == "SW" {
   120  		if bccspConfig.SwOpts == nil {
   121  			bccspConfig.SwOpts = factory.GetDefaultOpts().SwOpts
   122  		}
   123  
   124  		// Only override the KeyStorePath if it was left empty
   125  		if bccspConfig.SwOpts.FileKeystore == nil ||
   126  			bccspConfig.SwOpts.FileKeystore.KeyStorePath == "" {
   127  			bccspConfig.SwOpts.Ephemeral = false
   128  			bccspConfig.SwOpts.FileKeystore = &factory.FileKeystoreOpts{KeyStorePath: keystoreDir}
   129  		}
   130  	}
   131  
   132  	return bccspConfig
   133  }
   134  
   135  func GetLocalMspConfig(dir string, bccspConfig *factory.FactoryOpts, ID string) (*msp.MSPConfig, error) {
   136  	signcertDir := filepath.Join(dir, signcerts)
   137  	keystoreDir := filepath.Join(dir, keystore)
   138  	bccspConfig = SetupBCCSPKeystoreConfig(bccspConfig, keystoreDir)
   139  
   140  	err := factory.InitFactories(bccspConfig)
   141  	if err != nil {
   142  		return nil, fmt.Errorf("Could not initialize BCCSP Factories [%s]", err)
   143  	}
   144  
   145  	signcert, err := getPemMaterialFromDir(signcertDir)
   146  	if err != nil || len(signcert) == 0 {
   147  		return nil, fmt.Errorf("Could not load a valid signer certificate from directory %s, err %s", signcertDir, err)
   148  	}
   149  
   150  	/* FIXME: for now we're making the following assumptions
   151  	1) there is exactly one signing cert
   152  	2) BCCSP's KeyStore has the private key that matches SKI of
   153  	   signing cert
   154  	*/
   155  
   156  	sigid := &msp.SigningIdentityInfo{PublicSigner: signcert[0], PrivateSigner: nil}
   157  
   158  	return getMspConfig(dir, ID, sigid)
   159  }
   160  
   161  func GetVerifyingMspConfig(dir string, ID string) (*msp.MSPConfig, error) {
   162  	return getMspConfig(dir, ID, nil)
   163  }
   164  
   165  func getMspConfig(dir string, ID string, sigid *msp.SigningIdentityInfo) (*msp.MSPConfig, error) {
   166  	cacertDir := filepath.Join(dir, cacerts)
   167  	admincertDir := filepath.Join(dir, admincerts)
   168  	intermediatecertsDir := filepath.Join(dir, intermediatecerts)
   169  	crlsDir := filepath.Join(dir, crlsfolder)
   170  	configFile := filepath.Join(dir, configfilename)
   171  	tlscacertDir := filepath.Join(dir, tlscacerts)
   172  	tlsintermediatecertsDir := filepath.Join(dir, tlsintermediatecerts)
   173  
   174  	cacerts, err := getPemMaterialFromDir(cacertDir)
   175  	if err != nil || len(cacerts) == 0 {
   176  		return nil, fmt.Errorf("Could not load a valid ca certificate from directory %s, err %s", cacertDir, err)
   177  	}
   178  
   179  	admincert, err := getPemMaterialFromDir(admincertDir)
   180  	if err != nil || len(admincert) == 0 {
   181  		return nil, fmt.Errorf("Could not load a valid admin certificate from directory %s, err %s", admincertDir, err)
   182  	}
   183  
   184  	intermediatecerts, err := getPemMaterialFromDir(intermediatecertsDir)
   185  	if os.IsNotExist(err) {
   186  		mspLogger.Debugf("Intermediate certs folder not found at [%s]. Skipping. [%s]", intermediatecertsDir, err)
   187  	} else if err != nil {
   188  		return nil, fmt.Errorf("Failed loading intermediate ca certs at [%s]: [%s]", intermediatecertsDir, err)
   189  	}
   190  
   191  	tlsCACerts, err := getPemMaterialFromDir(tlscacertDir)
   192  	tlsIntermediateCerts := [][]byte{}
   193  	if os.IsNotExist(err) {
   194  		mspLogger.Debugf("TLS CA certs folder not found at [%s]. Skipping and ignoring TLS intermediate CA folder. [%s]", tlsintermediatecertsDir, err)
   195  	} else if err != nil {
   196  		return nil, fmt.Errorf("Failed loading TLS ca certs at [%s]: [%s]", tlsintermediatecertsDir, err)
   197  	} else if len(tlsCACerts) != 0 {
   198  		tlsIntermediateCerts, err = getPemMaterialFromDir(tlsintermediatecertsDir)
   199  		if os.IsNotExist(err) {
   200  			mspLogger.Debugf("TLS intermediate certs folder not found at [%s]. Skipping. [%s]", tlsintermediatecertsDir, err)
   201  		} else if err != nil {
   202  			return nil, fmt.Errorf("Failed loading TLS intermediate ca certs at [%s]: [%s]", tlsintermediatecertsDir, err)
   203  		}
   204  	} else {
   205  		mspLogger.Debugf("TLS CA certs folder at [%s] is empty. Skipping.", tlsintermediatecertsDir)
   206  	}
   207  
   208  	crls, err := getPemMaterialFromDir(crlsDir)
   209  	if os.IsNotExist(err) {
   210  		mspLogger.Debugf("crls folder not found at [%s]. Skipping. [%s]", crlsDir, err)
   211  	} else if err != nil {
   212  		return nil, fmt.Errorf("Failed loading crls at [%s]: [%s]", crlsDir, err)
   213  	}
   214  
   215  	// Load configuration file
   216  	// if the configuration file is there then load it
   217  	// otherwise skip it
   218  	var ouis []*msp.FabricOUIdentifier
   219  	_, err = os.Stat(configFile)
   220  	if err == nil {
   221  		// load the file, if there is a failure in loading it then
   222  		// return an error
   223  		raw, err := ioutil.ReadFile(configFile)
   224  		if err != nil {
   225  			return nil, fmt.Errorf("Failed loading configuration file at [%s]: [%s]", configFile, err)
   226  		}
   227  
   228  		configuration := Configuration{}
   229  		err = yaml.Unmarshal(raw, &configuration)
   230  		if err != nil {
   231  			return nil, fmt.Errorf("Failed unmarshalling configuration file at [%s]: [%s]", configFile, err)
   232  		}
   233  
   234  		// Prepare OrganizationalUnitIdentifiers
   235  		if len(configuration.OrganizationalUnitIdentifiers) > 0 {
   236  			for _, ouID := range configuration.OrganizationalUnitIdentifiers {
   237  				f := filepath.Join(dir, ouID.Certificate)
   238  				raw, err = ioutil.ReadFile(f)
   239  				if err != nil {
   240  					return nil, fmt.Errorf("Failed loading OrganizationalUnit certificate at [%s]: [%s]", f, err)
   241  				}
   242  				oui := &msp.FabricOUIdentifier{
   243  					Certificate:                  raw,
   244  					OrganizationalUnitIdentifier: ouID.OrganizationalUnitIdentifier,
   245  				}
   246  				ouis = append(ouis, oui)
   247  			}
   248  		}
   249  	} else {
   250  		mspLogger.Debugf("MSP configuration file not found at [%s]: [%s]", configFile, err)
   251  	}
   252  
   253  	// Set FabricCryptoConfig
   254  	cryptoConfig := &msp.FabricCryptoConfig{
   255  		SignatureHashFamily:            bccsp.SHA2,
   256  		IdentityIdentifierHashFunction: bccsp.SHA256,
   257  	}
   258  
   259  	// Compose FabricMSPConfig
   260  	fmspconf := &msp.FabricMSPConfig{
   261  		Admins:            admincert,
   262  		RootCerts:         cacerts,
   263  		IntermediateCerts: intermediatecerts,
   264  		SigningIdentity:   sigid,
   265  		Name:              ID,
   266  		OrganizationalUnitIdentifiers: ouis,
   267  		RevocationList:                crls,
   268  		CryptoConfig:                  cryptoConfig,
   269  		TlsRootCerts:                  tlsCACerts,
   270  		TlsIntermediateCerts:          tlsIntermediateCerts,
   271  	}
   272  
   273  	fmpsjs, _ := proto.Marshal(fmspconf)
   274  
   275  	mspconf := &msp.MSPConfig{Config: fmpsjs, Type: int32(FABRIC)}
   276  
   277  	return mspconf, nil
   278  }