github.com/hxx258456/fabric-ca-gm@v0.0.3-0.20221111064038-a268ad7e3a37/internal/pkg/util/util_test.go (about)

     1  /*
     2  Copyright IBM Corp. All Rights Reserved.
     3  
     4  SPDX-License-Identifier: Apache-2.0
     5  */
     6  
     7  package util
     8  
     9  import (
    10  	"crypto/rand"
    11  	"crypto/rsa"
    12  	"encoding/pem"
    13  	"fmt"
    14  	"io/ioutil"
    15  	"math/big"
    16  	"os"
    17  	"path/filepath"
    18  	"strings"
    19  	"testing"
    20  
    21  	http "github.com/hxx258456/ccgo/gmhttp"
    22  
    23  	"github.com/hxx258456/ccgo/x509"
    24  
    25  	"github.com/hxx258456/fabric-gm/bccsp/factory"
    26  	"github.com/spf13/viper"
    27  	"github.com/stretchr/testify/assert"
    28  )
    29  
    30  // TODO(mjs): So many tests that aren't. These need to be reviewed to ensure
    31  // that the tests are driving out the correct paths and assertions as there
    32  // are some obvious deficiencies.
    33  
    34  func TestGetEnrollmentIDFromPEM(t *testing.T) {
    35  	cert, err := ioutil.ReadFile(filepath.Join("testdata", "ec.pem"))
    36  	assert.NoError(t, err)
    37  
    38  	_, err = GetEnrollmentIDFromPEM(cert)
    39  	assert.NoError(t, err, "failed to get enrollment ID from PEM")
    40  }
    41  
    42  func TestECCreateToken(t *testing.T) {
    43  	bccsp := GetDefaultBCCSP()
    44  	privKey, err := ImportBCCSPKeyFromPEM(filepath.Join("testdata", "ec-key.pem"), bccsp, true)
    45  	assert.NoError(t, err, "failed to import key")
    46  
    47  	cert, err := ioutil.ReadFile(filepath.Join("testdata", "ec.pem"))
    48  	assert.NoError(t, err)
    49  	body := []byte("request byte array")
    50  
    51  	tok, err := CreateToken(bccsp, cert, privKey, "GET", "/enroll", body)
    52  	assert.NoError(t, err, "CreateToken failed")
    53  
    54  	os.Setenv("FABRIC_CA_SERVER_COMPATIBILITY_MODE_V1_3", "false") // Test new token
    55  	_, err = VerifyTokenFromHttpRequest(bccsp, tok, "GET", "/enroll", body, false)
    56  	assert.NoError(t, err, "VerifyToken failed")
    57  
    58  	_, err = VerifyTokenFromHttpRequest(nil, tok, "GET", "/enroll", body, false)
    59  	assert.Error(t, err, "VerifyToken should have failed as no instance of CSP was provided")
    60  
    61  	_, err = VerifyTokenFromHttpRequest(bccsp, "", "GET", "/enroll", body, false)
    62  	assert.Error(t, err, "VerifyToken should have failed as no EC token was provided")
    63  
    64  	_, err = VerifyTokenFromHttpRequest(bccsp, tok, "GET", "/enroll", nil, false)
    65  	assert.Error(t, err, "VerifyToken should have failed as no body was provided")
    66  
    67  	_, err = VerifyTokenFromHttpRequest(bccsp, tok, "POST", "/enroll", body, false)
    68  	assert.Error(t, err, "VerifyToken should have failed as the method was changed")
    69  
    70  	_, err = VerifyTokenFromHttpRequest(bccsp, tok, "GET", "/affiliations", body, false)
    71  	assert.Error(t, err, "VerifyToken should have failed as the path was changed")
    72  
    73  	_, err = VerifyTokenFromHttpRequest(bccsp, tok, "GET", "/enroll", append(body, byte('T')), false)
    74  	assert.Error(t, err, "VerifyToken should have failed as the body was changed")
    75  
    76  	ski, err := ioutil.ReadFile(filepath.Join("testdata", "ec-key.ski"))
    77  	assert.NoError(t, err, "failed to read ec-key.ski")
    78  
    79  	tok, err = CreateToken(bccsp, ski, privKey, "GET", "/enroll", body)
    80  	assert.Error(t, err, "CreateToken should have failed with non-certificate")
    81  	assert.Equal(t, "", tok)
    82  
    83  	// With comptability mode disabled, using old token should fail
    84  	b64Cert := B64Encode(cert)
    85  	payload := B64Encode(body) + "." + b64Cert
    86  	oldToken, err := genSM2Token(bccsp, privKey, b64Cert, payload)
    87  	FatalError(t, err, "Failed to create token")
    88  	_, err = VerifyTokenFromHttpRequest(bccsp, oldToken, "GET", "/enroll", body, false)
    89  	assert.Error(t, err)
    90  
    91  	// Test that by default with no environment variable set, the old token is considered valid
    92  	os.Unsetenv("FABRIC_CA_SERVER_COMPATIBILITY_MODE_V1_3")
    93  	_, err = VerifyTokenFromHttpRequest(bccsp, oldToken, "GET", "/enroll", body, true)
    94  	assert.NoError(t, err, "Failed to verify token using old token type")
    95  }
    96  
    97  func TestDecodeToken(t *testing.T) {
    98  	token := "x.y.z"
    99  	_, _, _, err := decodeToken(token)
   100  	assert.Error(t, err, "Decode should fail if the token has more than two parts")
   101  
   102  	token = "x"
   103  	_, _, _, err = decodeToken(token)
   104  	assert.Error(t, err, "Decode should fail if the token has less than two parts")
   105  
   106  	token = "x.y"
   107  	_, _, _, err = decodeToken(token)
   108  	assert.Error(t, err, "Decode should fail if the 1st part of the token is not in base64 encoded format")
   109  
   110  	fakecert := B64Encode([]byte("hello"))
   111  	token = fakecert + ".y"
   112  	_, _, _, err = decodeToken(token)
   113  	assert.Error(t, err, "Decode should fail if the 1st part of the token is not base64 bytes of a X509 cert")
   114  }
   115  
   116  func TestGetX509CertFromPem(t *testing.T) {
   117  	certBuffer, err := ioutil.ReadFile(filepath.Join("testdata", "ec.pem"))
   118  	assert.NoError(t, err)
   119  
   120  	certificate, err := GetX509CertificateFromPEM(certBuffer)
   121  	assert.NoError(t, err, "GetX509CertificateFromPEM failed")
   122  	assert.NotNil(t, certificate, "certificate cannot be nil")
   123  
   124  	skiBuffer, err := ioutil.ReadFile(filepath.Join("testdata", "ec-key.ski"))
   125  	assert.NoError(t, err)
   126  
   127  	certificate, err = GetX509CertificateFromPEM(skiBuffer)
   128  	assert.Error(t, err, "GetX509CertificateFromPEM should have failed as bytes passed was not in correct format")
   129  	assert.Nil(t, certificate, "GetX509CertificateFromPEM should have failed as bytes passed was not in correct format")
   130  }
   131  
   132  func TestGetX509CertsFromPem(t *testing.T) {
   133  	certBuffer, err := ioutil.ReadFile(filepath.Join("testdata", "ec.pem"))
   134  	assert.NoError(t, err)
   135  
   136  	certificates, err := GetX509CertificatesFromPEM(certBuffer)
   137  	assert.NoError(t, err, "GetX509CertificatesFromPEM failed")
   138  	assert.NotNil(t, certificates)
   139  	assert.Equal(t, 1, len(certificates), "GetX509CertificatesFromPEM should have returned 1 certificate")
   140  
   141  	skiBuffer, err := ioutil.ReadFile(filepath.Join("testdata", "ec-key.ski"))
   142  	assert.NoError(t, err)
   143  
   144  	certificates, err = GetX509CertificatesFromPEM(skiBuffer)
   145  	assert.Error(t, err, "GetX509CertificatesFromPEM should have failed as bytes passed was not in correct format")
   146  	assert.Nil(t, certificates, "GetX509CertificatesFromPEM should have failed as bytes passed was not in correct format")
   147  }
   148  
   149  // TODO(mjs): This isn't testing what it claims to test. RSA keys cannot be
   150  // imported so privKey is nil when CreateToken is called.
   151  
   152  // func TestCreateTokenDiffKey(t *testing.T) {
   153  // 	cert, _ := ioutil.ReadFile(filepath.Join("testdata", "ec.pem"))
   154  // 	bccsp := GetDefaultBCCSP()
   155  // 	privKey, _ := ImportBCCSPKeyFromPEM(filepath.Join("testdata", "rsa-key.pem"), bccsp, true)
   156  // 	body := []byte("request byte array")
   157  // 	_, err := CreateToken(bccsp, cert, privKey, "POST", "/enroll", body)
   158  // 	if err == nil {
   159  // 		t.Fatalf("TestCreateTokenDiffKey passed but should have failed")
   160  // 	}
   161  // }
   162  
   163  func TestEmptyToken(t *testing.T) {
   164  	csp := factory.GetDefault()
   165  	_, err := VerifyTokenFromHttpRequest(csp, "", "POST", "/enroll", []byte("request-body"), true)
   166  	assert.Error(t, err, "verification should fail with an empty token")
   167  }
   168  
   169  func TestEmptyCert(t *testing.T) {
   170  	cert, err := ioutil.ReadFile(filepath.Join("testdata", "ec.pem"))
   171  	assert.NoError(t, err)
   172  
   173  	csp := factory.GetDefault()
   174  	_, err = CreateToken(csp, cert, nil, "POST", "/enroll", []byte("request body"))
   175  	assert.Error(t, err, "CreateToken should have failed with nil key")
   176  }
   177  
   178  func TestEmptyKey(t *testing.T) {
   179  	bccsp := GetDefaultBCCSP()
   180  	privKey, err := ImportBCCSPKeyFromPEM(filepath.Join("testdata", "ec-key.pem"), bccsp, true)
   181  	assert.NoError(t, err)
   182  
   183  	_, err = CreateToken(bccsp, []byte(""), privKey, "POST", "/enroll", []byte("request body"))
   184  	assert.Error(t, err, "CreateToken should have failed with empty certificate")
   185  }
   186  
   187  func TestEmptyBody(t *testing.T) {
   188  	bccsp := GetDefaultBCCSP()
   189  	privKey, err := ImportBCCSPKeyFromPEM(filepath.Join("testdata", "ec-key.pem"), bccsp, true)
   190  	assert.NoError(t, err)
   191  	cert, err := ioutil.ReadFile(filepath.Join("testdata", "ec.pem"))
   192  	assert.NoError(t, err)
   193  
   194  	_, err = CreateToken(bccsp, cert, privKey, "POST", "/enroll", []byte(""))
   195  	assert.NoError(t, err, "create token should succeed with empty body")
   196  }
   197  
   198  func TestRandomString(t *testing.T) {
   199  	for i := 0; i <= 10; i++ {
   200  		str := RandomString(i)
   201  		assert.Equal(t, i, len(str))
   202  	}
   203  }
   204  
   205  func TestCreateHome(t *testing.T) {
   206  	tempDir, err := ioutil.TempDir("", "test")
   207  	assert.NoError(t, err, "failed to create temporary directory")
   208  	defer os.RemoveAll(tempDir)
   209  
   210  	os.Setenv("HOME", tempDir)
   211  	dir, err := CreateClientHome()
   212  	assert.NoError(t, err, "Failed to create home directory, error: %s")
   213  	assert.Equal(t, filepath.Join(tempDir, ".fabric-ca-client"), dir)
   214  	assert.DirExists(t, dir, "client home directory was not created")
   215  }
   216  
   217  func TestGetDefaultConfigFile(t *testing.T) {
   218  	os.Unsetenv("FABRIC_CA_HOME")
   219  	os.Unsetenv("FABRIC_CA_CLIENT_HOME")
   220  	os.Unsetenv("FABRIC_CA_SERVER_HOME")
   221  	os.Unsetenv("CA_CFG_PATH")
   222  
   223  	const clientConfig = "fabric-ca-client-config.yaml"
   224  	const serverConfig = "fabric-ca-server-config.yaml"
   225  
   226  	os.Setenv("HOME", "/tmp")
   227  
   228  	expected := filepath.Join("/tmp/.fabric-ca-client/", clientConfig)
   229  	actual := GetDefaultConfigFile("fabric-ca-client")
   230  	assert.Equal(t, expected, actual, "incorrect default config path")
   231  
   232  	os.Setenv("FABRIC_CA_HOME", "/tmp")
   233  	expected = filepath.Join("/tmp", clientConfig)
   234  	actual = GetDefaultConfigFile("fabric-ca-client")
   235  	assert.Equal(t, expected, actual, "incorrect default config path")
   236  
   237  	expected = filepath.Join("/tmp", serverConfig)
   238  	actual = GetDefaultConfigFile("fabric-ca-server")
   239  	assert.Equal(t, expected, actual, "incorrect default config path")
   240  
   241  	os.Setenv("FABRIC_CA_CLIENT_HOME", "/tmp/client")
   242  	expected = filepath.Join("/tmp/client", clientConfig)
   243  	actual = GetDefaultConfigFile("fabric-ca-client")
   244  	assert.Equal(t, expected, actual, "incorrect default config path")
   245  
   246  	os.Setenv("FABRIC_CA_SERVER_HOME", "/tmp/server")
   247  	expected = filepath.Join("/tmp/server", serverConfig)
   248  	actual = GetDefaultConfigFile("fabric-ca-server")
   249  	assert.Equal(t, expected, actual, "incorrect default config path")
   250  }
   251  
   252  // TODO(mjs): Move the implementation to the consumer(s). The majority of the
   253  // users are in the client pacakge and all the code does is annotate error
   254  // messages and hide the fact that the serialization format is JSON.
   255  // Oh, and the test doesn't even test the error wrapping aspect...
   256  func TestUnmarshal(t *testing.T) {
   257  	byteArray := []byte(`{"text":"foo"}`)
   258  	var test struct {
   259  		Text string
   260  	}
   261  	err := Unmarshal(byteArray, &test, "testing unmarshal")
   262  	assert.NoError(t, err, "failed to unmarshal")
   263  	assert.Equal(t, "foo", test.Text)
   264  }
   265  
   266  func TestUnmarshalInvalidArgs(t *testing.T) {
   267  	err := Unmarshal(nil, nil, "")
   268  	assert.Error(t, err)
   269  	assert.Contains(t, err.Error(), "Failed to unmarshal ")
   270  }
   271  
   272  // TODO(mjs): Move the implementation to the consumer(s). The majority of the
   273  // users are in the 'lib' pacakge and all the code does is annotate error
   274  // messages and hide the fact that the serialization format is JSON.
   275  // Oh, and the test doesn't even test the error wrapping aspect...
   276  func TestMarshal(t *testing.T) {
   277  	var x interface{}
   278  	_, err := Marshal(x, "testing marshal")
   279  	assert.NoError(t, err, "failed to marshal")
   280  }
   281  
   282  // TODO(mjs): Get rid of this. It's literally a call to ioutil.ReadFile.
   283  func TestReadFile(t *testing.T) {
   284  	_, err := ReadFile(filepath.Join("testdata", "csr.json"))
   285  	assert.NoError(t, err, "failed to read file")
   286  }
   287  
   288  func TestWriteFile(t *testing.T) {
   289  	testdir, err := ioutil.TempDir("", "writefiletest")
   290  	assert.NoError(t, err)
   291  	defer os.RemoveAll(testdir)
   292  
   293  	testData := []byte("foo")
   294  	err = WriteFile(filepath.Join(testdir, "test.txt"), testData, 0777)
   295  	assert.NoError(t, err)
   296  
   297  	readOnlyDir := filepath.Join(testdir, "readonlydir")
   298  	err = os.MkdirAll(readOnlyDir, 4444)
   299  	assert.NoError(t, err, "failed to create read only directory")
   300  	err = WriteFile(filepath.Join(readOnlyDir, "test/test.txt"), testData, 0777)
   301  	assert.Error(t, err, "Should fail to create 'test' directory as the parent directory is read only")
   302  }
   303  
   304  func TestFileExists(t *testing.T) {
   305  	name := filepath.Join("testdata", "csr.json")
   306  	exists := FileExists(name)
   307  	assert.True(t, exists, "%s should be an existing file", name)
   308  
   309  	exists = FileExists("better-not-exist")
   310  	assert.False(t, exists, "better-not-exist should not be an existing file")
   311  }
   312  
   313  func testMakeFileAbs(t *testing.T, file, dir, expect string) {
   314  	path, err := MakeFileAbs(file, dir)
   315  	assert.NoError(t, err, "failed to make %s absolute", file)
   316  	assert.Equal(t, expect, path, "unexpected absolute path for file %q in directory %q", file, dir)
   317  }
   318  
   319  func TestMakeFileAbs(t *testing.T) {
   320  	testMakeFileAbs(t, "", "", "")
   321  	testMakeFileAbs(t, "/a/b/c", "", "/a/b/c")
   322  	testMakeFileAbs(t, "c", "/a/b", "/a/b/c")
   323  	testMakeFileAbs(t, "../c", "/a/b", "/a/c")
   324  }
   325  
   326  func TestMakeFilesAbs(t *testing.T) {
   327  	file1 := "a"
   328  	file2 := "a/b"
   329  	file3 := "/a/b"
   330  	files := []*string{&file1, &file2, &file3}
   331  	err := MakeFileNamesAbsolute(files, "/tmp")
   332  	assert.NoError(t, err, "MakeFileNamesAbsolute failed")
   333  
   334  	assert.Equal(t, "/tmp/a", file1)
   335  	assert.Equal(t, "/tmp/a/b", file2)
   336  	assert.Equal(t, "/a/b", file3)
   337  }
   338  
   339  func TestB64(t *testing.T) {
   340  	// FIXME(mjs): And this tests the standard library...
   341  	buf := []byte("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ")
   342  	str := B64Encode(buf)
   343  	buf2, err := B64Decode(str)
   344  	assert.NoError(t, err, "failed base64 decoding")
   345  	assert.Equal(t, buf, buf2)
   346  }
   347  
   348  func TestGetUser(t *testing.T) {
   349  	v := viper.New()
   350  	os.Unsetenv("FABRIC_CA_CLIENT_URL")
   351  	err := v.BindEnv("url", "FABRIC_CA_CLIENT_URL")
   352  	assert.NoError(t, err)
   353  
   354  	os.Setenv("FABRIC_CA_CLIENT_URL", "http://localhost:7054")
   355  	_, _, err = GetUser(v)
   356  	assert.Error(t, err, "Should have failed no username and password provided")
   357  
   358  	os.Setenv("FABRIC_CA_CLIENT_URL", "http://:pass@localhost:7054")
   359  	_, _, err = GetUser(v)
   360  	assert.Error(t, err, "Should have failed no username provided")
   361  
   362  	os.Setenv("FABRIC_CA_CLIENT_URL", "http://user:@localhost:7054")
   363  	_, _, err = GetUser(v)
   364  	assert.Error(t, err, "Should have failed no password provided")
   365  
   366  	os.Setenv("FABRIC_CA_CLIENT_URL", "http://foo:bar@localhost:7054")
   367  	user, pass, err := GetUser(v)
   368  	assert.NoError(t, err)
   369  	assert.Equal(t, "foo", user, "unexpected username")
   370  	assert.Equal(t, "bar", pass, "unexpected password")
   371  }
   372  
   373  type masked struct {
   374  	Name string `mask:"username"`
   375  	Addr string `json:"address"`
   376  	Pass string `mask:"password"`
   377  	URL  string `mask:"url"`
   378  	ID   int    `mask:"url"`
   379  }
   380  
   381  func (cc masked) String() string {
   382  	return StructToString(&cc)
   383  }
   384  
   385  func TestStructToString(t *testing.T) {
   386  	obj := masked{
   387  		Name: "foo",
   388  		Addr: "101, penn ave",
   389  		Pass: "bar",
   390  		URL:  "http://bang:bazzword@localhost:7054",
   391  	}
   392  	str := StructToString(&obj)
   393  	assert.NotContains(t, str, "bar", "password is not masked")
   394  	assert.NotContains(t, str, "foo", "name is not masked")
   395  	assert.Contains(t, str, obj.Addr, "address should not be masked")
   396  	assert.NotContains(t, str, "bang", "user from url is not masked in the output")
   397  	assert.NotContains(t, str, "bazzword", "password from url is not masked in the output")
   398  
   399  	type registry struct{ Identities []masked }
   400  	type config struct{ Registry registry }
   401  	caConfig := config{
   402  		Registry: registry{
   403  			Identities: []masked{
   404  				{
   405  					Name: "foo",
   406  					Pass: "foopwd",
   407  					Addr: "user",
   408  					URL:  "http://foo:foopwd@localhost:7054",
   409  					ID:   2,
   410  				},
   411  				{
   412  					Name: "bar",
   413  					Pass: "barpwd",
   414  					Addr: "user",
   415  					URL:  "ldap://foo:foopwd@localhost:7054",
   416  					ID:   3,
   417  				},
   418  			},
   419  		},
   420  	}
   421  	caConfigStr := fmt.Sprintf("caConfig=%+v", caConfig)
   422  	assert.NotContains(t, caConfigStr, "foopwd", "Identity password is not masked in the output")
   423  	assert.NotContains(t, caConfigStr, "barpwd", "Identity password is not masked in the output")
   424  	assert.NotContains(t, caConfig.Registry.Identities[0].String(), "foopwd", "Identity password is not masked in the output")
   425  	assert.NotContains(t, caConfig.Registry.Identities[1].String(), "barpwd", "Identity password is not masked in the output")
   426  }
   427  
   428  func TestNormalizeStringSlice(t *testing.T) {
   429  	var tests = []struct {
   430  		slice    []string
   431  		expected []string
   432  	}{
   433  		{
   434  			slice:    []string{"string1"},
   435  			expected: []string{"string1"},
   436  		},
   437  		{
   438  			slice:    []string{" string1"},
   439  			expected: []string{"string1"},
   440  		},
   441  		{
   442  			slice:    []string{" string1   "},
   443  			expected: []string{"string1"},
   444  		},
   445  		{
   446  			slice:    []string{" string1   "},
   447  			expected: []string{"string1"},
   448  		},
   449  		{
   450  			slice:    []string{"string1", "string2"},
   451  			expected: []string{"string1", "string2"},
   452  		},
   453  		{
   454  			slice:    []string{"string1", "   string2"},
   455  			expected: []string{"string1", "string2"},
   456  		},
   457  	}
   458  
   459  	for _, test := range tests {
   460  		actual := NormalizeStringSlice(test.slice)
   461  		assert.Equal(t, test.expected, actual)
   462  	}
   463  }
   464  
   465  // Test file list with multiple and single entries both with and without brackets
   466  func TestNormalizeFileList(t *testing.T) {
   467  	slice := []string{"[file0,file1]", "file2,file3", "file4", "[file5]"}
   468  	slice, err := NormalizeFileList(slice, "testdata")
   469  	assert.NoError(t, err, "failed to normalize files list")
   470  	assert.Len(t, slice, 6, "Invalid slice length")
   471  
   472  	dataDir, err := filepath.Abs("testdata")
   473  	assert.NoError(t, err)
   474  	for i := range slice {
   475  		assert.Equal(t, dataDir, filepath.Dir(slice[i]))
   476  		assert.Equal(t, fmt.Sprintf("file%d", i), filepath.Base(slice[i]))
   477  	}
   478  }
   479  
   480  func TestGetSerialAsHex(t *testing.T) {
   481  	res := GetSerialAsHex(big.NewInt(101))
   482  	assert.Equal(t, "65", res)
   483  }
   484  
   485  func TestECPrivateKey(t *testing.T) {
   486  	_, err := GetECPrivateKey(getPEM(filepath.Join("testdata", "ec-key.pem"), t))
   487  	assert.NoError(t, err)
   488  
   489  	rsaKey, err := rsa.GenerateKey(rand.Reader, 256)
   490  	assert.NoError(t, err, "failed to create RSA key")
   491  	encodedPK, err := x509.MarshalPKCS8PrivateKey(rsaKey)
   492  	assert.NoError(t, err, "failed to marshal RSA private key")
   493  
   494  	pemEncodedPK := pem.EncodeToMemory(&pem.Block{Type: "PRIVATE KEY", Bytes: encodedPK})
   495  	_, err = GetECPrivateKey(pemEncodedPK)
   496  	assert.Error(t, err)
   497  
   498  	_, err = GetECPrivateKey([]byte("hello"))
   499  	assert.Error(t, err)
   500  
   501  	_, err = GetECPrivateKey(pem.EncodeToMemory(&pem.Block{Type: "PRIVATE KEY", Bytes: []byte("hello")}))
   502  	assert.Error(t, err)
   503  }
   504  
   505  func TestPKCS8WrappedECPrivateKey(t *testing.T) {
   506  	_, err := GetECPrivateKey(getPEM(filepath.Join("testdata", "pkcs8eckey.pem"), t))
   507  	assert.NoError(t, err)
   508  }
   509  
   510  // func TestRSAPrivateKey(t *testing.T) {
   511  // 	_, err := GetRSAPrivateKey([]byte("hello"))
   512  // 	assert.Error(t, err)
   513  
   514  // 	_, err = GetRSAPrivateKey(getPEM(filepath.Join("testdata", "rsa-key.pem"), t))
   515  // 	assert.NoError(t, err)
   516  
   517  // 	rsaKey, err := rsa.GenerateKey(rand.Reader, 256)
   518  // 	assert.NoError(t, err, "failed to create RSA key")
   519  // 	encodedPK, err := x509.MarshalPKCS8PrivateKey(rsaKey)
   520  // 	assert.NoError(t, err, "failed to marshal RSA private key")
   521  
   522  // 	pemEncodedPK := pem.EncodeToMemory(&pem.Block{Type: "PRIVATE KEY", Bytes: encodedPK})
   523  // 	_, err = GetRSAPrivateKey(pemEncodedPK)
   524  // 	assert.NoError(t, err)
   525  
   526  // 	_, err = GetRSAPrivateKey(pem.EncodeToMemory(&pem.Block{Type: "PRIVATE KEY", Bytes: []byte("hello")}))
   527  // 	assert.Error(t, err)
   528  
   529  // 	ecdsaKey, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
   530  // 	assert.NoError(t, err, "failed to generate P256 key")
   531  // 	encodedPK, err = x509.MarshalPKCS8PrivateKey(ecdsaKey)
   532  // 	assert.NoError(t, err, "failed to marshal P256 private key")
   533  
   534  // 	pemEncodedPK = pem.EncodeToMemory(&pem.Block{Type: "PRIVATE KEY", Bytes: encodedPK})
   535  // 	_, err = GetRSAPrivateKey(pemEncodedPK)
   536  // 	assert.Error(t, err, "treating P56 key as RSA private key should fail")
   537  // }
   538  
   539  func TestCheckHostsInCert(t *testing.T) {
   540  	err := CheckHostsInCert("testdata/doesnotexist.pem", "")
   541  	assert.Error(t, err) // TODO(mjs): clearly any error will do
   542  
   543  	err = CheckHostsInCert(filepath.Join("testdata", "tls_server-cert.pem"), "localhost")
   544  	assert.NoError(t, err, "failed to find 'localhost' in certificate")
   545  
   546  	err = CheckHostsInCert("testdata/tls_server-cert.pem", "localhost", "fakehost")
   547  	assert.Error(t, err, "certificate does not contain 'fakehost', should have failed")
   548  
   549  	err = CheckHostsInCert("testdata/root.pem", "x")
   550  	assert.Error(t, err, "certificate contained no host, should have failed")
   551  }
   552  
   553  func TestCertDuration(t *testing.T) {
   554  	d, err := GetCertificateDurationFromFile(filepath.Join("testdata", "ec.pem"))
   555  	assert.NoError(t, err)
   556  	assert.EqualValues(t, 43800, d.Hours(), "Expected certificate duration of 43800h in ec.pem")
   557  
   558  	_, err = GetCertificateDurationFromFile("bogus.pem")
   559  	assert.Error(t, err) // TODO(mjs): clearly any error will do
   560  }
   561  
   562  func TestRead(t *testing.T) {
   563  	// Test with a buffer that is too small to fit data
   564  	buf := make([]byte, 10)
   565  	_, err := Read(strings.NewReader("this-is-longer-than-ten-bytes"), buf)
   566  	assert.Error(t, err, "should have failed with too much data for buffer")
   567  
   568  	// Test with a buffer that is big enough to fit data
   569  	buf = make([]byte, 20)
   570  	data, err := Read(strings.NewReader("short-string"), buf)
   571  	assert.NoError(t, err, "read should have been successful")
   572  	assert.Equal(t, "short-string", string(data), "the read data does not match the source")
   573  
   574  	// Test with a buffer with exact size of data
   575  	buf = make([]byte, 2)
   576  	data, err = Read(strings.NewReader("hi"), buf)
   577  	assert.NoError(t, err, "read should have been successful")
   578  	assert.Equal(t, "hi", string(data), "the read data does not match the source")
   579  }
   580  
   581  func getPEM(file string, t *testing.T) []byte {
   582  	buf, err := ioutil.ReadFile(file)
   583  	assert.NoError(t, err)
   584  	return buf
   585  }
   586  
   587  func TestHostname(t *testing.T) {
   588  	host := Hostname()
   589  	assert.NotEqual(t, "", host, "Hostname should not be empty")
   590  }
   591  
   592  func TestHTTPRequestToString(t *testing.T) {
   593  	url := "http://localhost:7054"
   594  	reqBody := "Hello"
   595  	req, err := http.NewRequest("POST", url, strings.NewReader(reqBody))
   596  	assert.NoError(t, err, "failed to create http.Request")
   597  
   598  	reqStr := HTTPRequestToString(req)
   599  	assert.Contains(t, reqStr, url)
   600  	assert.Contains(t, reqStr, "POST")
   601  	assert.Contains(t, reqStr, reqBody)
   602  }
   603  
   604  func TestValidateAndReturnAbsConf(t *testing.T) {
   605  	var err error
   606  	var filename, homeDir string
   607  
   608  	filename, _, err = ValidateAndReturnAbsConf("/tmp/test.yaml", "/tmp/homeDir", "fabric-ca-client")
   609  	assert.NoError(t, err, "Should not have errored out, this is a valid configuration")
   610  	assert.Equal(t, "/tmp/test.yaml", filename, "failed to get correct path for configuration file")
   611  
   612  	filename, homeDir, err = ValidateAndReturnAbsConf("", "testdata/tmp", "fabric-ca-client")
   613  	assert.NoError(t, err, "should not have failed with a valid configuration")
   614  
   615  	homeDirAbs, err := filepath.Abs("testdata/tmp")
   616  	assert.NoError(t, err)
   617  	assert.Equal(t, homeDirAbs, homeDir, "failed to get correct path for home directory")
   618  	assert.Equal(t, filepath.Join(homeDirAbs, "fabric-ca-client-config.yaml"), filename)
   619  
   620  	// Test with no home directory set
   621  	filename, _, err = ValidateAndReturnAbsConf("/tmp/test.yaml", "", "fabric-ca-client")
   622  	assert.NoError(t, err, "Should not have errored out, this is a valid configuration")
   623  	assert.Equal(t, "/tmp/test.yaml", filename, "failed to get correct path for configuration file")
   624  
   625  	filename, homeDir, err = ValidateAndReturnAbsConf("testdata/tmp/test.yaml", "", "fabric-ca-client")
   626  	assert.NoError(t, err, "should not have failed with a valid configuration")
   627  	assert.Equal(t, homeDirAbs, homeDir, "failed to get correct path for home directory")
   628  	assert.Equal(t, filepath.Join(homeDirAbs, "test.yaml"), filename, "failed to get correct path for configuration file")
   629  }
   630  
   631  func TestListContains(t *testing.T) {
   632  	list := "peer, client,orderer, *"
   633  	found := ListContains(list, "*")
   634  	assert.Equal(t, found, true)
   635  
   636  	list = "peer, client,orderer"
   637  	found = ListContains(list, "*")
   638  	assert.Equal(t, found, false)
   639  }