github.com/silveraid/fabric-ca@v1.1.0-preview.0.20180127000700-71974f53ab08/lib/util.go (about)

     1  /*
     2  Copyright IBM Corp. 2016 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 lib
    18  
    19  import (
    20  	"crypto/tls"
    21  	"crypto/x509"
    22  	"encoding/hex"
    23  	"encoding/json"
    24  	"encoding/pem"
    25  	"fmt"
    26  	"io/ioutil"
    27  	"net/http"
    28  	"strings"
    29  
    30  	"github.com/pkg/errors"
    31  
    32  	"github.com/cloudflare/cfssl/log"
    33  	"github.com/hyperledger/fabric-ca/api"
    34  	"github.com/hyperledger/fabric-ca/lib/spi"
    35  	"github.com/hyperledger/fabric-ca/util"
    36  	"github.com/spf13/viper"
    37  )
    38  
    39  var clientAuthTypes = map[string]tls.ClientAuthType{
    40  	"noclientcert":               tls.NoClientCert,
    41  	"requestclientcert":          tls.RequestClientCert,
    42  	"requireanyclientcert":       tls.RequireAnyClientCert,
    43  	"verifyclientcertifgiven":    tls.VerifyClientCertIfGiven,
    44  	"requireandverifyclientcert": tls.RequireAndVerifyClientCert,
    45  }
    46  
    47  // GetCertID returns both the serial number and AKI (Authority Key ID) for the certificate
    48  func GetCertID(bytes []byte) (string, string, error) {
    49  	cert, err := BytesToX509Cert(bytes)
    50  	if err != nil {
    51  		return "", "", err
    52  	}
    53  	serial := util.GetSerialAsHex(cert.SerialNumber)
    54  	aki := hex.EncodeToString(cert.AuthorityKeyId)
    55  	return serial, aki, nil
    56  }
    57  
    58  // BytesToX509Cert converts bytes (PEM or DER) to an X509 certificate
    59  func BytesToX509Cert(bytes []byte) (*x509.Certificate, error) {
    60  	dcert, _ := pem.Decode(bytes)
    61  	if dcert != nil {
    62  		bytes = dcert.Bytes
    63  	}
    64  	cert, err := x509.ParseCertificate(bytes)
    65  	if err != nil {
    66  		return nil, errors.Wrap(err, "Buffer was neither PEM nor DER encoding")
    67  	}
    68  	return cert, err
    69  }
    70  
    71  // LoadPEMCertPool loads a pool of PEM certificates from list of files
    72  func LoadPEMCertPool(certFiles []string) (*x509.CertPool, error) {
    73  	certPool := x509.NewCertPool()
    74  
    75  	if len(certFiles) > 0 {
    76  		for _, cert := range certFiles {
    77  			log.Debugf("Reading cert file: %s", cert)
    78  			pemCerts, err := ioutil.ReadFile(cert)
    79  			if err != nil {
    80  				return nil, err
    81  			}
    82  
    83  			log.Debugf("Appending cert %s to pool", cert)
    84  			if !certPool.AppendCertsFromPEM(pemCerts) {
    85  				return nil, errors.New("Failed to load cert pool")
    86  			}
    87  		}
    88  	}
    89  
    90  	return certPool, nil
    91  }
    92  
    93  // UnmarshalConfig unmarshals a configuration file
    94  func UnmarshalConfig(config interface{}, vp *viper.Viper, configFile string,
    95  	server bool) error {
    96  
    97  	vp.SetConfigFile(configFile)
    98  	err := vp.ReadInConfig()
    99  	if err != nil {
   100  		return errors.Wrapf(err, "Failed to read config file '%s'", configFile)
   101  	}
   102  
   103  	err = vp.Unmarshal(config)
   104  	if err != nil {
   105  		return errors.Wrapf(err, "Incorrect format in file '%s'", configFile)
   106  	}
   107  	if server {
   108  		serverCfg := config.(*ServerConfig)
   109  		err = vp.Unmarshal(&serverCfg.CAcfg)
   110  		if err != nil {
   111  			return errors.Wrapf(err, "Incorrect format in file '%s'", configFile)
   112  		}
   113  	}
   114  	return nil
   115  }
   116  
   117  func getMaxEnrollments(userMaxEnrollments int, caMaxEnrollments int) (int, error) {
   118  	log.Debugf("Max enrollment value verification - User specified max enrollment: %d, CA max enrollment: %d", userMaxEnrollments, caMaxEnrollments)
   119  	if userMaxEnrollments < -1 {
   120  		return 0, errors.Errorf("Max enrollment in registration request may not be less than -1, but was %d", userMaxEnrollments)
   121  	}
   122  	switch caMaxEnrollments {
   123  	case -1:
   124  		if userMaxEnrollments == 0 {
   125  			// The user is requesting the matching limit of the CA, so gets infinite
   126  			return caMaxEnrollments, nil
   127  		}
   128  		// There is no CA max enrollment limit, so simply use the user requested value
   129  		return userMaxEnrollments, nil
   130  	case 0:
   131  		// The CA max enrollment is 0, so registration is disabled.
   132  		return 0, errors.New("Registration is disabled")
   133  	default:
   134  		switch userMaxEnrollments {
   135  		case -1:
   136  			// User requested infinite enrollments is not allowed
   137  			return 0, errors.New("Registration for infinite enrollments is not allowed")
   138  		case 0:
   139  			// User is requesting the current CA maximum
   140  			return caMaxEnrollments, nil
   141  		default:
   142  			// User is requesting a specific positive value; make sure it doesn't exceed the CA maximum.
   143  			if userMaxEnrollments > caMaxEnrollments {
   144  				return 0, errors.Errorf("Requested enrollments (%d) exceeds maximum allowable enrollments (%d)",
   145  					userMaxEnrollments, caMaxEnrollments)
   146  			}
   147  			// otherwise, use the requested maximum
   148  			return userMaxEnrollments, nil
   149  		}
   150  	}
   151  }
   152  
   153  // GetUserAffiliation return a joined version version of the affiliation path with '.' as the seperator
   154  func GetUserAffiliation(user spi.User) string {
   155  	return strings.Join(user.GetAffiliationPath(), ".")
   156  }
   157  
   158  func addQueryParm(req *http.Request, name, value string) {
   159  	url := req.URL.Query()
   160  	url.Add(name, value)
   161  	req.URL.RawQuery = url.Encode()
   162  }
   163  
   164  // IdentityDecoder decodes streams of data coming from the server into an Identity object
   165  func IdentityDecoder(decoder *json.Decoder) error {
   166  	var id api.IdentityInfo
   167  	err := decoder.Decode(&id)
   168  	if err != nil {
   169  		return err
   170  	}
   171  	fmt.Printf("Name: %s, Type: %s, Affiliation: %s, Max Enrollments: %d, Attributes: %+v\n", id.ID, id.Type, id.Affiliation, id.MaxEnrollments, id.Attributes)
   172  	return nil
   173  }
   174  
   175  // AffiliationDecoder decodes streams of data coming from the server into an Affiliation object
   176  func AffiliationDecoder(decoder *json.Decoder) error {
   177  	var aff api.AffiliationInfo
   178  	err := decoder.Decode(&aff)
   179  	if err != nil {
   180  		return err
   181  	}
   182  	fmt.Printf("%s\n", aff.Name)
   183  	return nil
   184  }