github.com/simranvc/fabric-ca@v0.0.0-20191030094829-acc364294dde/util/util_test.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 util
    18  
    19  import (
    20  	"bytes"
    21  	"crypto/ecdsa"
    22  	"crypto/elliptic"
    23  	"crypto/rand"
    24  	"crypto/rsa"
    25  	"crypto/x509"
    26  	"encoding/pem"
    27  	"fmt"
    28  	"io"
    29  	"io/ioutil"
    30  	"math/big"
    31  	"net/http"
    32  	"os"
    33  	"path"
    34  	"path/filepath"
    35  	"strings"
    36  	"testing"
    37  
    38  	"github.com/hyperledger/fabric/bccsp/factory"
    39  	_ "github.com/mattn/go-sqlite3"
    40  	"github.com/spf13/viper"
    41  	"github.com/stretchr/testify/assert"
    42  )
    43  
    44  func TestGetEnrollmentIDFromPEM(t *testing.T) {
    45  	cert, err := ioutil.ReadFile(getPath("ec.pem"))
    46  	if err != nil {
    47  		t.Fatalf("TestGetEnrollmentIDFromPEM.ReadFile failed: %s", err)
    48  	}
    49  	_, err = GetEnrollmentIDFromPEM(cert)
    50  	if err != nil {
    51  		t.Fatalf("Failed to get enrollment ID from PEM: %s", err)
    52  	}
    53  }
    54  
    55  func TestECCreateToken(t *testing.T) {
    56  	cert, _ := ioutil.ReadFile(getPath("ec.pem"))
    57  	bccsp := GetDefaultBCCSP()
    58  	privKey, err := ImportBCCSPKeyFromPEM(getPath("ec-key.pem"), bccsp, true)
    59  	if err != nil {
    60  		t.Logf("Failed importing key %s", err)
    61  	}
    62  	body := []byte("request byte array")
    63  
    64  	ECtoken, err := CreateToken(bccsp, cert, privKey, "GET", "/enroll", body)
    65  	if err != nil {
    66  		t.Fatalf("CreatToken failed: %s", err)
    67  	}
    68  
    69  	os.Setenv("FABRIC_CA_SERVER_COMPATIBILITY_MODE_V1_3", "false") // Test new token
    70  	_, err = VerifyToken(bccsp, ECtoken, "GET", "/enroll", body, false)
    71  	if err != nil {
    72  		t.Fatalf("VerifyToken failed: %s", err)
    73  	}
    74  
    75  	_, err = VerifyToken(nil, ECtoken, "GET", "/enroll", body, false)
    76  	if err == nil {
    77  		t.Fatal("VerifyToken should have failed as no instance of csp is passed")
    78  	}
    79  
    80  	_, err = VerifyToken(bccsp, "", "GET", "/enroll", body, false)
    81  	if err == nil {
    82  		t.Fatal("VerifyToken should have failed as no EC Token is passed")
    83  	}
    84  
    85  	_, err = VerifyToken(bccsp, ECtoken, "GET", "/enroll", nil, false)
    86  	if err == nil {
    87  		t.Fatal("VerifyToken should have failed as no body is passed")
    88  	}
    89  
    90  	_, err = VerifyToken(bccsp, ECtoken, "POST", "/enroll", nil, false)
    91  	if err == nil {
    92  		t.Fatal("VerifyToken should have failed as method was tampered")
    93  	}
    94  
    95  	_, err = VerifyToken(bccsp, ECtoken, "GET", "/affiliations", nil, false)
    96  	if err == nil {
    97  		t.Fatal("VerifyToken should have failed as path was tampered")
    98  	}
    99  
   100  	verifiedByte := []byte("TEST")
   101  	body = append(body, verifiedByte[0])
   102  	_, err = VerifyToken(bccsp, ECtoken, "GET", "/enroll", body, false)
   103  	if err == nil {
   104  		t.Fatal("VerifyToken should have failed as body was tampered")
   105  	}
   106  
   107  	ski, skierror := ioutil.ReadFile(getPath("ec-key.ski"))
   108  	if skierror != nil {
   109  		t.Fatalf("SKI File Read failed with error : %s", skierror)
   110  	}
   111  	ECtoken, err = CreateToken(bccsp, ski, privKey, "GET", "/enroll", body)
   112  	if (err == nil) || (ECtoken != "") {
   113  		t.Fatal("CreatToken should have failed as certificate passed is not correct")
   114  	}
   115  
   116  	// With comptability mode disabled, using old token should fail
   117  	b64Cert := B64Encode(cert)
   118  	payload := B64Encode(body) + "." + b64Cert
   119  	oldToken, err := genECDSAToken(bccsp, privKey, b64Cert, payload)
   120  	FatalError(t, err, "Failed to create token")
   121  	_, err = VerifyToken(bccsp, oldToken, "GET", "/enroll", body, false)
   122  	assert.Error(t, err)
   123  
   124  	// Test that by default with no environment variable set, the old token is considered valid
   125  	os.Unsetenv("FABRIC_CA_SERVER_COMPATIBILITY_MODE_V1_3")
   126  	_, err = VerifyToken(bccsp, oldToken, "GET", "/enroll", body, true)
   127  	assert.NoError(t, err, "Failed to verify token using old token type")
   128  }
   129  
   130  func TestDecodeToken(t *testing.T) {
   131  	token := "x.y.z"
   132  	_, _, _, err := DecodeToken(token)
   133  	assert.Error(t, err, "Decode should fail if the token has more than two parts")
   134  
   135  	token = "x"
   136  	_, _, _, err = DecodeToken(token)
   137  	assert.Error(t, err, "Decode should fail if the token has less than two parts")
   138  
   139  	token = "x.y"
   140  	_, _, _, err = DecodeToken(token)
   141  	assert.Error(t, err, "Decode should fail if the 1st part of the token is not in base64 encoded format")
   142  
   143  	fakecert := B64Encode([]byte("hello"))
   144  	token = fakecert + ".y"
   145  	_, _, _, err = DecodeToken(token)
   146  	assert.Error(t, err, "Decode should fail if the 1st part of the token is not base64 bytes of a X509 cert")
   147  }
   148  func TestGetX509CertFromPem(t *testing.T) {
   149  
   150  	certBuffer, error := ioutil.ReadFile(getPath("ec.pem"))
   151  	if error != nil {
   152  		t.Fatalf("Certificate File Read from file failed with error : %s", error)
   153  	}
   154  	certificate, err := GetX509CertificateFromPEM(certBuffer)
   155  	if err != nil {
   156  		t.Fatalf("GetX509CertificateFromPEM failed with error : %s", err)
   157  	}
   158  	if certificate == nil {
   159  		t.Fatal("Certificate cannot be nil")
   160  	}
   161  
   162  	skiBuffer, skiError := ioutil.ReadFile(getPath("ec-key.ski"))
   163  	if skiError != nil {
   164  		t.Fatalf("SKI File read failed with error : %s", skiError)
   165  	}
   166  
   167  	certificate, err = GetX509CertificateFromPEM(skiBuffer)
   168  	if err == nil {
   169  		t.Fatal("GetX509CertificateFromPEM should have failed as bytes passed was not in correct format")
   170  	}
   171  	if certificate != nil {
   172  		t.Fatalf("GetX509CertificateFromPEM should have failed as bytes passed was not in correct format")
   173  	}
   174  }
   175  
   176  func TestGetX509CertsFromPem(t *testing.T) {
   177  	certBuffer, error := ioutil.ReadFile(getPath("ec.pem"))
   178  	if error != nil {
   179  		t.Fatalf("Certificate File Read from file failed with error : %s", error)
   180  	}
   181  	certificates, err := GetX509CertificatesFromPEM(certBuffer)
   182  	assert.NoError(t, err, "GetX509CertificatesFromPEM failed")
   183  	assert.NotNil(t, certificates)
   184  	assert.Equal(t, 1, len(certificates), "GetX509CertificatesFromPEM should have returned 1 certificate")
   185  
   186  	skiBuffer, skiError := ioutil.ReadFile(getPath("ec-key.ski"))
   187  	if skiError != nil {
   188  		t.Fatalf("SKI File read failed with error : %s", skiError)
   189  	}
   190  
   191  	certificates, err = GetX509CertificatesFromPEM(skiBuffer)
   192  	if err == nil {
   193  		t.Fatal("GetX509CertificatesFromPEM should have failed as bytes passed was not in correct format")
   194  	}
   195  	if certificates != nil {
   196  		t.Fatalf("GetX509CertificatesFromPEM should have failed as bytes passed was not in correct format")
   197  	}
   198  }
   199  
   200  // This test case has been removed temporarily
   201  // as BCCSP does not have support for RSA private key import
   202  /*
   203  func TestRSACreateToken(t *testing.T) {
   204  	cert, _ := ioutil.ReadFile(getPath("rsa.pem"))
   205  	privKey, _ := ioutil.ReadFile(getPath("rsa-key.pem"))
   206  	body := []byte("request byte array")
   207  
   208  	csp := factory.GetDefault()
   209  	RSAtoken, err := CreateToken(csp, cert, privKey, body)
   210  	if err != nil {
   211  		t.Fatalf("CreatToken failed with error : %s", err)
   212  	}
   213  
   214  	_, err = VerifyToken(csp, RSAtoken, body)
   215  	if err != nil {
   216  		t.Fatalf("VerifyToken failed with error : %s", err)
   217  	}
   218  }
   219  */
   220  
   221  func TestCreateTokenDiffKey(t *testing.T) {
   222  	cert, _ := ioutil.ReadFile(getPath("ec.pem"))
   223  	bccsp := GetDefaultBCCSP()
   224  	privKey, _ := ImportBCCSPKeyFromPEM(getPath("rsa-key.pem"), bccsp, true)
   225  	body := []byte("request byte array")
   226  	_, err := CreateToken(bccsp, cert, privKey, "POST", "/enroll", body)
   227  	if err == nil {
   228  		t.Fatalf("TestCreateTokenDiffKey passed but should have failed")
   229  	}
   230  }
   231  
   232  // TestCreateTokenDiffKey2 has been commeted out right now
   233  // As there BCCSP does not have support fot RSA private Key
   234  // import. This will be uncommented when the support is in.
   235  /*
   236  func TestCreateTokenDiffKey2(t *testing.T) {
   237  	cert, _ := ioutil.ReadFile(getPath("rsa.pem"))
   238  	privKey, _ := ioutil.ReadFile(getPath("ec-key.pem"))
   239  	body := []byte("request byte array")
   240  
   241  	csp := factory.GetDefault()
   242  	_, err := CreateToken(csp, cert, privKey, body)
   243  	if err == nil {
   244  		t.Fatalf("TestCreateTokenDiffKey2 passed but should have failed")
   245  	}
   246  }
   247  */
   248  
   249  func TestEmptyToken(t *testing.T) {
   250  	body := []byte("request byte array")
   251  
   252  	csp := factory.GetDefault()
   253  	_, err := VerifyToken(csp, "", "POST", "/enroll", body, true)
   254  	if err == nil {
   255  		t.Fatalf("TestEmptyToken passed but should have failed")
   256  	}
   257  }
   258  
   259  func TestEmptyCert(t *testing.T) {
   260  	cert, _ := ioutil.ReadFile(getPath("ec.pem"))
   261  	body := []byte("request byte array")
   262  
   263  	csp := factory.GetDefault()
   264  	_, err := CreateToken(csp, cert, nil, "POST", "/enroll", body)
   265  	if err == nil {
   266  		t.Fatalf("TestEmptyCert passed but should have failed")
   267  	}
   268  }
   269  
   270  func TestEmptyKey(t *testing.T) {
   271  	bccsp := GetDefaultBCCSP()
   272  	privKey, _ := ImportBCCSPKeyFromPEM(getPath("ec-key.pem"), bccsp, true)
   273  	body := []byte("request byte array")
   274  	_, err := CreateToken(bccsp, []byte(""), privKey, "POST", "/enroll", body)
   275  	if err == nil {
   276  		t.Fatalf("TestEmptyKey passed but should have failed")
   277  	}
   278  }
   279  
   280  func TestEmptyBody(t *testing.T) {
   281  	bccsp := GetDefaultBCCSP()
   282  	privKey, _ := ImportBCCSPKeyFromPEM(getPath("ec-key.pem"), bccsp, true)
   283  	cert, _ := ioutil.ReadFile(getPath("ec.pem"))
   284  	_, err := CreateToken(bccsp, cert, privKey, "POST", "/enroll", []byte(""))
   285  	if err != nil {
   286  		t.Fatalf("CreateToken failed: %s", err)
   287  	}
   288  }
   289  
   290  func TestRandomString(t *testing.T) {
   291  	str := RandomString(10)
   292  	if str == "" {
   293  		t.Fatalf("RandomString failure")
   294  	}
   295  }
   296  
   297  func TestRemoveQuotes(t *testing.T) {
   298  	str := RemoveQuotes(`"a"`)
   299  	if str != "a" {
   300  		t.Fatalf("TestRemoveQuotes failed")
   301  	}
   302  }
   303  
   304  func TestRemoveQuotesNone(t *testing.T) {
   305  	str := RemoveQuotes(`a`)
   306  	if str != "a" {
   307  		t.Fatalf("TestRemoveQuotesNone failed")
   308  	}
   309  }
   310  
   311  func TestCreateHome(t *testing.T) {
   312  	t.Log("Test Creating Home Directory")
   313  	os.Unsetenv("COP_HOME")
   314  	tempDir, err := ioutil.TempDir("", "test")
   315  	if err != nil {
   316  		t.Errorf("Failed to create temp directory [error: %s]", err)
   317  	}
   318  	os.Setenv("HOME", tempDir)
   319  
   320  	dir, err := CreateClientHome()
   321  	if err != nil {
   322  		t.Errorf("Failed to create home directory, error: %s", err)
   323  	}
   324  
   325  	if _, err = os.Stat(dir); err != nil {
   326  		if os.IsNotExist(err) {
   327  			t.Error("Failed to create home directory")
   328  		}
   329  	}
   330  
   331  	os.RemoveAll(dir)
   332  }
   333  
   334  func TestGetDefaultConfigFile(t *testing.T) {
   335  	os.Unsetenv("FABRIC_CA_HOME")
   336  	os.Unsetenv("FABRIC_CA_CLIENT_HOME")
   337  	os.Unsetenv("FABRIC_CA_SERVER_HOME")
   338  	os.Unsetenv("CA_CFG_PATH")
   339  
   340  	const clientConfig = "fabric-ca-client-config.yaml"
   341  	const serverConfig = "fabric-ca-server-config.yaml"
   342  
   343  	os.Setenv("HOME", "/tmp")
   344  
   345  	expected := filepath.Join("/tmp/.fabric-ca-client/", clientConfig)
   346  	real := GetDefaultConfigFile("fabric-ca-client")
   347  	if real != expected {
   348  		t.Errorf("Incorrect default config path retrieved; expected %s but found %s",
   349  			expected, real)
   350  	}
   351  
   352  	os.Setenv("FABRIC_CA_HOME", "/tmp")
   353  	expected = filepath.Join("/tmp", clientConfig)
   354  	real = GetDefaultConfigFile("fabric-ca-client")
   355  	if real != expected {
   356  		t.Errorf("Incorrect default config path retrieved; expected %s but found %s",
   357  			expected, real)
   358  	}
   359  
   360  	expected = filepath.Join("/tmp", serverConfig)
   361  	real = GetDefaultConfigFile("fabric-ca-server")
   362  	if real != expected {
   363  		t.Errorf("Incorrect default config path retrieved; expected %s but found %s",
   364  			expected, real)
   365  	}
   366  
   367  	os.Setenv("FABRIC_CA_CLIENT_HOME", "/tmp/client")
   368  	expected = filepath.Join("/tmp/client", clientConfig)
   369  	real = GetDefaultConfigFile("fabric-ca-client")
   370  	if real != expected {
   371  		t.Errorf("Incorrect default config path retrieved; expected %s but found %s",
   372  			expected, real)
   373  	}
   374  
   375  	os.Setenv("FABRIC_CA_SERVER_HOME", "/tmp/server")
   376  	expected = filepath.Join("/tmp/server", serverConfig)
   377  	real = GetDefaultConfigFile("fabric-ca-server")
   378  	if real != expected {
   379  		t.Errorf("Incorrect default config path retrieved; expected %s but found %s",
   380  			expected, real)
   381  	}
   382  }
   383  
   384  func TestUnmarshal(t *testing.T) {
   385  	byteArray := []byte(`{"text":"foo"}`)
   386  	type test struct {
   387  		text string
   388  	}
   389  	var Test test
   390  	err := Unmarshal(byteArray, &Test, "testing unmarshal")
   391  	if err != nil {
   392  		t.Error("Failed to unmarshal, error: ", err)
   393  	}
   394  }
   395  
   396  func TestMarshal(t *testing.T) {
   397  	var x interface{}
   398  	_, err := Marshal(x, "testing marshal")
   399  	if err != nil {
   400  		t.Error("Failed to marshal, error: ", err)
   401  	}
   402  }
   403  
   404  func TestReadFile(t *testing.T) {
   405  	_, err := ReadFile("../testdata/csr.json")
   406  	if err != nil {
   407  		t.Error("Failed to read file, error: ", err)
   408  	}
   409  }
   410  
   411  func TestWriteFile(t *testing.T) {
   412  	testdir, err := ioutil.TempDir(".", "writefiletest")
   413  	if err != nil {
   414  		t.Fatalf("Failed to create temp directory: %s", err.Error())
   415  	}
   416  	defer os.RemoveAll(testdir)
   417  	testData := []byte("foo")
   418  	err = WriteFile(path.Join(testdir, "test.txt"), testData, 0777)
   419  	assert.NoError(t, err)
   420  	readOnlyDir := path.Join(testdir, "readonlydir")
   421  	err = os.MkdirAll(readOnlyDir, 4444)
   422  	if err != nil {
   423  		t.Fatalf("Failed to create directory: %s", err.Error())
   424  	}
   425  	err = WriteFile(path.Join(readOnlyDir, "test/test.txt"), testData, 0777)
   426  	assert.Error(t, err, "Should fail to create 'test' directory as the parent directory is read only")
   427  }
   428  
   429  func getPath(file string) string {
   430  	return "../testdata/" + file
   431  }
   432  
   433  func TestStrContained(t *testing.T) {
   434  	strs := []string{"one", "two", "three"}
   435  	str := "one"
   436  	result := StrContained(str, strs)
   437  	if result != true {
   438  		t.Error("Should have result in true")
   439  	}
   440  }
   441  
   442  func TestFileExists(t *testing.T) {
   443  	name := "../testdata/csr.json"
   444  	exists := FileExists(name)
   445  	if exists == false {
   446  		t.Error("File does not exist")
   447  	}
   448  	name = "better-not-exist"
   449  	exists = FileExists(name)
   450  	if exists == true {
   451  		t.Error("File 'better-not-exist' should not exist")
   452  	}
   453  }
   454  
   455  func TestMakeFileAbs(t *testing.T) {
   456  	testMakeFileAbs(t, "", "", "")
   457  	testMakeFileAbs(t, "/a/b/c", "", "/a/b/c")
   458  	testMakeFileAbs(t, "c", "/a/b", "/a/b/c")
   459  	testMakeFileAbs(t, "../c", "/a/b", "/a/c")
   460  }
   461  
   462  func TestMakeFilesAbs(t *testing.T) {
   463  	file1 := "a"
   464  	file2 := "a/b"
   465  	file3 := "/a/b"
   466  	files := []*string{&file1, &file2, &file3}
   467  	err := MakeFileNamesAbsolute(files, "/tmp")
   468  	if err != nil {
   469  		t.Fatalf("MakeFilesAbsolute failed: %s", err)
   470  	}
   471  	if file1 != "/tmp/a" {
   472  		t.Errorf("TestMakeFilesAbs failure: expecting /tmp/a but found %s", file1)
   473  	}
   474  	if file2 != "/tmp/a/b" {
   475  		t.Errorf("TestMakeFilesAbs failure: expecting /tmp/a/b but found %s", file2)
   476  	}
   477  	if file3 != "/a/b" {
   478  		t.Errorf("TestMakeFilesAbs failure: expecting /a/b but found %s", file3)
   479  	}
   480  }
   481  
   482  func TestB64(t *testing.T) {
   483  	buf := []byte("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ")
   484  	str := B64Encode(buf)
   485  	buf2, err := B64Decode(str)
   486  	if err != nil {
   487  		t.Errorf("Failed base64 decoding standard: %s", err)
   488  	}
   489  	if !bytes.Equal(buf, buf2) {
   490  		t.Error("Failed base64 decoding standard bytes aren't equal")
   491  	}
   492  }
   493  
   494  func TestGetUser(t *testing.T) {
   495  	os.Unsetenv("FABRIC_CA_CLIENT_URL")
   496  	viper.BindEnv("url", "FABRIC_CA_CLIENT_URL")
   497  	os.Setenv("FABRIC_CA_CLIENT_URL", "http://localhost:7054")
   498  	_, _, err := GetUser(viper.GetViper())
   499  	assert.Error(t, err, "Should have failed no username and password provided")
   500  
   501  	os.Setenv("FABRIC_CA_CLIENT_URL", "http://:pass@localhost:7054")
   502  	_, _, err = GetUser(viper.GetViper())
   503  	assert.Error(t, err, "Should have failed no username provided")
   504  
   505  	os.Setenv("FABRIC_CA_CLIENT_URL", "http://user:@localhost:7054")
   506  	_, _, err = GetUser(viper.GetViper())
   507  	assert.Error(t, err, "Should have failed no password provided")
   508  
   509  	os.Setenv("FABRIC_CA_CLIENT_URL", "http://foo:bar@localhost:7054")
   510  
   511  	user, pass, err := GetUser(viper.GetViper())
   512  	assert.NoError(t, err)
   513  
   514  	if user != "foo" {
   515  		t.Error("Failed to retrieve correct username")
   516  	}
   517  
   518  	if pass != "bar" {
   519  		t.Error("Failed to retrieve correct password")
   520  	}
   521  }
   522  
   523  type configID struct {
   524  	Name string `mask:"username"`
   525  	Addr string `json:"address"`
   526  	Pass string `mask:"password"`
   527  	URL  string `mask:"url"`
   528  	ID   int    `mask:"url"`
   529  }
   530  
   531  func (cc configID) String() string {
   532  	return StructToString(&cc)
   533  }
   534  
   535  func TestStructToString(t *testing.T) {
   536  	var obj configID
   537  	obj.Name = "foo"
   538  	addr := "101, penn ave"
   539  	obj.Addr = addr
   540  	obj.Pass = "bar"
   541  	str := StructToString(&obj)
   542  	if strings.Index(str, "bar") > 0 {
   543  		t.Errorf("Password is not masked by the StructToString function: %s", str)
   544  	}
   545  	if strings.Index(str, "foo") > 0 {
   546  		t.Errorf("Name is not masked by the StructToString function: %s", str)
   547  	}
   548  	if strings.Index(str, addr) < 0 {
   549  		t.Errorf("Addr is masked by the StructToString function: %s", str)
   550  	}
   551  
   552  	type registry struct {
   553  		MaxEnrollments int
   554  		Identities     []configID
   555  	}
   556  	type config struct {
   557  		Registry     registry
   558  		Affiliations map[string]interface{}
   559  	}
   560  	affiliations := map[string]interface{}{"org1": nil}
   561  	caConfig := config{
   562  		Affiliations: affiliations,
   563  		Registry: registry{
   564  			MaxEnrollments: -1,
   565  			Identities: []configID{
   566  				configID{
   567  					Name: "foo",
   568  					Pass: "foopwd",
   569  					Addr: "user",
   570  					URL:  "http://foo:foopwd@localhost:7054",
   571  					ID:   2,
   572  				},
   573  				configID{
   574  					Name: "bar",
   575  					Pass: "barpwd",
   576  					Addr: "user",
   577  					URL:  "ldap://foo:foopwd@localhost:7054",
   578  					ID:   3,
   579  				},
   580  			},
   581  		},
   582  	}
   583  	caConfigStr := fmt.Sprintf("caConfig=%+v", caConfig)
   584  	assert.NotContains(t, caConfigStr, "foopwd", "Identity password is not masked in the output")
   585  	assert.NotContains(t, caConfigStr, "barpwd", "Identity password is not masked in the output")
   586  	idStr := fmt.Sprintf("Identity[0]=%+v", caConfig.Registry.Identities[0])
   587  	assert.NotContains(t, idStr, "foopwd", "Identity password is not masked in the output")
   588  	idStr = fmt.Sprintf("Identity[1]=%+v", &caConfig.Registry.Identities[1])
   589  	assert.NotContains(t, idStr, "barpwd", "Identity password is not masked in the output")
   590  }
   591  
   592  func TestNormalizeStringSlice(t *testing.T) {
   593  	var tests = []struct {
   594  		slice    []string
   595  		expected []string
   596  	}{
   597  		{
   598  			slice:    []string{"string1"},
   599  			expected: []string{"string1"},
   600  		},
   601  		{
   602  			slice:    []string{" string1"},
   603  			expected: []string{"string1"},
   604  		},
   605  		{
   606  			slice:    []string{" string1   "},
   607  			expected: []string{"string1"},
   608  		},
   609  		{
   610  			slice:    []string{" string1   "},
   611  			expected: []string{"string1"},
   612  		},
   613  		{
   614  			slice:    []string{"string1", "string2"},
   615  			expected: []string{"string1", "string2"},
   616  		},
   617  		{
   618  			slice:    []string{"string1", "   string2"},
   619  			expected: []string{"string1", "string2"},
   620  		},
   621  	}
   622  
   623  	for _, test := range tests {
   624  		actual := NormalizeStringSlice(test.slice)
   625  		assert.Equal(t, test.expected, actual)
   626  	}
   627  }
   628  
   629  // Test file list with multiple and single entries both with and without brackets
   630  func TestNormalizeFileList(t *testing.T) {
   631  	slice := []string{"[file0,file1]", "file2,file3", "file4", "[file5]"}
   632  	slice, err := NormalizeFileList(slice, "../testdata")
   633  	if err != nil {
   634  		t.Fatalf("Failed to normalize files list, error: %s", err)
   635  	}
   636  	assert.Equal(t, 6, len(slice), "Invalid slice length")
   637  	for i := range slice {
   638  		if !strings.HasSuffix(slice[i], fmt.Sprintf("file%d", i)) {
   639  			t.Errorf("Failed to normalize files list for element %d; found '%s'", i, slice[i])
   640  		}
   641  	}
   642  }
   643  
   644  func testMakeFileAbs(t *testing.T, file, dir, expect string) {
   645  	path, err := MakeFileAbs(file, dir)
   646  	if err != nil {
   647  		t.Errorf("Failed to make %s absolute: %s", file, err)
   648  	}
   649  	// make expected path platform specific to work on Windows
   650  	if expect != "" {
   651  		expect, _ = filepath.Abs(expect)
   652  	}
   653  	if path != expect {
   654  		t.Errorf("Absolute of file=%s with dir=%s expected %s but was %s", file, dir, expect, path)
   655  	}
   656  }
   657  
   658  func TestRemoveQuotesInvalidArgs(t *testing.T) {
   659  	res := RemoveQuotes("")
   660  	assert.Equal(t, "", res)
   661  }
   662  
   663  func TestUnmarshalInvalidArgs(t *testing.T) {
   664  	err := Unmarshal(nil, nil, "")
   665  	assert.Error(t, err)
   666  	assert.Contains(t, err.Error(), "Failed to unmarshal ")
   667  }
   668  
   669  func TestStrContainedInvalidArgs(t *testing.T) {
   670  	res := StrContained("Hello World", nil)
   671  	assert.False(t, res)
   672  }
   673  
   674  func TestGetSerialAsHex(t *testing.T) {
   675  	res := GetSerialAsHex(big.NewInt(101))
   676  	assert.Equal(t, "65", res)
   677  }
   678  
   679  func TestECPrivateKey(t *testing.T) {
   680  	_, err := GetECPrivateKey(getPEM("../testdata/ec-key.pem", t))
   681  	assert.NoError(t, err)
   682  
   683  	rsaKey, err := rsa.GenerateKey(rand.Reader, 256)
   684  	if err != nil {
   685  		t.Fatalf("Failed to create rsa key: %s", err.Error())
   686  	}
   687  	encodedPK, err := x509.MarshalPKCS8PrivateKey(rsaKey)
   688  	if err != nil {
   689  		t.Fatalf("Failed to marshal RSA private key: %s", err.Error())
   690  	}
   691  
   692  	pemEncodedPK := pem.EncodeToMemory(&pem.Block{Type: "PRIVATE KEY", Bytes: encodedPK})
   693  	_, err = GetECPrivateKey(pemEncodedPK)
   694  	assert.Error(t, err)
   695  
   696  	_, err = GetECPrivateKey([]byte("hello"))
   697  	assert.Error(t, err)
   698  
   699  	_, err = GetECPrivateKey(pem.EncodeToMemory(&pem.Block{Type: "PRIVATE KEY", Bytes: []byte("hello")}))
   700  	assert.Error(t, err)
   701  }
   702  
   703  func TestPKCS8WrappedECPrivateKey(t *testing.T) {
   704  	_, err := GetECPrivateKey(getPEM("../testdata/pkcs8eckey.pem", t))
   705  	assert.NoError(t, err)
   706  }
   707  
   708  func TestRSAPrivateKey(t *testing.T) {
   709  	_, err := GetRSAPrivateKey([]byte("hello"))
   710  	assert.Error(t, err)
   711  
   712  	_, err = GetRSAPrivateKey(getPEM("../testdata/rsa-key.pem", t))
   713  	assert.NoError(t, err)
   714  
   715  	rsaKey, err := rsa.GenerateKey(rand.Reader, 256)
   716  	if err != nil {
   717  		t.Fatalf("Failed to create rsa key: %s", err.Error())
   718  	}
   719  	encodedPK, err := x509.MarshalPKCS8PrivateKey(rsaKey)
   720  	if err != nil {
   721  		t.Fatalf("Failed to marshal RSA private key: %s", err.Error())
   722  	}
   723  
   724  	pemEncodedPK := pem.EncodeToMemory(&pem.Block{Type: "PRIVATE KEY", Bytes: encodedPK})
   725  	_, err = GetRSAPrivateKey(pemEncodedPK)
   726  	assert.NoError(t, err)
   727  
   728  	_, err = GetRSAPrivateKey(pem.EncodeToMemory(&pem.Block{Type: "PRIVATE KEY", Bytes: []byte("hello")}))
   729  	assert.Error(t, err)
   730  
   731  	ecdsaKey, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
   732  	if err != nil {
   733  		t.Fatalf("Failed to create rsa key: %s", err.Error())
   734  	}
   735  	encodedPK, err = x509.MarshalPKCS8PrivateKey(ecdsaKey)
   736  	if err != nil {
   737  		t.Fatalf("Failed to marshal RSA private key: %s", err.Error())
   738  	}
   739  
   740  	pemEncodedPK = pem.EncodeToMemory(&pem.Block{Type: "PRIVATE KEY", Bytes: encodedPK})
   741  	_, err = GetRSAPrivateKey(pemEncodedPK)
   742  	assert.Error(t, err)
   743  }
   744  
   745  func TestCheckHostsInCert(t *testing.T) {
   746  	err := CheckHostsInCert("../testdata/doesnotexist.pem", "")
   747  	assert.Error(t, err)
   748  
   749  	err = CheckHostsInCert("../testdata/tls_server-cert.pem", "localhost")
   750  	assert.NoError(t, err, fmt.Sprintf("Failed to find 'localhost' for host in certificate: %s", err))
   751  
   752  	err = CheckHostsInCert("../testdata/tls_server-cert.pem", "localhost", "fakehost")
   753  	assert.Error(t, err, "Certificate does not contain 'fakehost', should have failed")
   754  
   755  	err = CheckHostsInCert("../testdata/root.pem", "x")
   756  	assert.Error(t, err, "Certificate contained no host, should have failed")
   757  }
   758  
   759  func TestCertDuration(t *testing.T) {
   760  	d, err := GetCertificateDurationFromFile("../testdata/ec.pem")
   761  	assert.NoError(t, err)
   762  	assert.True(t, d.Hours() == 43800, "Expected certificate duration of 43800h in ec.pem")
   763  	_, err = GetCertificateDurationFromFile("bogus.pem")
   764  	assert.Error(t, err)
   765  }
   766  
   767  type MyReader struct {
   768  	buf                   []byte
   769  	maxPerRead, bytesRead int
   770  }
   771  
   772  func (r *MyReader) Read(data []byte) (int, error) {
   773  	if r.bytesRead >= len(r.buf) {
   774  		return 0, io.EOF
   775  	}
   776  	buf := r.buf[r.bytesRead:]
   777  	count := 0
   778  	for i, v := range buf {
   779  		if i >= len(data) || count > r.maxPerRead {
   780  			break
   781  		}
   782  		data[i] = v
   783  		count++
   784  	}
   785  	r.bytesRead = r.bytesRead + count
   786  	return count, nil
   787  }
   788  
   789  func TestRead(t *testing.T) {
   790  	myReader := MyReader{
   791  		buf:        []byte("123456789012345"),
   792  		maxPerRead: 6,
   793  	}
   794  
   795  	// Test with a buffer that is too small to fit data
   796  	buf := make([]byte, 10)
   797  	data, err := Read(&myReader, buf)
   798  	assert.Error(t, err, "Should have errored, the data passed is bigger than the buffer")
   799  
   800  	// Test with a buffer that is big enough to fit data
   801  	buf = make([]byte, 25)
   802  	myReader.bytesRead = 0
   803  	data, err = Read(&myReader, buf)
   804  	if assert.NoError(t, err, fmt.Sprintf("Error occured during read: %s", err)) {
   805  		if string(data) != string(myReader.buf) {
   806  			t.Error("The data returned does not match")
   807  		}
   808  	}
   809  
   810  	// Test with a buffer with exact size of data
   811  	buf = make([]byte, len(myReader.buf))
   812  	myReader.bytesRead = 0
   813  	data, err = Read(&myReader, buf)
   814  	if assert.NoError(t, err, fmt.Sprintf("Error occured during exact size read: %s", err)) {
   815  		if string(data) != string(myReader.buf) {
   816  			t.Error("The data returned does not match")
   817  		}
   818  	}
   819  }
   820  
   821  func getPEM(file string, t *testing.T) []byte {
   822  	buf, err := ioutil.ReadFile(file)
   823  	assert.NoError(t, err)
   824  	return buf
   825  }
   826  
   827  func TestIsSubsetOf(t *testing.T) {
   828  	testIsSubsetOf(t, "a,b", "b,a,c", true)
   829  	testIsSubsetOf(t, "a,b", "b,a", true)
   830  	testIsSubsetOf(t, "a,b,c", "a,b", false)
   831  	testIsSubsetOf(t, "a,b,c", "", false)
   832  }
   833  
   834  func testIsSubsetOf(t *testing.T, small, large string, expectToPass bool) {
   835  	err := IsSubsetOf(small, large)
   836  	if expectToPass {
   837  		if err != nil {
   838  			t.Errorf("IsSubsetOf('%s','%s') failed: %s", small, large, err)
   839  		}
   840  	} else {
   841  		if err == nil {
   842  			t.Errorf("IsSubsetOf('%s','%s') expected error but passed", small, large)
   843  		}
   844  	}
   845  }
   846  
   847  func TestHostname(t *testing.T) {
   848  	host := Hostname()
   849  	assert.NotEqual(t, "", host, "Hostname should not be empty")
   850  }
   851  
   852  func TestHTTPRequestToString(t *testing.T) {
   853  	url := "http://localhost:7054"
   854  	reqBody := "Hello"
   855  	req, err := http.NewRequest("POST", url, strings.NewReader(reqBody))
   856  	if err != nil {
   857  		t.Errorf("Failed to create a request: %s", err)
   858  	} else {
   859  		reqStr := HTTPRequestToString(req)
   860  		assert.Contains(t, reqStr, url)
   861  		assert.Contains(t, reqStr, "POST")
   862  		assert.Contains(t, reqStr, reqBody)
   863  	}
   864  }
   865  
   866  func TestValidateAndReturnAbsConf(t *testing.T) {
   867  	var err error
   868  	var filename, homeDir string
   869  
   870  	filename, _, err = ValidateAndReturnAbsConf("/tmp/test.yaml", "/tmp/homeDir", "fabric-ca-client")
   871  	assert.NoError(t, err, "Should not have errored out, this is a valid configuration")
   872  
   873  	if filename != "/tmp/test.yaml" {
   874  		t.Error("Failed to get correct path for configuration file")
   875  	}
   876  
   877  	filename, homeDir, err = ValidateAndReturnAbsConf("", "../testdata/tmp", "fabric-ca-client")
   878  	assert.NoError(t, err, "Should not have errored out, this is a valid configuration")
   879  
   880  	homeDirAbs, err := filepath.Abs("../testdata/tmp")
   881  	if err != nil {
   882  		t.Fatal("Error occured getting absolute path: ", err)
   883  	}
   884  
   885  	if homeDir != homeDirAbs {
   886  		t.Error("Failed to get correct path for home directory")
   887  	}
   888  
   889  	if filename != filepath.Join(homeDirAbs, "fabric-ca-client-config.yaml") {
   890  		t.Error("Failed to get correct path for configuration file")
   891  	}
   892  
   893  	// Test with no home directory set
   894  	filename, _, err = ValidateAndReturnAbsConf("/tmp/test.yaml", "", "fabric-ca-client")
   895  	assert.NoError(t, err, "Should not have errored out, this is a valid configuration")
   896  
   897  	if filename != "/tmp/test.yaml" {
   898  		t.Error("Failed to get correct path for configuration file")
   899  	}
   900  
   901  	filename, homeDir, err = ValidateAndReturnAbsConf("../testdata/tmp/test.yaml", "", "fabric-ca-client")
   902  	assert.NoError(t, err, "Should not have errored out, this is a valid configuration")
   903  
   904  	homeDirAbs, err = filepath.Abs("../testdata/tmp")
   905  	if err != nil {
   906  		t.Fatal("Error occured getting absolute path: ", err)
   907  	}
   908  
   909  	if homeDir != homeDirAbs {
   910  		t.Error("Failed to get correct path for home directory")
   911  	}
   912  
   913  	if filename != filepath.Join(homeDirAbs, "test.yaml") {
   914  		t.Error("Failed to get correct path for configuration file")
   915  	}
   916  }
   917  
   918  func TestListContains(t *testing.T) {
   919  	list := "peer, client,orderer, *"
   920  	found := ListContains(list, "*")
   921  	assert.Equal(t, found, true)
   922  
   923  	list = "peer, client,orderer"
   924  	found = ListContains(list, "*")
   925  	assert.Equal(t, found, false)
   926  }