github.com/canhui/fabric_ca2_2@v2.0.0-alpha+incompatible/lib/ca_test.go (about)

     1  /*
     2  Copyright IBM Corp. 2016 All Rights Reserved.
     3  
     4  SPDX-License-Identifier: Apache-2.0
     5  */
     6  
     7  package lib
     8  
     9  import (
    10  	"crypto/x509"
    11  	"fmt"
    12  	"io/ioutil"
    13  	"os"
    14  	"path"
    15  	"path/filepath"
    16  	"testing"
    17  
    18  	"github.com/cloudflare/cfssl/csr"
    19  	"github.com/hyperledger/fabric-ca/api"
    20  	"github.com/hyperledger/fabric-ca/lib/mocks"
    21  	"github.com/hyperledger/fabric-ca/lib/server/db/sqlite"
    22  	dbutil "github.com/hyperledger/fabric-ca/lib/server/db/util"
    23  	"github.com/hyperledger/fabric-ca/util"
    24  	"github.com/hyperledger/fabric/common/metrics/disabled"
    25  	"github.com/hyperledger/fabric/common/metrics/metricsfakes"
    26  	"github.com/stretchr/testify/assert"
    27  )
    28  
    29  const (
    30  	testdir               = "../testdata/"
    31  	dbname                = "fabric-ca-server.db"
    32  	badcert               = "../testdata/expiredcert.pem"
    33  	dsacert               = "../testdata/dsa-cert.pem"
    34  	lowbitcert            = "../testdata/lowbitcert.pem"
    35  	ecPrivKeyNotMatching  = "../testdata/ec-key.pem"
    36  	ecCert                = "../testdata/ec_cert.pem"
    37  	ecPrivKeyMatching     = "../testdata/ec_key.pem"
    38  	rsacert               = "../testdata/rsa.pem"
    39  	rsaPrivKeyNotMatching = "../testdata/rsa2048-1-key.pem"
    40  	backDated             = "../testdata/unRipeCaEc256-cert.pem"
    41  	badUsageCert          = "../testdata/tls_client-cert.pem"
    42  	badUsageKey           = "../testdata/tls_client-key.pem"
    43  	noUsageCert           = "../testdata/noKeyUsage.cert.pem"
    44  	noUsageKey            = "../testdata/noKeyUsage.key.pem"
    45  	noCACert              = "../testdata/caFalse.cert.pem"
    46  	noCAkey               = "../testdata/caFalse.key.pem"
    47  	caCert                = "ca-cert.pem"
    48  	caKey                 = "ca-key.pem"
    49  	caPort                = "7054"
    50  )
    51  
    52  var (
    53  	configFile = serverCfgFile(testdir)
    54  )
    55  
    56  var cfg CAConfig
    57  var srv Server
    58  
    59  func TestCABadCACertificates(t *testing.T) {
    60  	srv.levels = &dbutil.Levels{
    61  		Identity:    1,
    62  		Affiliation: 1,
    63  		Certificate: 1,
    64  	}
    65  	mockOperationsServer := &mocks.OperationsServer{}
    66  	fakeCounter := &metricsfakes.Counter{}
    67  	fakeCounter.WithReturns(fakeCounter)
    68  	mockOperationsServer.NewCounterReturns(fakeCounter)
    69  	fakeHistogram := &metricsfakes.Histogram{}
    70  	fakeHistogram.WithReturns(fakeHistogram)
    71  	mockOperationsServer.NewHistogramReturns(fakeHistogram)
    72  
    73  	srv.Operations = mockOperationsServer
    74  	testDirClean(t)
    75  	ca, err := newCA(configFile, &CAConfig{}, &srv, false)
    76  	if err != nil {
    77  		t.Fatal("newCA failed ", err)
    78  	}
    79  	err = ca.validateCertAndKey(noCACert, noCAkey)
    80  	t.Log("validateCertAndKey Error: ", err)
    81  	if err == nil {
    82  		t.Error("Should have failed, non-CA certificate provided")
    83  	}
    84  	err = ca.validateCertAndKey(badUsageCert, badUsageKey)
    85  	t.Log("validateCertAndKey Error: ", err)
    86  	if err == nil {
    87  		t.Error("Should have failed, incorrect keyusage")
    88  	}
    89  
    90  	cert, err := getCertFromFile(noCACert)
    91  	if err != nil {
    92  		t.Fatal(err)
    93  	}
    94  	testValidCA(cert, t)
    95  
    96  	cert, err = getCertFromFile(backDated)
    97  	if err != nil {
    98  		t.Fatal(err)
    99  	}
   100  	testValidDates(cert, t)
   101  
   102  	cert, err = getCertFromFile(badcert)
   103  	if err != nil {
   104  		t.Fatal(err)
   105  	}
   106  	testValidDates(cert, t)
   107  	testValidKeyType(cert, t)
   108  	testValidKeySize(cert, t)
   109  	testValidMatchingKeys(cert, t)
   110  	testValidUsages(cert, t)
   111  	CAclean(ca, t)
   112  }
   113  
   114  func testValidDates(cert *x509.Certificate, t *testing.T) {
   115  	err := validateDates(cert)
   116  	t.Log("validateDates Error: ", err)
   117  	if err == nil {
   118  		t.Error("Should have failed, expired CA certificate provided")
   119  	}
   120  }
   121  
   122  func testValidUsages(cert *x509.Certificate, t *testing.T) {
   123  	err := validateUsage(cert, "")
   124  	t.Log("validateUsage Error: ", err)
   125  	if err == nil {
   126  		t.Error("Should have failed, incorrect usage specified for certificate")
   127  	}
   128  
   129  	cert, err = getCertFromFile(badUsageCert)
   130  	if err != nil {
   131  		t.Fatal(err)
   132  	}
   133  
   134  	err = validateUsage(cert, "")
   135  	t.Log("validateUsage Error: ", err)
   136  	if assert.Error(t, err, "Should have failed, missing 'Cert Sign' key usage") {
   137  		assert.Contains(t, err.Error(), "'cert sign' key usage is required")
   138  	}
   139  }
   140  
   141  func testValidCA(cert *x509.Certificate, t *testing.T) {
   142  	cert.IsCA = false
   143  	err := validateIsCA(cert)
   144  	t.Log("validateIsCA Error: ", err)
   145  	if err == nil {
   146  		t.Error("Should have failed, invalid value for IsCA")
   147  	}
   148  }
   149  
   150  func testValidKeyType(cert *x509.Certificate, t *testing.T) {
   151  	err := validateKeyType(cert)
   152  	if err != nil {
   153  		t.Error("Error occured during validation of a supported key type: ", err)
   154  	}
   155  
   156  	cert, err = getCertFromFile(dsacert)
   157  	if err != nil {
   158  		t.Fatal(err)
   159  	}
   160  
   161  	err = validateKeyType(cert)
   162  	t.Log("validateKeyType-Bad Error: ", err)
   163  	if err == nil {
   164  		t.Error("Should have failed, unsupported key type DSA")
   165  	}
   166  }
   167  
   168  func testValidKeySize(cert *x509.Certificate, t *testing.T) {
   169  	err := validateKeySize(cert)
   170  	if err != nil {
   171  		t.Error("Failed to pass a ceritificate with valid key size: ", err)
   172  	}
   173  
   174  	cert, err = getCertFromFile(lowbitcert)
   175  	if err != nil {
   176  		t.Fatal(err)
   177  	}
   178  
   179  	err = validateKeySize(cert)
   180  	t.Log("validateKeySize Error: ", err)
   181  	if err == nil {
   182  		t.Error("Should have failed, bit size is too low (1024) for certificate")
   183  	}
   184  }
   185  
   186  func testValidMatchingKeys(cert *x509.Certificate, t *testing.T) {
   187  	err := GenerateECDSATestCert()
   188  	util.FatalError(t, err, "Failed to generate certificate for testing")
   189  	cert, err = getCertFromFile(ecCert)
   190  	if err != nil {
   191  		t.Fatal(err)
   192  	}
   193  	err = validateMatchingKeys(cert, ecPrivKeyNotMatching)
   194  	t.Log("validateMatchingKeys Error: ", err)
   195  	if err == nil {
   196  		t.Error("Should have failed, public key and private key do not match")
   197  	}
   198  
   199  	err = validateMatchingKeys(cert, ecPrivKeyMatching)
   200  	if err != nil {
   201  		t.Error("Failed to validate a matching key pair, error: ", err)
   202  	}
   203  
   204  	cert, err = getCertFromFile(rsacert)
   205  	if err != nil {
   206  		t.Fatal(err)
   207  	}
   208  
   209  	err = validateMatchingKeys(cert, rsaPrivKeyNotMatching)
   210  	t.Log("validateMatchingKeys Error: ", err)
   211  	if err == nil {
   212  		t.Error("Should have failed, public key and private key do not match")
   213  	}
   214  
   215  	err = validateMatchingKeys(cert, ecPrivKeyNotMatching)
   216  	t.Log("validateMatchingKeys Error: ", err)
   217  	if err == nil {
   218  		t.Error("Should have failed, public key and private key do not match")
   219  	}
   220  
   221  	err = validateMatchingKeys(cert, string(0))
   222  	t.Log("validateMatchingKeys Error: ", err)
   223  	if err == nil {
   224  		t.Error("Should have failed to read bad file")
   225  	}
   226  
   227  }
   228  
   229  // Tests String method of CAConfigDB
   230  func TestCAConfigDBStringer(t *testing.T) {
   231  	dbconfig := CAConfigDB{
   232  		Type:       "postgres",
   233  		Datasource: "dbname=mypostgres host=127.0.0.1 port=8888 user=admin password=admin sslmode=disable",
   234  	}
   235  	str := fmt.Sprintf("%+v", dbconfig) // String method of CAConfigDB is called here
   236  	t.Logf("Stringified postgres CAConfigDB: %s", str)
   237  	assert.Contains(t, str, "user=****", "Username is not masked in the datasource URL")
   238  	assert.Contains(t, str, "password=****", "Password is not masked in the datasource URL")
   239  
   240  	dbconfig.Datasource = "dbname=mypostgres host=127.0.0.1 port=8888 password=admin sslmode=disable user=admin"
   241  	str = fmt.Sprintf("%+v", dbconfig) // String method of CAConfigDB is called here
   242  	t.Logf("Stringified postgres CAConfigDB: %s", str)
   243  	assert.Contains(t, str, "user=****", "Username is not masked in the datasource URL")
   244  	assert.Contains(t, str, "password=****", "Password is not masked in the datasource URL")
   245  
   246  	dbconfig.Datasource = "dbname=cadb password=adminpwd host=127.0.0.1 port=8888 user=cadb sslmode=disable"
   247  	str = fmt.Sprintf("%+v", dbconfig) // String method of CAConfigDB is called here
   248  	t.Logf("Stringified postgres CAConfigDB: %s", str)
   249  	assert.Contains(t, str, "user=****", "Username is not masked in the datasource URL")
   250  	assert.Contains(t, str, "password=****", "Password is not masked in the datasource URL")
   251  
   252  	dbconfig = CAConfigDB{
   253  		Type:       "mysql",
   254  		Datasource: "root:rootpw@tcp(localhost:8888)/mysqldb?parseTime=true",
   255  	}
   256  	str = fmt.Sprintf("%+v", dbconfig)
   257  	t.Logf("Stringified mysql CAConfigDB: %s", str)
   258  	assert.NotContains(t, str, "root", "Username is not masked in the datasource URL")
   259  	assert.NotContains(t, str, "rootpw", "Password is not masked in the datasource URL")
   260  }
   261  
   262  func getTestDir(d string) (string, error) {
   263  	td, err := ioutil.TempDir(".", d)
   264  	if err != nil {
   265  		return string(""), err
   266  	}
   267  	_, d2 := filepath.Split(td)
   268  	return d2, nil
   269  }
   270  
   271  func cdTmpTestDir(name string) (string, error) {
   272  	os.Chdir(testdir)
   273  	tmpDir, err := getTestDir(name)
   274  	if err != nil {
   275  		return "", err
   276  	}
   277  	os.Chdir(tmpDir)
   278  	return tmpDir, nil
   279  }
   280  
   281  func TestCAParseDuration(t *testing.T) {
   282  	defer func() {
   283  		if r := recover(); r != nil {
   284  			t.Log("Successfully recovered ", r)
   285  		} else {
   286  			t.Error("parseDuration should have failed")
   287  		}
   288  	}()
   289  
   290  	parseDuration("9999999999999999999")
   291  }
   292  
   293  func TestCAwriteFile(t *testing.T) {
   294  	err := writeFile("/"+string(0)+"/", make([]byte, 1), 0777)
   295  	t.Log("writeFile err: ", err)
   296  	if err == nil {
   297  		t.Fatal("Should have failed: ")
   298  	}
   299  	err = writeFile(string(0), make([]byte, 1), 0777)
   300  	t.Log("writeFile err: ", err)
   301  	if err == nil {
   302  		t.Fatal("Should have failed: ")
   303  	}
   304  }
   305  
   306  func TestCAloadCNFromEnrollmentInfo(t *testing.T) {
   307  	ca, err := newCA(serverCfgFile(os.TempDir()), &CAConfig{}, &srv, true)
   308  	_, err = ca.loadCNFromEnrollmentInfo(string(0))
   309  	t.Log("loadCNFromEnrollmentInfo err: ", err)
   310  	if err == nil {
   311  		t.Error("Should have failed: ")
   312  	}
   313  	_, err = ca.loadCNFromEnrollmentInfo(ecPrivKeyMatching)
   314  	t.Log("loadCNFromEnrollmentInfo err: ", err)
   315  	if err == nil {
   316  		t.Error("Should have failed: ")
   317  	}
   318  	CAclean(ca, t)
   319  }
   320  
   321  func TestCAgetUserAffiliation(t *testing.T) {
   322  	testDirClean(t)
   323  	ca, err := newCA(configFile, &CAConfig{}, &srv, false)
   324  	if err != nil {
   325  		t.Fatal("newCA failed ", err)
   326  	}
   327  	_, err = ca.getUserAffiliation(string(0))
   328  	t.Log("getUserAffiliation err: ", err)
   329  	if err == nil {
   330  		t.Error("getUserAffiliation should have failed: bad parameter")
   331  	}
   332  	CAclean(ca, t)
   333  }
   334  
   335  func TestCAuserHasAttribute(t *testing.T) {
   336  	testDirClean(t)
   337  	ca, err := newCA(configFile, &CAConfig{}, &srv, false)
   338  	if err != nil {
   339  		t.Fatal("newCA failed ", err)
   340  	}
   341  	_, err = ca.userHasAttribute(string(0), string(0))
   342  	t.Log("userHasAttribute err: ", err)
   343  	if err == nil {
   344  		t.Error("userHasAttribute should have failed: bad parameter")
   345  	}
   346  	CAclean(ca, t)
   347  }
   348  
   349  func TestCAgetUserAttrValue(t *testing.T) {
   350  	testDirClean(t)
   351  	ca, err := newCA(configFile, &CAConfig{}, &srv, false)
   352  	if err != nil {
   353  		t.Fatal("newCA failed: ", err)
   354  	}
   355  	_, err = ca.getUserAttrValue("maryjokopechne", "delmont")
   356  	t.Log("getUserAttrValue err: ", err)
   357  	if err == nil {
   358  		t.Error("getUserAttrValue sould have failed: no such user")
   359  	}
   360  	CAclean(ca, t)
   361  }
   362  
   363  func TestCAaddIdentity(t *testing.T) {
   364  	testDirClean(t)
   365  	id := &CAConfigIdentity{
   366  		Name: "admin",
   367  		Pass: "adminpw",
   368  	}
   369  
   370  	cfg = CAConfig{}
   371  	cfg.Registry = CAConfigRegistry{MaxEnrollments: 10}
   372  	ca, err := newCA(configFile, &cfg, &srv, false)
   373  	if err != nil {
   374  		t.Fatal("newCA failed: ", err)
   375  	}
   376  	err = ca.addIdentity(id, true)
   377  	t.Log("ca.addIdentity err: ", err)
   378  	if err != nil {
   379  		t.Error("ca.addIdentity failed: ", err)
   380  	}
   381  	err = ca.addIdentity(id, true)
   382  	t.Log("ca.addIdentity err: ", err)
   383  	if err == nil {
   384  		t.Error("getUserAttrValue sould have failed: duplicate id")
   385  	}
   386  	CAclean(ca, t)
   387  }
   388  
   389  func TestCAinitUserRegistry(t *testing.T) {
   390  	testDirClean(t)
   391  	cfg = CAConfig{}
   392  	cfg.LDAP.Enabled = true
   393  	cfg.LDAP.URL = "ldap://CN=admin,dc=example,dc=com:adminpw@localhost:389/dc=example,dc=com"
   394  	ca, err := newCA(configFile, &cfg, &srv, false)
   395  	if err != nil {
   396  		t.Fatal("newCA FAILED", err)
   397  	}
   398  	CAclean(ca, t)
   399  }
   400  
   401  func TestCAgetCaCert(t *testing.T) {
   402  	testDirClean(t)
   403  	os.Remove(configFile)
   404  	cfg = CAConfig{}
   405  
   406  	cfg.CSR = api.CSRInfo{CA: &csr.CAConfig{}}
   407  	cfg.CSR.CA.Expiry = string(0)
   408  	_, err := newCA(configFile, &cfg, &srv, false)
   409  	t.Log("getCaCert error: ", err)
   410  	if err == nil {
   411  		t.Error("newCA should have failed")
   412  	}
   413  
   414  	cfg.CSR.CA.Expiry = ""
   415  	ca, err := newCA(configFile, &cfg, &srv, false)
   416  	if err != nil {
   417  		t.Fatal("newCA failed ", err)
   418  	}
   419  	cfg.CSR.CA.Expiry = ""
   420  	_, err = ca.getCACert()
   421  	if err != nil {
   422  		t.Error("getCaCert failed ", err)
   423  	}
   424  
   425  	ca.Config.CA.Keyfile = ecPrivKeyMatching
   426  	ca.Config.CA.Certfile = "/"
   427  	ca, err = newCA(configFile, &cfg, &srv, true)
   428  	t.Log("getCaCert error: ", err)
   429  	if err == nil {
   430  		t.Fatal("newCA should have failed")
   431  	}
   432  
   433  	CAclean(ca, t)
   434  	err = os.RemoveAll(configFile)
   435  	if err != nil {
   436  		t.Errorf("RemoveAll failed: %s", err)
   437  	}
   438  }
   439  
   440  func TestCAinitEnrollmentSigner(t *testing.T) {
   441  	testDirClean(t)
   442  	cfg = CAConfig{}
   443  	ca, err := newCA(configFile, &cfg, &srv, true)
   444  	if err != nil {
   445  		t.Fatal("newCA FAILED", err)
   446  	}
   447  
   448  	cfg.Intermediate.ParentServer.URL = "1"
   449  	ca, err = newCA(configFile, &cfg, &srv, false)
   450  	if err != nil {
   451  		t.Fatal("newCA FAILED", err)
   452  	}
   453  
   454  	//Rely on default policy
   455  	cfg.Signing = nil
   456  	ca.csp = nil
   457  	err = ca.initEnrollmentSigner()
   458  	t.Log("ca.initEnrollmentSigner error: ", err)
   459  	if err == nil {
   460  		t.Error("initEnrollmentSigner should have failed")
   461  	}
   462  	CAclean(ca, t)
   463  }
   464  
   465  func TestCADBinit(t *testing.T) {
   466  	orgwd, err := os.Getwd()
   467  	if err != nil {
   468  		t.Fatal("failed to get cwd")
   469  	}
   470  	confDir, err := cdTmpTestDir("TestCADBinit")
   471  	t.Logf("Conf dir: %s", confDir)
   472  	defer func() {
   473  		err = os.Chdir(orgwd)
   474  		if err != nil {
   475  			t.Fatalf("failed to cd to %v: %s", orgwd, err)
   476  		}
   477  	}()
   478  	wd, err := os.Getwd()
   479  	defer cleanupTmpfiles(t, wd)
   480  
   481  	cfg = CAConfig{}
   482  	cfg.DB = CAConfigDB{Datasource: "root:mysql@" + util.RandomString(237)}
   483  	t.Logf("serverCfgFile(confDir): %s", serverCfgFile(confDir))
   484  	ca, err := newCA(serverCfgFile(confDir), &cfg, &srv, false)
   485  	if ca.db != nil {
   486  		t.Error("Create DB should have failed")
   487  	}
   488  }
   489  
   490  func TestCAloadAffiliationsTableR(t *testing.T) {
   491  	testDirClean(t)
   492  	cfg = CAConfig{}
   493  	ca, err := newCA(configFile, &cfg, &srv, true)
   494  	if err != nil {
   495  		t.Fatal("newCA FAILED", err)
   496  	}
   497  
   498  	//Failure to write to DB; non-valid accessor
   499  	dbAccessor := &Accessor{}
   500  	ca.registry = dbAccessor
   501  
   502  	i := make([]interface{}, 3)
   503  	i[1] = []string{"", "root", "root"}
   504  	ca.Config.Affiliations = make(map[string]interface{}, 3)
   505  	ca.Config.Affiliations["a"] = i
   506  	err = ca.loadAffiliationsTable()
   507  	t.Log("ca.loadAffiliationsTable error: ", err)
   508  	if err == nil {
   509  		t.Error("ca.loadAffiliationsTableR should have failed ", err)
   510  	}
   511  	err = ca.loadAffiliationsTableR(i[1], "")
   512  	t.Log("ca.loadAffiliationsTableR error: ", err)
   513  	if err == nil {
   514  		t.Error("ca.loadAffiliationsTableR should have failed ", err)
   515  	}
   516  	err = ca.loadAffiliationsTableR(i, "root")
   517  	t.Log("ca.loadAffiliationsTableR error: ", err)
   518  	if err == nil {
   519  		t.Error("ca.loadAffiliationsTableR should have failed ", err)
   520  	}
   521  	CAclean(ca, t)
   522  }
   523  
   524  func TestCAloadUsersTable(t *testing.T) {
   525  	testDirClean(t)
   526  	cfg = CAConfig{}
   527  	u := &CAConfigIdentity{Name: "a", MaxEnrollments: -10}
   528  	cfg.Registry = CAConfigRegistry{Identities: []CAConfigIdentity{*u}, MaxEnrollments: 10}
   529  	ca, err := newCA(configFile, &cfg, &srv, false)
   530  	t.Log("ca.newCA error: ", err)
   531  	if err == nil {
   532  		t.Error("ca.newCA should have failed")
   533  	}
   534  
   535  	// Chase down all error paths using duplicate entries
   536  	i := make([]interface{}, 3)
   537  	i[1] = []string{"", "root", "root"}
   538  	cfg.Affiliations = make(map[string]interface{}, 3)
   539  	cfg.Affiliations["a"] = i
   540  
   541  	// Valid registration
   542  	err = os.Remove(testdir + dbname)
   543  	if err != nil {
   544  		t.Fatalf("Remove failed: %s", err)
   545  	}
   546  	u = &CAConfigIdentity{Name: "a", MaxEnrollments: 10}
   547  	cfg.Registry = CAConfigRegistry{Identities: []CAConfigIdentity{*u}, MaxEnrollments: 10}
   548  	ca, err = newCA(configFile, &cfg, &srv, false)
   549  	if err != nil {
   550  		t.Fatal("newCA FAILED", err)
   551  	}
   552  
   553  	u = &CAConfigIdentity{Name: "a", MaxEnrollments: 10}
   554  	ca.Config.Registry = CAConfigRegistry{Identities: []CAConfigIdentity{*u}, MaxEnrollments: 10}
   555  	err = ca.loadUsersTable()
   556  	if err != nil {
   557  		t.Error("ca.loadUsersTable failed ", err)
   558  	}
   559  
   560  	// Duplicate resgistration, non-error
   561  	u = &CAConfigIdentity{Name: "a", MaxEnrollments: 10}
   562  	ca.Config.Registry = CAConfigRegistry{Identities: []CAConfigIdentity{*u}, MaxEnrollments: 10}
   563  	err = ca.loadUsersTable()
   564  	if err != nil {
   565  		t.Error("ca.loadUsersTable error path should have succeeded: ", err)
   566  	}
   567  
   568  	// Database error (db is closed)
   569  	u = &CAConfigIdentity{Name: "b", MaxEnrollments: 10}
   570  	ca.Config.Registry = CAConfigRegistry{Identities: []CAConfigIdentity{*u}, MaxEnrollments: 10}
   571  	err = ca.closeDB()
   572  	if err != nil {
   573  		t.Fatalf("CloseDB failed: %s", err)
   574  	}
   575  	err = os.Remove(testdir + dbname)
   576  	if err != nil {
   577  		t.Fatalf("Remove failed: %s", err)
   578  	}
   579  	err = ca.loadUsersTable()
   580  	t.Log("ca.loadUsersTable error: ", err)
   581  	if err == nil {
   582  		t.Error("ca.loadUsersTable should have failed due to DB error ", err)
   583  	}
   584  	CAclean(ca, t)
   585  }
   586  
   587  func TestCAVerifyCertificate(t *testing.T) {
   588  	testDirClean(t)
   589  	cfg = CAConfig{}
   590  	ca, err := newCA(configFile, &cfg, &srv, false)
   591  	if err != nil {
   592  		t.Fatal("newCA FAILED", err)
   593  	}
   594  
   595  	cert, err := getCertFromFile(noCACert)
   596  	if err != nil {
   597  		t.Fatal(err)
   598  	}
   599  
   600  	ca.Config.CA.Keyfile = caKey
   601  	ca.Config.CA.Certfile = caCert
   602  	ca.Config.CA.Chainfile = "../testdata/empty.json"
   603  	err = ca.VerifyCertificate(cert)
   604  	t.Log("ca.VerifyCertificate error: ", err)
   605  	if err == nil {
   606  		t.Error("VerifyCertificate should have failed")
   607  	}
   608  
   609  	ca.Config.CA.Chainfile = "../testdata/crl.pem"
   610  	err = ca.VerifyCertificate(cert)
   611  	t.Log("ca.VerifyCertificate error: ", err)
   612  	if err == nil {
   613  		t.Error("VerifyCertificate should have failed")
   614  	}
   615  
   616  	err = GenerateECDSATestCert()
   617  	util.FatalError(t, err, "Failed to generate certificate for testing")
   618  	caCert1, err := ioutil.ReadFile("../testdata/ec_cert.pem")
   619  	caCert2 := append(caCert1, util.RandomString(128)...)
   620  	err = ioutil.WriteFile(filepath.Join(os.TempDir(), "ca-chainfile.pem"), caCert2, 0644)
   621  	ca.Config.CA.Chainfile = filepath.Join(os.TempDir(), "ca-chainfile.pem")
   622  	err = ca.VerifyCertificate(cert)
   623  	t.Log("ca.VerifyCertificate error: ", err)
   624  	if err == nil {
   625  		t.Error("VerifyCertificate should have failed")
   626  	}
   627  	err = os.Remove(filepath.Join(os.TempDir(), "ca-chainfile.pem"))
   628  	if err != nil {
   629  		t.Errorf("Remove failed: %s", err)
   630  	}
   631  
   632  	ca.Config.CA.Chainfile = "doesNotExist"
   633  	ca.Config.CA.Certfile = "doesNotExist"
   634  	ca.Config.Intermediate.ParentServer.URL = "http://127.0.0.1:" + caPort
   635  	err = ca.VerifyCertificate(cert)
   636  	t.Log("ca.VerifyCertificate error: ", err)
   637  	if err == nil {
   638  		t.Error("VerifyCertificate should have failed")
   639  	}
   640  	ca.Config.CA.Chainfile = noUsageCert
   641  	err = ca.VerifyCertificate(cert)
   642  	t.Log("ca.VerifyCertificate error: ", err)
   643  	if err == nil {
   644  		t.Error("VerifyCertificate should have failed")
   645  	}
   646  	CAclean(ca, t)
   647  }
   648  
   649  // Loads a registrar user and a non-registrar user into database. Server is started using an existing database
   650  // with users. This test verifies that the registrar is given the new attribute "hf.Registrar.Attribute" but
   651  // the non-registrar user is not.
   652  func TestServerMigration(t *testing.T) {
   653  	dir := "migrationTest"
   654  	os.RemoveAll(dir)
   655  	defer os.RemoveAll(dir)
   656  	err := os.Mkdir(dir, 0777)
   657  	if err != nil {
   658  		t.Fatalf("Failed to create directory: %s", err.Error())
   659  	}
   660  
   661  	sqliteDB := sqlite.NewDB(filepath.Join(dir, "fabric-ca-server.db"), "", &disabled.Provider{})
   662  	err = sqliteDB.Connect()
   663  	assert.NoError(t, err, "failed to connect to database")
   664  	db, err := sqliteDB.Create()
   665  	assert.NoError(t, err, "failed to create database")
   666  
   667  	util.FatalError(t, err, "Failed to create db")
   668  	_, err = db.Exec("", "INSERT INTO users (id, token, type, affiliation, attributes, state, max_enrollments, level) VALUES ('registrar', '', 'user', 'org2', '[{\"name\":\"hf.Registrar.Roles\",\"value\":\"user,peer,client\"}]', '0', '-1', '0')")
   669  	assert.NoError(t, err, "Failed to insert user 'registrar' into database")
   670  	_, err = db.Exec("", "INSERT INTO users (id, token, type, affiliation, attributes, state, max_enrollments, level) VALUES ('notregistrar', '', 'user', 'org2', '[{\"name\":\"hf.Revoker\",\"value\":\"true\"}]', '0', '-1', '0')")
   671  	assert.NoError(t, err, "Failed to insert user 'notregistrar' into database")
   672  
   673  	server := TestGetServer2(false, rootPort, dir, "", -1, t)
   674  	if server == nil {
   675  		return
   676  	}
   677  	err = server.Start()
   678  	util.FatalError(t, err, "Server start failed")
   679  	defer func() {
   680  		err = server.Stop()
   681  		if err != nil {
   682  			t.Errorf("Failed to stop server: %s", err)
   683  		}
   684  	}()
   685  
   686  	registrar, err := server.CA.registry.GetUser("registrar", nil)
   687  	assert.NoError(t, err, "Failed to get user")
   688  	registrarAttr, err := registrar.GetAttribute("hf.Registrar.Attributes")
   689  	assert.NoError(t, err, "Failed to get attribute")
   690  	t.Logf("registrarAttr: '%+v'", registrarAttr)
   691  	if registrarAttr.Value == "" {
   692  		t.Error("Failed to correctly migrate user 'registrar'")
   693  	}
   694  
   695  	notregistrar, err := server.CA.registry.GetUser("notregistrar", nil)
   696  	assert.NoError(t, err, "Failed to get user")
   697  	_, err = notregistrar.GetAttribute("hf.Registrar.Attributes")
   698  	assert.Error(t, err, "Non-registrar user should not have this attribute, failed to correctly migrate user")
   699  }
   700  
   701  func getCertFromFile(f string) (*x509.Certificate, error) {
   702  	p, err := ioutil.ReadFile(f)
   703  	if err != nil {
   704  		return nil, fmt.Errorf("read of %s failed", f)
   705  	}
   706  	c, err := util.GetX509CertificateFromPEM(p)
   707  	if err != nil {
   708  		return nil, fmt.Errorf("decode of %s failed", f)
   709  	}
   710  	return c, nil
   711  }
   712  
   713  func serverCfgFile(dir string) string {
   714  	return path.Join(dir, "fabric-ca-server-config.yaml")
   715  }
   716  
   717  func cleanupTmpfiles(t *testing.T, d string) {
   718  	err := os.RemoveAll(d) // clean up
   719  	if err != nil {
   720  		t.Fatal("Remove failed: ", err)
   721  	} else {
   722  		t.Log("Removed: ", d)
   723  	}
   724  }
   725  
   726  func CAclean(ca *CA, t *testing.T) {
   727  	if ca != nil {
   728  		err := ca.closeDB()
   729  		if err != nil {
   730  			t.Error("CloseDB failed: ", err)
   731  		}
   732  	}
   733  	testDirClean(t)
   734  }
   735  
   736  func testDirClean(t *testing.T) {
   737  	err := os.RemoveAll(testdir + "msp")
   738  	if err != nil {
   739  		t.Fatal("RemoveAll failed: ", err)
   740  	}
   741  	err = os.RemoveAll(testdir + "ca-cert.pem")
   742  	if err != nil {
   743  		t.Fatal("RemoveAll failed: ", err)
   744  	}
   745  	err = os.RemoveAll(testdir + "ca-key.pem")
   746  	if err != nil {
   747  		t.Fatal("RemoveAll failed: ", err)
   748  	}
   749  	err = os.RemoveAll(testdir + dbname)
   750  	if err != nil {
   751  		t.Fatal("RemoveAll failed: ", err)
   752  	}
   753  	os.Remove(configFile)
   754  }