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