github.com/canhui/fabric_ca2_2@v2.0.0-alpha+incompatible/lib/client/credential/x509/credential_test.go (about)

     1  /*
     2  Copyright IBM Corp. All Rights Reserved.
     3  
     4  SPDX-License-Identifier: Apache-2.0
     5  */
     6  
     7  package x509_test
     8  
     9  import (
    10  	"bytes"
    11  	"crypto/x509"
    12  	"encoding/hex"
    13  	"fmt"
    14  	"io/ioutil"
    15  	"net/http"
    16  	"os"
    17  	"path/filepath"
    18  	"testing"
    19  
    20  	"github.com/hyperledger/fabric-ca/api"
    21  	"github.com/hyperledger/fabric-ca/lib"
    22  	"github.com/hyperledger/fabric-ca/lib/client/credential"
    23  	. "github.com/hyperledger/fabric-ca/lib/client/credential/x509"
    24  	"github.com/hyperledger/fabric-ca/lib/client/credential/x509/mocks"
    25  	"github.com/hyperledger/fabric-ca/util"
    26  	"github.com/hyperledger/fabric/bccsp/factory"
    27  	"github.com/stretchr/testify/assert"
    28  )
    29  
    30  const (
    31  	testDataDir = "../../../../testdata"
    32  )
    33  
    34  func TestX509Credential(t *testing.T) {
    35  	clientHome, err := ioutil.TempDir(testDataDir, "x509credtest")
    36  	if err != nil {
    37  		t.Fatalf("Failed to create temp directory: %s", err.Error())
    38  	}
    39  	defer os.RemoveAll(clientHome)
    40  
    41  	err = lib.CopyFile(filepath.Join(testDataDir, "ec256-1-cert.pem"), filepath.Join(clientHome, "ec256-1-cert.pem"))
    42  	if err != nil {
    43  		t.Fatalf("Failed to copy ec256-1-cert.pem to %s: %s", clientHome, err.Error())
    44  	}
    45  	err = os.MkdirAll(filepath.Join(clientHome, "msp/keystore"), 0777)
    46  	if err != nil {
    47  		t.Fatalf("Failed to create msp/keystore directory: %s", err.Error())
    48  	}
    49  
    50  	client := &lib.Client{
    51  		Config: &lib.ClientConfig{
    52  			URL: fmt.Sprintf("http://localhost:7054"),
    53  			CSP: &factory.FactoryOpts{
    54  				SwOpts: &factory.SwOpts{
    55  					HashFamily: "SHA2",
    56  					SecLevel:   256,
    57  					FileKeystore: &factory.FileKeystoreOpts{
    58  						KeyStorePath: "msp/keystore",
    59  					},
    60  				},
    61  			},
    62  		},
    63  		HomeDir: clientHome,
    64  	}
    65  	certFile := filepath.Join(client.HomeDir, "fake-cert.pem")
    66  	keyFile := filepath.Join(client.HomeDir, "fake-key.pem")
    67  	x509Cred := NewCredential(certFile, keyFile, client)
    68  
    69  	assert.Equal(t, x509Cred.Type(), CredType, "Type for a X509Credential instance must be X509")
    70  	_, err = x509Cred.Val()
    71  	assert.Error(t, err, "Val should return error as credential has not been loaded from disk or set")
    72  	if err != nil {
    73  		assert.Equal(t, err.Error(), "X509 Credential value is not set")
    74  	}
    75  	_, err = x509Cred.EnrollmentID()
    76  	assert.Error(t, err, "EnrollmentID should return an error as credential has not been loaded from disk or set")
    77  	if err != nil {
    78  		assert.Equal(t, err.Error(), "X509 Credential value is not set")
    79  	}
    80  
    81  	err = x509Cred.Store()
    82  	assert.Error(t, err, "Store should return an error as credential has not been loaded from disk or set")
    83  
    84  	err = x509Cred.SetVal("hello")
    85  	assert.Error(t, err, "SetVal should fail as it expects an object of type *Signer")
    86  
    87  	_, err = x509Cred.RevokeSelf()
    88  	assert.Error(t, err, "RevokeSelf should return an error as credential has not been loaded from disk or set")
    89  
    90  	// Set valid value
    91  	certBytes, err := util.ReadFile(filepath.Join(testDataDir, "ec256-1-cert.pem"))
    92  	if err != nil {
    93  		t.Fatalf("Failed to read file: %s", err.Error())
    94  	}
    95  	signer, err := NewSigner(nil, certBytes)
    96  	if err != nil {
    97  		t.Fatalf("Failed to create signer: %s", err.Error())
    98  	}
    99  	err = x509Cred.SetVal(signer)
   100  	assert.NoError(t, err, "SetVal should not fail")
   101  
   102  	// Load the credential from client msp, which should fail as enrollment cert/key pair is not present
   103  	err = x509Cred.Load()
   104  	assert.Error(t, err, "Load should have failed to load non-existent certificate file")
   105  
   106  	certFile = filepath.Join(client.HomeDir, "ec256-1-cert.pem")
   107  	keyFile = filepath.Join(client.HomeDir, "ec256-1-key.pem")
   108  
   109  	err = client.Init()
   110  	if err != nil {
   111  		t.Fatalf("Failed to initialize client: %s", err.Error())
   112  	}
   113  	x509Cred = NewCredential(certFile, keyFile, client)
   114  	err = x509Cred.Load()
   115  	assert.Error(t, err, "Load should have failed to load non-existent key file")
   116  	assert.Contains(t, err.Error(), "Could not find the private key in the BCCSP keystore nor in the keyfile")
   117  
   118  	err = lib.CopyFile(filepath.Join(testDataDir, "ec256-1-key.pem"), filepath.Join(client.HomeDir, "ec256-1-key.pem"))
   119  	if err != nil {
   120  		t.Fatalf("Failed to copy ec256-1-key.pem to %s: %s", clientHome, err.Error())
   121  	}
   122  	err = x509Cred.Load()
   123  	assert.NoError(t, err, "Load should not fail as both cert and key files exist and are valid")
   124  
   125  	// Should error if it fails to write cert to the specified file
   126  	if err = os.Chmod(certFile, 0000); err != nil {
   127  		t.Fatalf("Failed to chmod certificate file %s: %s", certFile, err.Error())
   128  	}
   129  	err = x509Cred.Store()
   130  	assert.Error(t, err, "Store should fail as %s is not writable", certFile)
   131  	if err = os.Chmod(certFile, 0644); err != nil {
   132  		t.Fatalf("Failed to chmod certificate file %s: %s", certFile, err.Error())
   133  	}
   134  
   135  	// Success cases
   136  	err = x509Cred.Load()
   137  	assert.NoError(t, err, "Load should not fail as cert exists and key is in bccsp keystore")
   138  
   139  	_, err = x509Cred.Val()
   140  	assert.NoError(t, err, "Val should not return error as x509 credential has been loaded")
   141  
   142  	_, err = x509Cred.EnrollmentID()
   143  	assert.NoError(t, err, "EnrollmentID should not return error as credential has been loaded")
   144  
   145  	err = x509Cred.Store()
   146  	assert.NoError(t, err, "Store should not fail as x509 credential is set and cert file path is valid")
   147  
   148  	body := []byte("hello")
   149  	req, err := http.NewRequest("GET", "localhost:7054/enroll", bytes.NewReader(body))
   150  	if err != nil {
   151  		t.Fatalf("Failed to create HTTP request: %s", err.Error())
   152  	}
   153  	_, err = x509Cred.CreateToken(req, body)
   154  	assert.NoError(t, err, "CreateToken should not return error")
   155  }
   156  
   157  func TestRevokeSelf(t *testing.T) {
   158  	clientHome, err := ioutil.TempDir(testDataDir, "revokeselftest")
   159  	if err != nil {
   160  		t.Fatalf("Failed to create temp directory: %s", err.Error())
   161  	}
   162  	defer os.RemoveAll(clientHome)
   163  
   164  	err = lib.CopyFile(filepath.Join(testDataDir, "ec256-1-cert.pem"), filepath.Join(clientHome, "ec256-1-cert.pem"))
   165  	if err != nil {
   166  		t.Fatalf("Failed to copy ec256-1-cert.pem to %s: %s", clientHome, err.Error())
   167  	}
   168  	err = os.MkdirAll(filepath.Join(clientHome, "msp/keystore"), 0777)
   169  	if err != nil {
   170  		t.Fatalf("Failed to create msp/keystore directory: %s", err.Error())
   171  	}
   172  	keystore := filepath.Join(clientHome, "msp/keystore/ec256-1-key.pem")
   173  	err = lib.CopyFile(filepath.Join(testDataDir, "ec256-1-key.pem"), keystore)
   174  	if err != nil {
   175  		t.Fatalf("Failed to copy ec256-1-key.pem to %s: %s", keystore, err.Error())
   176  	}
   177  
   178  	id := new(mocks.Identity)
   179  	client := new(mocks.Client)
   180  	opts := &factory.FactoryOpts{
   181  		SwOpts: &factory.SwOpts{
   182  			HashFamily: "SHA2",
   183  			SecLevel:   256,
   184  			FileKeystore: &factory.FileKeystoreOpts{
   185  				KeyStorePath: "msp/keystore",
   186  			},
   187  		},
   188  	}
   189  	bccsp, err := util.InitBCCSP(&opts, filepath.Join(clientHome, "msp/keystore"), clientHome)
   190  	if err != nil {
   191  		t.Fatalf("Failed initialize BCCSP: %s", err.Error())
   192  	}
   193  	client.On("GetCSP").Return(bccsp)
   194  	client.On("GetCSP").Return(nil)
   195  	certFile := filepath.Join(clientHome, "ec256-1-cert.pem")
   196  	cert, err := readCert(certFile)
   197  	if err != nil {
   198  		t.Fatalf("Failed to read the cert: %s", err.Error())
   199  	}
   200  	x509Cred := NewCredential(certFile, keystore, client)
   201  	err = x509Cred.Load()
   202  	if err != nil {
   203  		t.Fatalf("Should not fail to load x509 credential as cert exists and key is in bccsp keystore: %s", err.Error())
   204  	}
   205  	name, err := x509Cred.EnrollmentID()
   206  	assert.NoError(t, err, "EnrollmentID() should not return an error")
   207  	client.On("NewX509Identity", name, []credential.Credential{x509Cred}).Return(id)
   208  
   209  	serial := util.GetSerialAsHex(cert.SerialNumber)
   210  	aki := hex.EncodeToString(cert.AuthorityKeyId)
   211  	req := &api.RevocationRequest{
   212  		Serial: serial,
   213  		AKI:    aki,
   214  	}
   215  	id.On("Revoke", req).Return(&api.RevocationResponse{}, nil)
   216  
   217  	_, err = x509Cred.RevokeSelf()
   218  	assert.NoError(t, err)
   219  
   220  	body := []byte{}
   221  	httpReq, err := http.NewRequest("GET", "localhost:7054/enroll", bytes.NewReader(body))
   222  	if err != nil {
   223  		t.Fatalf("Failed to create HTTP request: %s", err.Error())
   224  	}
   225  	_, err = x509Cred.CreateToken(httpReq, body)
   226  	assert.NoError(t, err)
   227  }
   228  
   229  func readCert(certFile string) (*x509.Certificate, error) {
   230  	certBytes, err := util.ReadFile(certFile)
   231  	if err != nil {
   232  		return nil, err
   233  	}
   234  	cert, err := util.GetX509CertificateFromPEM(certBytes)
   235  	if err != nil {
   236  		return nil, err
   237  	}
   238  	return cert, nil
   239  }