github.com/silveraid/fabric-ca@v1.1.0-preview.0.20180127000700-71974f53ab08/cmd/fabric-ca-client/gencrl.go (about)

     1  /*
     2  Copyright IBM Corp. 2017 All Rights Reserved.
     3  Licensed under the Apache License, Version 2.0 (the "License");
     4  you may not use this file except in compliance with the License.
     5  You may obtain a copy of the License at
     6                   http://www.apache.org/licenses/LICENSE-2.0
     7  Unless required by applicable law or agreed to in writing, software
     8  distributed under the License is distributed on an "AS IS" BASIS,
     9  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    10  See the License for the specific language governing permissions and
    11  limitations under the License.
    12  */
    13  package main
    14  
    15  import (
    16  	"os"
    17  	"path"
    18  	"path/filepath"
    19  	"time"
    20  
    21  	"github.com/cloudflare/cfssl/log"
    22  	"github.com/hyperledger/fabric-ca/api"
    23  	"github.com/hyperledger/fabric-ca/lib"
    24  	"github.com/hyperledger/fabric-ca/util"
    25  	"github.com/pkg/errors"
    26  	"github.com/spf13/cobra"
    27  )
    28  
    29  const (
    30  	// crlsFolder is the MSP folder name where generate CRL will be stored
    31  	crlsFolder = "crls"
    32  	// crlFile is the name of the file used to the generate CRL
    33  	crlFile = "crl.pem"
    34  )
    35  
    36  func (c *ClientCmd) newGenCRLCommand() *cobra.Command {
    37  	var genCrlCmd = &cobra.Command{
    38  		Use:   "gencrl",
    39  		Short: "Generate a CRL",
    40  		Long:  "Generate a Certificate Revocation List",
    41  		// PreRunE block for this command will load client configuration
    42  		// before running the command
    43  		PreRunE: func(cmd *cobra.Command, args []string) error {
    44  			if len(args) > 0 {
    45  				return errors.Errorf(extraArgsError, args, cmd.UsageString())
    46  			}
    47  			err := c.configInit()
    48  			if err != nil {
    49  				return err
    50  			}
    51  			log.Debugf("Client configuration settings: %+v", c.clientCfg)
    52  			return nil
    53  		},
    54  		RunE: func(cmd *cobra.Command, args []string) error {
    55  			err := c.runGenCRL()
    56  			if err != nil {
    57  				return err
    58  			}
    59  			return nil
    60  		},
    61  	}
    62  	util.RegisterFlags(c.myViper, genCrlCmd.Flags(), &c.crlParams, nil)
    63  	return genCrlCmd
    64  }
    65  
    66  // The client register main logic
    67  func (c *ClientCmd) runGenCRL() error {
    68  	log.Debug("Entered runGenCRL")
    69  	client := lib.Client{
    70  		HomeDir: filepath.Dir(c.cfgFileName),
    71  		Config:  c.clientCfg,
    72  	}
    73  	id, err := client.LoadMyIdentity()
    74  	if err != nil {
    75  		return err
    76  	}
    77  	var revokedAfter, revokedBefore time.Time
    78  	if c.crlParams.RevokedAfter != "" {
    79  		revokedAfter, err = time.Parse(time.RFC3339, c.crlParams.RevokedAfter)
    80  		if err != nil {
    81  			return errors.Wrap(err, "Invalid 'revokedafter' value")
    82  		}
    83  	}
    84  	if c.crlParams.RevokedBefore != "" {
    85  		revokedBefore, err = time.Parse(time.RFC3339, c.crlParams.RevokedBefore)
    86  		if err != nil {
    87  			return errors.Wrap(err, "Invalid 'revokedbefore' value")
    88  		}
    89  	}
    90  	if !revokedBefore.IsZero() && revokedAfter.After(revokedBefore) {
    91  		return errors.Errorf("Invalid revokedafter value '%s'. It must not be a timestamp greater than revokedbefore value '%s'",
    92  			c.crlParams.RevokedAfter, c.crlParams.RevokedBefore)
    93  	}
    94  
    95  	var expireAfter, expireBefore time.Time
    96  	if c.crlParams.ExpireAfter != "" {
    97  		expireAfter, err = time.Parse(time.RFC3339, c.crlParams.ExpireAfter)
    98  		if err != nil {
    99  			return errors.Wrap(err, "Invalid 'expireafter' value")
   100  		}
   101  	}
   102  	if c.crlParams.ExpireBefore != "" {
   103  		expireBefore, err = time.Parse(time.RFC3339, c.crlParams.ExpireBefore)
   104  		if err != nil {
   105  			return errors.Wrap(err, "Invalid 'expirebefore' value")
   106  		}
   107  	}
   108  	if !expireBefore.IsZero() && expireAfter.After(expireBefore) {
   109  		return errors.Errorf("Invalid expireafter value '%s'. It must not be a timestamp greater than expirebefore value '%s'",
   110  			c.crlParams.ExpireAfter, c.crlParams.ExpireBefore)
   111  	}
   112  	req := &api.GenCRLRequest{
   113  		CAName:        c.clientCfg.CAName,
   114  		RevokedAfter:  revokedAfter,
   115  		RevokedBefore: revokedBefore,
   116  		ExpireAfter:   expireAfter,
   117  		ExpireBefore:  expireBefore,
   118  	}
   119  	resp, err := id.GenCRL(req)
   120  	if err != nil {
   121  		return err
   122  	}
   123  	log.Info("Successfully generated the CRL")
   124  	err = storeCRL(c.clientCfg, resp.CRL)
   125  	if err != nil {
   126  		return err
   127  	}
   128  	return nil
   129  }
   130  
   131  // Store the CRL
   132  func storeCRL(config *lib.ClientConfig, crl []byte) error {
   133  	dirName := path.Join(config.MSPDir, crlsFolder)
   134  	if _, err := os.Stat(dirName); os.IsNotExist(err) {
   135  		mkdirErr := os.MkdirAll(dirName, os.ModeDir|0755)
   136  		if mkdirErr != nil {
   137  			return errors.Wrapf(mkdirErr, "Failed to create directory %s", dirName)
   138  		}
   139  	}
   140  	fileName := path.Join(dirName, crlFile)
   141  	err := util.WriteFile(fileName, crl, 0644)
   142  	if err != nil {
   143  		return errors.Wrapf(err, "Failed to write CRL to the file %s", fileName)
   144  	}
   145  	log.Info("Successfully stored the CRL in the file %s", fileName)
   146  	return nil
   147  }