github.com/tenywen/fabric@v1.0.0-beta.0.20170620030522-a5b1ed380643/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  )
   111  
   112  func SetupBCCSPKeystoreConfig(bccspConfig *factory.FactoryOpts, keystoreDir string) *factory.FactoryOpts {
   113  	if bccspConfig == nil {
   114  		bccspConfig = factory.GetDefaultOpts()
   115  	}
   116  
   117  	if bccspConfig.ProviderName == "SW" {
   118  		if bccspConfig.SwOpts == nil {
   119  			bccspConfig.SwOpts = factory.GetDefaultOpts().SwOpts
   120  		}
   121  
   122  		// Only override the KeyStorePath if it was left empty
   123  		if bccspConfig.SwOpts.FileKeystore == nil ||
   124  			bccspConfig.SwOpts.FileKeystore.KeyStorePath == "" {
   125  			bccspConfig.SwOpts.Ephemeral = false
   126  			bccspConfig.SwOpts.FileKeystore = &factory.FileKeystoreOpts{KeyStorePath: keystoreDir}
   127  		}
   128  	}
   129  
   130  	return bccspConfig
   131  }
   132  
   133  func GetLocalMspConfig(dir string, bccspConfig *factory.FactoryOpts, ID string) (*msp.MSPConfig, error) {
   134  	signcertDir := filepath.Join(dir, signcerts)
   135  	keystoreDir := filepath.Join(dir, keystore)
   136  	bccspConfig = SetupBCCSPKeystoreConfig(bccspConfig, keystoreDir)
   137  
   138  	err := factory.InitFactories(bccspConfig)
   139  	if err != nil {
   140  		return nil, fmt.Errorf("Could not initialize BCCSP Factories [%s]", err)
   141  	}
   142  
   143  	signcert, err := getPemMaterialFromDir(signcertDir)
   144  	if err != nil || len(signcert) == 0 {
   145  		return nil, fmt.Errorf("Could not load a valid signer certificate from directory %s, err %s", signcertDir, err)
   146  	}
   147  
   148  	/* FIXME: for now we're making the following assumptions
   149  	1) there is exactly one signing cert
   150  	2) BCCSP's KeyStore has the private key that matches SKI of
   151  	   signing cert
   152  	*/
   153  
   154  	sigid := &msp.SigningIdentityInfo{PublicSigner: signcert[0], PrivateSigner: nil}
   155  
   156  	return getMspConfig(dir, ID, sigid)
   157  }
   158  
   159  func GetVerifyingMspConfig(dir string, ID string) (*msp.MSPConfig, error) {
   160  	return getMspConfig(dir, ID, nil)
   161  }
   162  
   163  func getMspConfig(dir string, ID string, sigid *msp.SigningIdentityInfo) (*msp.MSPConfig, error) {
   164  	cacertDir := filepath.Join(dir, cacerts)
   165  	admincertDir := filepath.Join(dir, admincerts)
   166  	intermediatecertsDir := filepath.Join(dir, intermediatecerts)
   167  	crlsDir := filepath.Join(dir, crlsfolder)
   168  	configFile := filepath.Join(dir, configfilename)
   169  
   170  	cacerts, err := getPemMaterialFromDir(cacertDir)
   171  	if err != nil || len(cacerts) == 0 {
   172  		return nil, fmt.Errorf("Could not load a valid ca certificate from directory %s, err %s", cacertDir, err)
   173  	}
   174  
   175  	admincert, err := getPemMaterialFromDir(admincertDir)
   176  	if err != nil || len(admincert) == 0 {
   177  		return nil, fmt.Errorf("Could not load a valid admin certificate from directory %s, err %s", admincertDir, err)
   178  	}
   179  
   180  	intermediatecert, err := getPemMaterialFromDir(intermediatecertsDir)
   181  	if os.IsNotExist(err) {
   182  		mspLogger.Infof("intermediate certs folder not found at [%s]. Skipping.: [%s]", intermediatecertsDir, err)
   183  	} else if err != nil {
   184  		return nil, fmt.Errorf("Failed loading intermediate ca certs at [%s]: [%s]", intermediatecertsDir, err)
   185  	}
   186  
   187  	crls, err := getPemMaterialFromDir(crlsDir)
   188  	if os.IsNotExist(err) {
   189  		mspLogger.Infof("crls folder not found at [%s]. Skipping.: [%s]", intermediatecertsDir, err)
   190  	} else if err != nil {
   191  		return nil, fmt.Errorf("Failed loading crls ca certs at [%s]: [%s]", intermediatecertsDir, err)
   192  	}
   193  
   194  	// Load configuration file
   195  	// if the configuration file is there then load it
   196  	// otherwise skip it
   197  	var ouis []*msp.FabricOUIdentifier
   198  	_, err = os.Stat(configFile)
   199  	if err == nil {
   200  		// load the file, if there is a failure in loading it then
   201  		// return an error
   202  		raw, err := ioutil.ReadFile(configFile)
   203  		if err != nil {
   204  			return nil, fmt.Errorf("Failed loading configuration file at [%s]: [%s]", configFile, err)
   205  		}
   206  
   207  		configuration := Configuration{}
   208  		err = yaml.Unmarshal(raw, &configuration)
   209  		if err != nil {
   210  			return nil, fmt.Errorf("Failed unmarshalling configuration file at [%s]: [%s]", configFile, err)
   211  		}
   212  
   213  		// Prepare OrganizationalUnitIdentifiers
   214  		if len(configuration.OrganizationalUnitIdentifiers) > 0 {
   215  			for _, ouID := range configuration.OrganizationalUnitIdentifiers {
   216  				f := filepath.Join(dir, ouID.Certificate)
   217  				raw, err = ioutil.ReadFile(f)
   218  				if err != nil {
   219  					return nil, fmt.Errorf("Failed loading OrganizationalUnit certificate at [%s]: [%s]", f, err)
   220  				}
   221  				oui := &msp.FabricOUIdentifier{
   222  					Certificate:                  raw,
   223  					OrganizationalUnitIdentifier: ouID.OrganizationalUnitIdentifier,
   224  				}
   225  				ouis = append(ouis, oui)
   226  			}
   227  		}
   228  	} else {
   229  		mspLogger.Infof("MSP configuration file not found at [%s]: [%s]", configFile, err)
   230  	}
   231  
   232  	// Set FabricCryptoConfig
   233  	cryptoConfig := &msp.FabricCryptoConfig{
   234  		SignatureHashFamily:            bccsp.SHA2,
   235  		IdentityIdentifierHashFunction: bccsp.SHA256,
   236  	}
   237  
   238  	// Compose FabricMSPConfig
   239  	fmspconf := &msp.FabricMSPConfig{
   240  		Admins:            admincert,
   241  		RootCerts:         cacerts,
   242  		IntermediateCerts: intermediatecert,
   243  		SigningIdentity:   sigid,
   244  		Name:              ID,
   245  		OrganizationalUnitIdentifiers: ouis,
   246  		RevocationList:                crls,
   247  		CryptoConfig:                  cryptoConfig}
   248  
   249  	fmpsjs, _ := proto.Marshal(fmspconf)
   250  
   251  	mspconf := &msp.MSPConfig{Config: fmpsjs, Type: int32(FABRIC)}
   252  
   253  	return mspconf, nil
   254  }