github.com/hxx258456/fabric-ca-gm@v0.0.3-0.20221111064038-a268ad7e3a37/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  	"encoding/hex"
    12  	"io/ioutil"
    13  	"os"
    14  	"path/filepath"
    15  	"testing"
    16  
    17  	http "github.com/hxx258456/ccgo/gmhttp"
    18  
    19  	"github.com/hxx258456/ccgo/x509"
    20  
    21  	"github.com/hxx258456/fabric-ca-gm/internal/pkg/api"
    22  	"github.com/hxx258456/fabric-ca-gm/internal/pkg/util"
    23  	"github.com/hxx258456/fabric-ca-gm/lib"
    24  	"github.com/hxx258456/fabric-ca-gm/lib/client/credential"
    25  	. "github.com/hxx258456/fabric-ca-gm/lib/client/credential/x509"
    26  	"github.com/hxx258456/fabric-ca-gm/lib/client/credential/x509/mocks"
    27  	"github.com/hxx258456/fabric-gm/bccsp/factory"
    28  
    29  	// "github.com/hxx258456/ccgo/x509"
    30  	"github.com/stretchr/testify/assert"
    31  )
    32  
    33  const (
    34  	testDataDir = "../../../../testdata"
    35  )
    36  
    37  func TestX509Credential(t *testing.T) {
    38  	clientHome, err := ioutil.TempDir(testDataDir, "x509credtest")
    39  	if err != nil {
    40  		t.Fatalf("Failed to create temp directory: %s", err.Error())
    41  	}
    42  	defer os.RemoveAll(clientHome)
    43  
    44  	err = lib.CopyFile(filepath.Join(testDataDir, "ec256-1-cert.pem"), filepath.Join(clientHome, "ec256-1-cert.pem"))
    45  	if err != nil {
    46  		t.Fatalf("Failed to copy ec256-1-cert.pem to %s: %s", clientHome, err.Error())
    47  	}
    48  	err = os.MkdirAll(filepath.Join(clientHome, "msp/keystore"), 0777)
    49  	if err != nil {
    50  		t.Fatalf("Failed to create msp/keystore directory: %s", err.Error())
    51  	}
    52  
    53  	client := &lib.Client{
    54  		Config: &lib.ClientConfig{
    55  			URL: "http://localhost:7054",
    56  			CSP: &factory.FactoryOpts{
    57  				SwOpts: &factory.SwOpts{
    58  					HashFamily: "SHA2",
    59  					SecLevel:   256,
    60  					FileKeystore: &factory.FileKeystoreOpts{
    61  						KeyStorePath: "msp/keystore",
    62  					},
    63  				},
    64  			},
    65  		},
    66  		HomeDir: clientHome,
    67  	}
    68  	certFile := filepath.Join(client.HomeDir, "fake-cert.pem")
    69  	keyFile := filepath.Join(client.HomeDir, "fake-key.pem")
    70  	x509Cred := NewCredential(certFile, keyFile, client)
    71  
    72  	assert.Equal(t, x509Cred.Type(), CredType, "Type for a X509Credential instance must be X509")
    73  	_, err = x509Cred.Val()
    74  	assert.Error(t, err, "Val should return error as credential has not been loaded from disk or set")
    75  	if err != nil {
    76  		assert.Equal(t, err.Error(), "X509 Credential value is not set")
    77  	}
    78  	_, err = x509Cred.EnrollmentID()
    79  	assert.Error(t, err, "EnrollmentID should return an error as credential has not been loaded from disk or set")
    80  	if err != nil {
    81  		assert.Equal(t, err.Error(), "X509 Credential value is not set")
    82  	}
    83  
    84  	err = x509Cred.Store()
    85  	assert.Error(t, err, "Store should return an error as credential has not been loaded from disk or set")
    86  
    87  	err = x509Cred.SetVal("hello")
    88  	assert.Error(t, err, "SetVal should fail as it expects an object of type *Signer")
    89  
    90  	_, err = x509Cred.RevokeSelf()
    91  	assert.Error(t, err, "RevokeSelf should return an error as credential has not been loaded from disk or set")
    92  
    93  	// Set valid value
    94  	certBytes, err := util.ReadFile(filepath.Join(testDataDir, "ec256-1-cert.pem"))
    95  	if err != nil {
    96  		t.Fatalf("Failed to read file: %s", err.Error())
    97  	}
    98  	signer, err := NewSigner(nil, certBytes)
    99  	if err != nil {
   100  		t.Fatalf("Failed to create signer: %s", err.Error())
   101  	}
   102  	err = x509Cred.SetVal(signer)
   103  	assert.NoError(t, err, "SetVal should not fail")
   104  
   105  	// Load the credential from client msp, which should fail as enrollment cert/key pair is not present
   106  	err = x509Cred.Load()
   107  	assert.Error(t, err, "Load should have failed to load non-existent certificate file")
   108  
   109  	certFile = filepath.Join(client.HomeDir, "ec256-1-cert.pem")
   110  	keyFile = filepath.Join(client.HomeDir, "ec256-1-key.pem")
   111  
   112  	err = client.Init()
   113  	if err != nil {
   114  		t.Fatalf("Failed to initialize client: %s", err.Error())
   115  	}
   116  	x509Cred = NewCredential(certFile, keyFile, client)
   117  	err = x509Cred.Load()
   118  	assert.Error(t, err, "Load should have failed to load non-existent key file")
   119  	assert.Contains(t, err.Error(), "Could not find the private key in the BCCSP keystore nor in the keyfile")
   120  
   121  	err = lib.CopyFile(filepath.Join(testDataDir, "ec256-1-key.pem"), filepath.Join(client.HomeDir, "ec256-1-key.pem"))
   122  	if err != nil {
   123  		t.Fatalf("Failed to copy ec256-1-key.pem to %s: %s", clientHome, err.Error())
   124  	}
   125  	err = x509Cred.Load()
   126  	assert.NoError(t, err, "Load should not fail as both cert and key files exist and are valid")
   127  
   128  	// Should error if it fails to write cert to the specified file
   129  	if err = os.Chmod(certFile, 0000); err != nil {
   130  		t.Fatalf("Failed to chmod certificate file %s: %s", certFile, err.Error())
   131  	}
   132  	err = x509Cred.Store()
   133  	assert.Errorf(t, err, "Store should fail as %s is not writable", certFile)
   134  	if err = os.Chmod(certFile, 0644); err != nil {
   135  		t.Fatalf("Failed to chmod certificate file %s: %s", certFile, err.Error())
   136  	}
   137  
   138  	// Success cases
   139  	err = x509Cred.Load()
   140  	assert.NoError(t, err, "Load should not fail as cert exists and key is in bccsp keystore")
   141  
   142  	_, err = x509Cred.Val()
   143  	assert.NoError(t, err, "Val should not return error as x509 credential has been loaded")
   144  
   145  	_, err = x509Cred.EnrollmentID()
   146  	assert.NoError(t, err, "EnrollmentID should not return error as credential has been loaded")
   147  
   148  	err = x509Cred.Store()
   149  	assert.NoError(t, err, "Store should not fail as x509 credential is set and cert file path is valid")
   150  
   151  	body := []byte("hello")
   152  	req, err := http.NewRequest("GET", "localhost:7054/enroll", bytes.NewReader(body))
   153  	if err != nil {
   154  		t.Fatalf("Failed to create HTTP request: %s", err.Error())
   155  	}
   156  	_, err = x509Cred.CreateToken(req, body)
   157  	assert.NoError(t, err, "CreateToken should not return error")
   158  }
   159  
   160  func TestRevokeSelf(t *testing.T) {
   161  	clientHome, err := ioutil.TempDir(testDataDir, "revokeselftest")
   162  	if err != nil {
   163  		t.Fatalf("Failed to create temp directory: %s", err.Error())
   164  	}
   165  	defer os.RemoveAll(clientHome)
   166  
   167  	err = lib.CopyFile(filepath.Join(testDataDir, "ec256-1-cert.pem"), filepath.Join(clientHome, "ec256-1-cert.pem"))
   168  	if err != nil {
   169  		t.Fatalf("Failed to copy ec256-1-cert.pem to %s: %s", clientHome, err.Error())
   170  	}
   171  	err = os.MkdirAll(filepath.Join(clientHome, "msp/keystore"), 0777)
   172  	if err != nil {
   173  		t.Fatalf("Failed to create msp/keystore directory: %s", err.Error())
   174  	}
   175  	keystore := filepath.Join(clientHome, "msp/keystore/ec256-1-key.pem")
   176  	err = lib.CopyFile(filepath.Join(testDataDir, "ec256-1-key.pem"), keystore)
   177  	if err != nil {
   178  		t.Fatalf("Failed to copy ec256-1-key.pem to %s: %s", keystore, err.Error())
   179  	}
   180  
   181  	id := new(mocks.Identity)
   182  	client := new(mocks.Client)
   183  	opts := &factory.FactoryOpts{
   184  		SwOpts: &factory.SwOpts{
   185  			HashFamily: "SHA2",
   186  			SecLevel:   256,
   187  		},
   188  	}
   189  	bccsp, err := util.InitBCCSP(&opts, "msp", 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  }