github.com/silveraid/fabric-ca@v1.1.0-preview.0.20180127000700-71974f53ab08/lib/client_whitebox_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  package lib
    17  
    18  import (
    19  	"crypto/rand"
    20  	"crypto/x509"
    21  	"encoding/pem"
    22  	"fmt"
    23  	"io/ioutil"
    24  	"net/http"
    25  	"os"
    26  	"path"
    27  	"testing"
    28  
    29  	"github.com/cloudflare/cfssl/csr"
    30  	"github.com/cloudflare/cfssl/log"
    31  	"github.com/cloudflare/cfssl/signer"
    32  	"github.com/hyperledger/fabric-ca/api"
    33  	"github.com/hyperledger/fabric-ca/util"
    34  	"github.com/hyperledger/fabric/bccsp"
    35  	"github.com/hyperledger/fabric/bccsp/factory"
    36  	cspsigner "github.com/hyperledger/fabric/bccsp/signer"
    37  	"github.com/hyperledger/fabric/bccsp/utils"
    38  	"github.com/stretchr/testify/assert"
    39  )
    40  
    41  const (
    42  	whitePort            = 7058
    43  	user                 = "admin"
    44  	pass                 = "adminpw"
    45  	serversDir           = "testservers"
    46  	testTLSClientAuthDir = "testTLSClientAuthDir"
    47  )
    48  
    49  var clientConfig = path.Join(testdataDir, "client-config.json")
    50  
    51  func TestCWBClient1(t *testing.T) {
    52  	server := getServer(whitePort, path.Join(serversDir, "c1"), "", 1, t)
    53  	if server == nil {
    54  		t.Fatal("Failed to get server")
    55  	}
    56  	err := server.Start()
    57  	if err != nil {
    58  		t.Fatalf("Failed to start server: %s", err)
    59  	}
    60  	defer func() {
    61  		err = server.Stop()
    62  		if err != nil {
    63  			t.Errorf("Server stop failed: %s", err)
    64  		}
    65  		err = os.RemoveAll(serversDir)
    66  		if err != nil {
    67  			t.Errorf("RemoveAll failed: %s", err)
    68  		}
    69  	}()
    70  
    71  	testInvalidAuthEnrollment(t)
    72  }
    73  
    74  // TestTLS performs 3 main steps:
    75  // 1) Test over HTTP to get an standard ECert
    76  // 2) Test over HTTPS with client auth disabled
    77  // 3) Test over HTTPS with client auth enabled, using standard ECert from #1
    78  func TestCWBTLSClientAuth(t *testing.T) {
    79  	cleanTestSlateCWB(t)
    80  	defer cleanTestSlateCWB(t)
    81  	//
    82  	// 1) Test over HTTP to get a standard ECert
    83  	//
    84  	// Start server
    85  	server := getServer(whitePort, path.Join(testTLSClientAuthDir, "server"), "", 2, t)
    86  	if server == nil {
    87  		return
    88  	}
    89  	server.CA.Config.CSR.CN = "localhost"
    90  	err := server.Start()
    91  	if err != nil {
    92  		t.Fatalf("Failed to start server: %s", err)
    93  	}
    94  
    95  	// Enroll over HTTP
    96  	client := &Client{
    97  		Config: &ClientConfig{
    98  			URL: fmt.Sprintf("http://localhost:%d", whitePort),
    99  		},
   100  		HomeDir: path.Join(testTLSClientAuthDir, "client"),
   101  	}
   102  
   103  	eresp, err := client.Enroll(&api.EnrollmentRequest{Name: user, Secret: pass})
   104  	if err != nil {
   105  		server.Stop()
   106  		t.Fatalf("Failed to enroll admin: %s", err)
   107  	}
   108  	id := eresp.Identity
   109  	testImpersonation(id, t)
   110  	testMasqueradeEnroll(t, client, id)
   111  
   112  	// Register and enroll user to test reenrolling while masquerading
   113  	name := "masqueradeUser2"
   114  	rr, err := id.Register(&api.RegistrationRequest{
   115  		Name:           name,
   116  		Type:           "user",
   117  		Affiliation:    "hyperledger.fabric.security",
   118  		MaxEnrollments: 2,
   119  	})
   120  	if err != nil {
   121  		t.Fatalf("Failed to register maqueradeUser: %s", err)
   122  	}
   123  
   124  	eresp2, err := client.Enroll(&api.EnrollmentRequest{Name: name, Secret: rr.Secret})
   125  	if err != nil {
   126  		t.Errorf("Failed to enroll")
   127  	}
   128  
   129  	id2 := eresp2.Identity
   130  	testMasqueradeReenroll(t, client, id2)
   131  
   132  	// Stop server
   133  	log.Debug("Stopping the server")
   134  	err = server.Stop()
   135  	if err != nil {
   136  		t.Fatalf("Failed to stop server: %s", err)
   137  	}
   138  
   139  	//
   140  	// 2) Test over HTTPS with client auth disabled
   141  	//
   142  	// Start server
   143  	log.Debug("Starting the server with TLS")
   144  	server.Config.TLS.Enabled = true
   145  	server.Config.TLS.CertFile = "ca-cert.pem"
   146  	err = server.Start()
   147  	if err != nil {
   148  		t.Fatalf("Failed to start server with HTTPS: %s", err)
   149  	}
   150  
   151  	// Close the idle connections that were established to the non-SSL
   152  	// server. client will create new connection for the next request
   153  	// There is no need to do this in real scenario where the Fabric CA
   154  	// server's transport can only be changed from ssl to non-ssl or vice-versa
   155  	// by restarting the server, in which case connections in the client's
   156  	// connection pool are invalidated and it is forced to create new connection.
   157  	client.httpClient.Transport.(*http.Transport).CloseIdleConnections()
   158  
   159  	// Try to reenroll over HTTP and it should fail because server is listening on HTTPS
   160  	_, err = id.Reenroll(&api.ReenrollmentRequest{})
   161  	if err == nil {
   162  		t.Error("Client HTTP should have failed to reenroll with server HTTPS")
   163  	}
   164  
   165  	client.Config.URL = fmt.Sprintf("https://localhost:%d", whitePort)
   166  	client.Config.TLS.Enabled = true
   167  	client.Config.TLS.CertFiles = []string{"../server/ca-cert.pem"}
   168  	// Reinialize the http client with updated config and re-enroll over HTTPS
   169  	err = client.initHTTPClient()
   170  	resp, err := id.Reenroll(&api.ReenrollmentRequest{})
   171  	if err != nil {
   172  		server.Stop()
   173  		t.Fatalf("Failed to reenroll over HTTPS: %s", err)
   174  	}
   175  	id = resp.Identity
   176  	// Store identity persistently
   177  	err = id.Store()
   178  	if err != nil {
   179  		server.Stop()
   180  		t.Fatalf("Failed to store identity: %s", err)
   181  	}
   182  
   183  	// Stop server
   184  	err = server.Stop()
   185  	if err != nil {
   186  		t.Fatalf("Failed to stop server: %s", err)
   187  	}
   188  
   189  	//
   190  	// 3) Test over HTTPS with client auth enabled
   191  	//
   192  	server.Config.TLS.ClientAuth.Type = "RequireAndVerifyClientCert"
   193  	server.Config.TLS.ClientAuth.CertFiles = []string{"ca-cert.pem"}
   194  	err = server.Start()
   195  	if err != nil {
   196  		t.Fatalf("Failed to start server with HTTPS and client auth: %s", err)
   197  	}
   198  	// Close all idle connections
   199  	client.httpClient.Transport.(*http.Transport).CloseIdleConnections()
   200  
   201  	// Try to reenroll and it should fail because client has no client cert
   202  	_, err = id.Reenroll(&api.ReenrollmentRequest{})
   203  	if err == nil {
   204  		t.Error("Client reenroll without client cert should have failed")
   205  	}
   206  
   207  	client.Config.TLS.Client.CertFile = path.Join("msp", "signcerts", "cert.pem")
   208  	// Reinialize the http client with updated config and re-enroll over HTTPS with client auth
   209  	err = client.initHTTPClient()
   210  	_, err = id.Reenroll(&api.ReenrollmentRequest{})
   211  	if err != nil {
   212  		t.Errorf("Client reenroll with client auth failed: %s", err)
   213  	}
   214  	// Stop server
   215  	err = server.Stop()
   216  	if err != nil {
   217  		t.Fatalf("Failed to stop server: %s", err)
   218  	}
   219  }
   220  
   221  func testInvalidAuthEnrollment(t *testing.T) {
   222  	c := getTestClient(whitePort)
   223  	err := c.Init()
   224  	if err != nil {
   225  		t.Fatalf("Failed to initialize client: %s", err)
   226  	}
   227  	body, err1 := getEnrollmentPayload(t, c)
   228  	if err1 != nil {
   229  		t.Fatalf("Failed to get enrollment payload: %s", err1)
   230  	}
   231  
   232  	enrollAndCheck(t, c, body, "Basic admin:adminpw")         // Invalid auth header
   233  	enrollAndCheck(t, c, body, "Basicadmin:adminpw")          // Invalid auth header
   234  	enrollAndCheck(t, c, body, "BasicYWRtaW46YWRtaW5wdw==")   // Invalid auth header
   235  	enrollAndCheck(t, c, body, "Basic YWRtaW46YWRtaW4=")      // Invalid password
   236  	enrollAndCheck(t, c, body, "Basic dXNlcjpwYXNz")          // Invalid user
   237  	enrollAndCheck(t, c, body, "Bearer YWRtaW46YWRtaW5wdw==") // Invalid auth header
   238  	// Invalid auth header, it has to be Basic <base64 encoded user:pass>
   239  	enrollAndCheck(t, c, body, "basic YWRtaW46YWRtaW5wdw==")
   240  	enrollAndCheck(t, c, body, "Basic   YWRtaW46YWRtaW5wdw==")
   241  	enrollAndCheck(t, c, body, "garbage") // Invalid auth header
   242  	enrollAndCheck(t, c, body, "")        // No auth header
   243  }
   244  
   245  func enrollAndCheck(t *testing.T, c *Client, body []byte, authHeader string) {
   246  	// Send the CSR to the fabric-ca server with basic auth header
   247  	post, err := c.newPost("enroll", body)
   248  	if err != nil {
   249  		t.Fatalf("Failed to create post request: %s", err)
   250  	}
   251  	if authHeader != "" {
   252  		post.Header.Set("Authorization", authHeader)
   253  	}
   254  	var result enrollmentResponseNet
   255  	err = c.SendReq(post, &result)
   256  	t.Logf("c.SendReq: %v", err)
   257  	if err == nil {
   258  		t.Errorf("Enrollment with bad basic auth header '%s' should have failed",
   259  			authHeader)
   260  	}
   261  	err = os.RemoveAll("../testdata/msp")
   262  	if err != nil {
   263  		t.Errorf("RemoveAll failed: %s", err)
   264  	}
   265  }
   266  
   267  // Try to impersonate 'id' identity by creating a self-signed certificate
   268  // with the same serial and AKI as this identity.
   269  func testImpersonation(id *Identity, t *testing.T) {
   270  	// test as a fake user trying to impersonate admin give only the cert
   271  	cert, err := BytesToX509Cert(id.GetECert().Cert())
   272  	if err != nil {
   273  		t.Fatalf("Failed to convert admin's cert: %s", err)
   274  	}
   275  	bc := &factory.FactoryOpts{}
   276  	csp, err := util.InitBCCSP(&bc, "", path.Join(testTLSClientAuthDir, "client"))
   277  	if err != nil {
   278  		t.Fatalf("Failed to initialize BCCSP: %s", err)
   279  	}
   280  	var fm os.FileMode = 0777
   281  	os.MkdirAll("msp/keystore", os.FileMode(fm))
   282  	defer func() {
   283  		err = os.RemoveAll("msp")
   284  		if err != nil {
   285  			t.Errorf("RemoveAll failed: %s", err)
   286  		}
   287  	}()
   288  
   289  	privateKey, err := csp.KeyGen(&bccsp.ECDSAKeyGenOpts{Temporary: false})
   290  	if err != nil {
   291  		t.Fatalf("Failed generating ECDSA key [%s]", err)
   292  	}
   293  	cspSigner, err := cspsigner.New(csp, privateKey)
   294  	if err != nil {
   295  		t.Fatalf("Failed initializing signer: %s", err)
   296  	}
   297  	// Export the public key
   298  	publicKey, err := privateKey.PublicKey()
   299  	if err != nil {
   300  		t.Fatalf("Failed getting ECDSA public key: %s", err)
   301  	}
   302  	pkRaw, err := publicKey.Bytes()
   303  	if err != nil {
   304  		t.Fatalf("Failed getting ECDSA raw public key [%s]", err)
   305  	}
   306  	pub, err := utils.DERToPublicKey(pkRaw)
   307  	if err != nil {
   308  		t.Fatalf("Failed converting raw to ECDSA.PublicKey [%s]", err)
   309  	}
   310  	fakeCertBytes, err := x509.CreateCertificate(rand.Reader, cert, cert, pub, cspSigner)
   311  	if err != nil {
   312  		t.Fatalf("Failed to create self-signed fake cert: %s", err)
   313  	}
   314  	fakeCert := pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: fakeCertBytes})
   315  	fakeID := newIdentity(id.GetClient(), "admin", privateKey, fakeCert)
   316  	_, err = fakeID.RevokeSelf()
   317  	t.Logf("fakeID.RevokeSelf: %v", err)
   318  	if err == nil {
   319  		t.Fatalf("Fake ID should have failed revocation")
   320  	}
   321  }
   322  
   323  func testMasqueradeEnroll(t *testing.T, c *Client, id *Identity) {
   324  	// Register masqueradeUser
   325  	log.Debug("Entering testMasqueradeEnroll")
   326  	name := "masqueradeUser"
   327  	rr, err := id.Register(&api.RegistrationRequest{
   328  		Name:           name,
   329  		Type:           "user",
   330  		Affiliation:    "hyperledger.fabric.security",
   331  		MaxEnrollments: 2,
   332  	})
   333  	if err != nil {
   334  		t.Fatalf("Failed to register maqueradeUser: %s", err)
   335  	}
   336  	// Try to enroll masqueradeUser but masquerading as 'admin'
   337  	_, err = masqueradeEnroll(c, "admin", false, &api.EnrollmentRequest{
   338  		Name:   name,
   339  		Secret: rr.Secret,
   340  	})
   341  	if err == nil {
   342  		t.Fatalf("%s masquerading as admin (false) should have failed", name)
   343  	}
   344  	log.Debugf("testMasqueradeEnroll (false) error: %s", err)
   345  	_, err = masqueradeEnroll(c, "admin", true, &api.EnrollmentRequest{
   346  		Name:   name,
   347  		Secret: rr.Secret,
   348  	})
   349  	if err == nil {
   350  		t.Fatalf("%s masquerading as admin (true) should have failed", name)
   351  	}
   352  	log.Debugf("testMasqueradeEnroll (true) error: %s", err)
   353  }
   354  
   355  func testMasqueradeReenroll(t *testing.T, c *Client, id *Identity) {
   356  	log.Debug("Entering testMasqueradeReenroll")
   357  	// Try to reenroll but masquerading as 'admin'
   358  	_, err := masqueradeReenroll(c, "admin", id, false, &api.ReenrollmentRequest{})
   359  	if assert.Error(t, err, fmt.Sprintf("%s masquerading as admin (false) should have failed", id.GetName())) {
   360  		assert.Contains(t, err.Error(), "The CSR subject common name must equal the enrollment ID", "Failed for other reason besides masquerading")
   361  	}
   362  
   363  	log.Debugf("testMasqueradeEnroll (false) error: %s", err)
   364  	_, err = masqueradeReenroll(c, "admin", id, true, &api.ReenrollmentRequest{})
   365  	if assert.Error(t, err, fmt.Sprintf("%s masquerading as admin (false) should have failed", id.GetName())) {
   366  		assert.Contains(t, err.Error(), "The CSR subject common name must equal the enrollment ID", "Failed for other reason besides masquerading")
   367  	}
   368  	log.Debugf("testMasqueradeEnroll (true) error: %s", err)
   369  }
   370  
   371  func getEnrollmentPayload(t *testing.T, c *Client) ([]byte, error) {
   372  	req := &api.EnrollmentRequest{
   373  		Name:   user,
   374  		Secret: pass,
   375  	}
   376  
   377  	// Generate the CSR
   378  	csrPEM, _, err := c.GenCSR(req.CSR, req.Name)
   379  	if err != nil {
   380  		t.Logf("Enroll failure generating CSR: %s", err)
   381  		return nil, err
   382  	}
   383  
   384  	// Get the body of the request
   385  	sreq := signer.SignRequest{
   386  		Request: string(csrPEM),
   387  		Profile: req.Profile,
   388  		Label:   req.Label,
   389  	}
   390  
   391  	return util.Marshal(sreq, "SignRequest")
   392  }
   393  
   394  func getServer(port int, home, parentURL string, maxEnroll int, t *testing.T) *Server {
   395  	if home != testdataDir {
   396  		err := os.RemoveAll(home)
   397  		if err != nil {
   398  			t.Errorf("RemoveAll failed: %s", err)
   399  		}
   400  	}
   401  	srv, err := createServer(port, home, parentURL, maxEnroll)
   402  	if err != nil {
   403  		t.Errorf("failed to register bootstrap user: %s", err)
   404  		return nil
   405  	}
   406  	return srv
   407  }
   408  
   409  func getServerForBenchmark(port int, home, parentURL string, maxEnroll int, b *testing.B) *Server {
   410  	if home != testdataDir {
   411  		err := os.RemoveAll(home)
   412  		if err != nil {
   413  			b.Errorf("RemoveAll failed: %s", err)
   414  		}
   415  	}
   416  	srv, err := createServer(port, home, parentURL, maxEnroll)
   417  	if err != nil {
   418  		b.Errorf("failed to register bootstrap user: %s", err)
   419  		return nil
   420  	}
   421  	return srv
   422  }
   423  
   424  func createServer(port int, home, parentURL string, maxEnroll int) (*Server, error) {
   425  	affiliations := map[string]interface{}{
   426  		"hyperledger": map[string]interface{}{
   427  			"fabric":    []string{"ledger", "orderer", "security"},
   428  			"fabric-ca": nil,
   429  			"sdk":       nil,
   430  		},
   431  		"org2": nil,
   432  	}
   433  	affiliations[affiliationName] = map[string]interface{}{
   434  		"department1": nil,
   435  		"department2": nil,
   436  	}
   437  	srv := &Server{
   438  		Config: &ServerConfig{
   439  			Port:  port,
   440  			Debug: true,
   441  		},
   442  		CA: CA{
   443  			Config: &CAConfig{
   444  				Intermediate: IntermediateCA{
   445  					ParentServer: ParentServer{
   446  						URL: parentURL,
   447  					},
   448  				},
   449  				Affiliations: affiliations,
   450  				Registry: CAConfigRegistry{
   451  					MaxEnrollments: maxEnroll,
   452  				},
   453  			},
   454  		},
   455  		HomeDir: home,
   456  	}
   457  	// The bootstrap user's affiliation is the empty string, which
   458  	// means the user is at the affiliation root
   459  	err := srv.RegisterBootstrapUser(user, pass, "")
   460  	if err != nil {
   461  		return nil, err
   462  	}
   463  	return srv, nil
   464  }
   465  
   466  func getTestClient(port int) *Client {
   467  	return &Client{
   468  		Config:  &ClientConfig{URL: fmt.Sprintf("http://localhost:%d", port)},
   469  		HomeDir: testdataDir,
   470  	}
   471  }
   472  
   473  func TestCWBCAConfig(t *testing.T) {
   474  	ca := &CA{}
   475  
   476  	//Error cases
   477  	err := ca.fillCAInfo(nil)
   478  	t.Logf("fillCAInfo err: %v", err)
   479  	if err == nil {
   480  		t.Error("ca.fileCAInfo should have failed but passed")
   481  	}
   482  	_, err = ca.getCAChain()
   483  	t.Logf("getCAChain err: %v", err)
   484  	if err == nil {
   485  		t.Error("getCAChain:1 should have failed but passed")
   486  	}
   487  	ca.Config = &CAConfig{}
   488  	ca.Config.Intermediate.ParentServer.URL = "foo"
   489  	_, err = ca.getCAChain()
   490  	t.Logf("getCAChain err: %v", err)
   491  	if err == nil {
   492  		t.Error("getCAChain:2 should have failed but passed")
   493  	}
   494  	ca.Config.DB.Type = "postgres"
   495  	err = ca.initDB()
   496  	t.Logf("initDB err: %v", err)
   497  	if err == nil {
   498  		t.Error("initDB postgres should have failed but passed")
   499  	}
   500  	ca.Config.DB.Type = "mysql"
   501  	err = ca.initDB()
   502  	t.Logf("initDB err: %v", err)
   503  	if err == nil {
   504  		t.Error("initDB mysql should have failed but passed")
   505  	}
   506  
   507  	ca.Config.DB.Type = "unknown"
   508  	err = ca.initDB()
   509  	t.Logf("initDB err: %v", err)
   510  	if err == nil {
   511  		t.Error("initDB unknown should have failed but passed")
   512  	}
   513  
   514  	ca.Config.LDAP.Enabled = true
   515  	ca.server = &Server{}
   516  	err = ca.initUserRegistry()
   517  	t.Logf("initUserRegistry err: %v", err)
   518  	if err == nil {
   519  		t.Error("initConfig LDAP passed but should have failed")
   520  	}
   521  
   522  	//Non error cases
   523  	ca.Config.CA.Chainfile = "../testdata/ec.pem"
   524  	_, err = ca.getCAChain()
   525  	t.Logf("getCAChain err: %v", err)
   526  	if err != nil {
   527  		t.Errorf("Failed to getCAChain: %s", err)
   528  	}
   529  	err = ca.initConfig()
   530  	if err != nil {
   531  		t.Errorf("initConfig failed: %s", err)
   532  	}
   533  	ca = &CA{}
   534  	ca.server = &Server{}
   535  	err = ca.initConfig()
   536  	if err != nil {
   537  		t.Errorf("ca.initConfig default failed: %s", err)
   538  	}
   539  	ca.HomeDir = ""
   540  	err = ca.initConfig()
   541  	if err != nil {
   542  		t.Errorf("initConfig failed: %s", err)
   543  	}
   544  	ca.Config = new(CAConfig)
   545  	ca.server = &Server{}
   546  	ca.Config.CA.Certfile = "../testdata/ec_cert.pem"
   547  	ca.Config.CA.Keyfile = "../testdata/ec_key.pem"
   548  	err = ca.initConfig()
   549  	if err != nil {
   550  		t.Errorf("initConfig failed: %s", err)
   551  	}
   552  	s := &Server{}
   553  	s.CA.Config = &CAConfig{}
   554  	err = s.initConfig()
   555  	if err != nil {
   556  		t.Errorf("server.initConfig default failed: %s", err)
   557  	}
   558  }
   559  
   560  func TestCWBNewCertificateRequest(t *testing.T) {
   561  	c := &Client{}
   562  	req := &api.CSRInfo{
   563  		Names:      []csr.Name{},
   564  		Hosts:      []string{},
   565  		KeyRequest: api.NewBasicKeyRequest(),
   566  	}
   567  	if c.newCertificateRequest(req) == nil {
   568  		t.Error("newCertificateRequest failed")
   569  	}
   570  }
   571  
   572  func TestCWBCAConfigStat(t *testing.T) {
   573  	wd, err := os.Getwd()
   574  	if err != nil {
   575  		t.Fatalf("failed to get cwd: %s", err)
   576  	}
   577  	td, err := ioutil.TempDir("", "CAConfigStat")
   578  	if err != nil {
   579  		t.Fatalf("failed to get tmp dir: %s", err)
   580  	}
   581  	defer func() {
   582  		err = os.RemoveAll(td)
   583  		if err != nil {
   584  			t.Errorf("RemoveAll failed: %s", err)
   585  		}
   586  	}()
   587  	err = os.Chdir(td)
   588  	if err != nil {
   589  		t.Fatalf("failed to cd to %v: %s", td, err)
   590  	}
   591  	defer func() {
   592  		err = os.Chdir(wd)
   593  		if err != nil {
   594  			t.Fatalf("failed to cd to %v: %s", wd, err)
   595  		}
   596  	}()
   597  
   598  	ca := &CA{}
   599  	ca.Config = &CAConfig{}
   600  	ca.HomeDir = "."
   601  	fileInfo, err := os.Stat(".")
   602  	if err != nil {
   603  		t.Fatalf("os.Stat failed on current dir: %s", err)
   604  	}
   605  	oldmode := fileInfo.Mode()
   606  	err = os.Chmod(".", 0000)
   607  	if err != nil {
   608  		t.Fatalf("Chmod on %s failed: %s", fileInfo.Name(), err)
   609  	}
   610  	defer func() {
   611  		err = os.Chmod(td, oldmode)
   612  		if err != nil {
   613  			t.Fatalf("Chmod on %s failed: %s", td, err)
   614  		}
   615  	}()
   616  
   617  	ca.Config.DB.Type = ""
   618  	err = ca.initDB()
   619  	t.Logf("initDB err: %v", err)
   620  	if err == nil {
   621  		t.Errorf("initDB should have failed (getcwd failure)")
   622  	}
   623  	ca.Config.DB.Datasource = ""
   624  	ca.HomeDir = ""
   625  }
   626  
   627  func cleanTestSlateCWB(t *testing.T) {
   628  	err := os.RemoveAll("msp")
   629  	if err != nil {
   630  		t.Errorf("RemoveAll failed: %s", err)
   631  	}
   632  	err = os.RemoveAll("../testdata/msp")
   633  	if err != nil {
   634  		t.Errorf("RemoveAll failed: %s", err)
   635  	}
   636  	err = os.RemoveAll(serversDir)
   637  	if err != nil {
   638  		t.Errorf("RemoveAll failed: %s", err)
   639  	}
   640  	err = os.RemoveAll(testTLSClientAuthDir)
   641  	if err != nil {
   642  		t.Errorf("RemoveAll failed: %s", err)
   643  	}
   644  }
   645  
   646  // masqueradeEnroll enrolls a new identity as a masquerader
   647  func masqueradeEnroll(c *Client, id string, passInSubject bool, req *api.EnrollmentRequest) (*EnrollmentResponse, error) {
   648  	err := c.Init()
   649  	if err != nil {
   650  		return nil, err
   651  	}
   652  	csrPEM, key, err := c.GenCSR(req.CSR, id)
   653  	if err != nil {
   654  		log.Debugf("Enroll failure generating CSR: %s", err)
   655  		return nil, err
   656  	}
   657  	reqNet := &api.EnrollmentRequestNet{
   658  		CAName: req.CAName,
   659  	}
   660  	if req.CSR != nil {
   661  		reqNet.SignRequest.Hosts = req.CSR.Hosts
   662  	}
   663  	reqNet.SignRequest.Request = string(csrPEM)
   664  	reqNet.SignRequest.Profile = req.Profile
   665  	reqNet.SignRequest.Label = req.Label
   666  	if passInSubject {
   667  		reqNet.SignRequest.Subject = &signer.Subject{CN: id}
   668  	}
   669  	body, err := util.Marshal(reqNet, "SignRequest")
   670  	if err != nil {
   671  		return nil, err
   672  	}
   673  	// Send the CSR to the fabric-ca server with basic auth header
   674  	post, err := c.newPost("enroll", body)
   675  	if err != nil {
   676  		return nil, err
   677  	}
   678  	post.SetBasicAuth(req.Name, req.Secret)
   679  	var result enrollmentResponseNet
   680  	err = c.SendReq(post, &result)
   681  	if err != nil {
   682  		return nil, err
   683  	}
   684  	// Create the enrollment response
   685  	return c.newEnrollmentResponse(&result, req.Name, key)
   686  }
   687  
   688  // masqueradeReenroll reenrolls a new identity as a masquerader
   689  func masqueradeReenroll(c *Client, id string, identity *Identity, passInSubject bool, req *api.ReenrollmentRequest) (*EnrollmentResponse, error) {
   690  	err := c.Init()
   691  	if err != nil {
   692  		return nil, err
   693  	}
   694  	csrPEM, key, err := c.GenCSR(req.CSR, id)
   695  	if err != nil {
   696  		log.Debugf("Enroll failure generating CSR: %s", err)
   697  		return nil, err
   698  	}
   699  	reqNet := &api.EnrollmentRequestNet{
   700  		CAName: req.CAName,
   701  	}
   702  	if req.CSR != nil {
   703  		reqNet.SignRequest.Hosts = req.CSR.Hosts
   704  	}
   705  	reqNet.SignRequest.Request = string(csrPEM)
   706  	reqNet.SignRequest.Profile = req.Profile
   707  	reqNet.SignRequest.Label = req.Label
   708  	if passInSubject {
   709  		reqNet.SignRequest.Subject = &signer.Subject{CN: id}
   710  	}
   711  	body, err := util.Marshal(reqNet, "SignRequest")
   712  	if err != nil {
   713  		return nil, err
   714  	}
   715  	// Send the CSR to the fabric-ca server with basic auth header
   716  	var result enrollmentResponseNet
   717  	err = identity.Post("reenroll", body, &result, nil)
   718  	if err != nil {
   719  		return nil, err
   720  	}
   721  
   722  	// Create the enrollment response
   723  	return c.newEnrollmentResponse(&result, identity.GetName(), key)
   724  }