From a9ff4d4f6eb6f87e6bc78f4f1e220b6140d2024f Mon Sep 17 00:00:00 2001 From: Keith Smith Date: Sun, 11 Dec 2016 05:53:37 -0500 Subject: [PATCH] Store COP enrollment artifacts in MSP friendly way Instead of storing all enrollment artifacts in a single client.json file, store it in separate key and store files. This is inline with MSP (Membership Service Provider) APIs. The enrollment certificate is stored at `$COP_ENROLLMENT_DIR/cert.pem` by default, but a different path can be specified by setting the `COP_CERT_FILE` environment variable. The enrollment key is stored at `$COP_ENROLLMENT_DIR/key.pem` by default, but a different path can be specified by setting the `COP_KEY_FILE` environment variable. The default value of the `COP_ENROLLMENT_DIR` environment variable is `$COP_HOME`. The default value of the `COP_HOME` environment variable is `$HOME/cop`. See https://jira.hyperledger.org/browse/FAB-1353 Change-Id: I77625acefad9365a345dc107d94ddf6c86e877c1 Signed-off-by: Keith Smith --- README.md | 12 +++++- cli/client/enroll.go | 3 +- cli/client/reenroll.go | 3 +- cli/server/server_test.go | 77 ++++++++++++++++++++------------------- factory.go | 5 --- factory_test.go | 7 ---- idp/idp.go | 9 ----- lib/client.go | 77 ++++++++++++++++++++++++++------------- lib/client_test.go | 18 --------- lib/identity.go | 24 +++--------- lib/identity_test.go | 10 ----- testdata/client.json | 1 - util/util.go | 10 ++--- util/util_test.go | 30 ++++++++++++--- 14 files changed, 141 insertions(+), 145 deletions(-) delete mode 100644 testdata/client.json diff --git a/README.md b/README.md index 7ec2e8520..c63b5922e 100644 --- a/README.md +++ b/README.md @@ -249,7 +249,15 @@ The following command gets an ecert for the admin user. # ./cop client enroll admin adminpw http://localhost:8888 ``` -Note that this stores the enrollment material in the `$COP_HOME/client.json` file. +The enrollment certificate is stored at `$COP_ENROLLMENT_DIR/cert.pem` by default, but a different +path can be specified by setting the `COP_CERT_FILE` environment variable to an absolute path name or a path relative to the current working directory. + +The enrollment key is stored at `$COP_ENROLLMENT_DIR/key.pem` by default, but a different +path can be specified by setting the `COP_KEY_FILE` environment variable to an absolute path name or a path relative to the current working directory. + +The default value of the `COP_ENROLLMENT_DIR` environment variable is `$COP_HOME`. + +The default value of the `COP_HOME` environment variable is `$HOME/.cop`. ### Reenroll @@ -263,7 +271,7 @@ key is used to authenticate to the COP server. # ./cop client reenroll ../testdata/csr.json http://localhost:8888 ``` -Note that this updates the enrollment material in the `$COP_HOME/client.json` file. +The enrollment certificate and enrollment key are stored in the same location as described in the previous section for the `enroll` command. ### Register a new user diff --git a/cli/client/enroll.go b/cli/client/enroll.go index c4f74b544..5482a12dd 100644 --- a/cli/client/enroll.go +++ b/cli/client/enroll.go @@ -92,7 +92,8 @@ func enrollMain(args []string, c cli.Config) error { return fmt.Errorf("failed to store enrollment information: %s", err) } - log.Infof("enrollment information was successfully stored in %s", client.GetMyIdentityFile()) + log.Infof("enrollment information was successfully stored in %s and %s", + client.GetMyKeyFile(), client.GetMyCertFile()) return nil } diff --git a/cli/client/reenroll.go b/cli/client/reenroll.go index d6ef7b049..25da7c7f3 100644 --- a/cli/client/reenroll.go +++ b/cli/client/reenroll.go @@ -80,7 +80,8 @@ func reenrollMain(args []string, c cli.Config) error { return err } - log.Infof("enrollment information was successfully stored in %s", client.GetMyIdentityFile()) + log.Infof("enrollment information was successfully stored in %s and %s", + client.GetMyKeyFile(), client.GetMyCertFile()) return nil } diff --git a/cli/server/server_test.go b/cli/server/server_test.go index eb309bd70..3209543f8 100644 --- a/cli/server/server_test.go +++ b/cli/server/server_test.go @@ -25,12 +25,10 @@ import ( "testing" "time" - factory "github.com/hyperledger/fabric-cop" "github.com/hyperledger/fabric-cop/cli/server/dbutil" "github.com/hyperledger/fabric-cop/cli/server/ldap" "github.com/hyperledger/fabric-cop/idp" "github.com/hyperledger/fabric-cop/lib" - "github.com/hyperledger/fabric-cop/util" ) const ( @@ -88,21 +86,23 @@ func TestRegisterUser(t *testing.T) { clientConfig := filepath.Join(dir, ClientTLSConfig) os.Link("../../testdata/cop_client2.json", clientConfig) - copServer := `{"serverURL":"https://localhost:8888"}` - c, _ := lib.NewClient(copServer) + c := getClient(t) + if c == nil { + return + } enrollReq := &idp.EnrollmentRequest{ Name: "admin", Secret: "adminpw", } - ID, err := c.Enroll(enrollReq) + id, err := c.Enroll(enrollReq) if err != nil { t.Error("Enroll of user 'admin' with password 'adminpw' failed") return } - err = ID.Store() + err = id.Store() if err != nil { t.Errorf("Failed to store enrollment information: %s", err) return @@ -114,14 +114,6 @@ func TestRegisterUser(t *testing.T) { Group: "bank_a", } - id, _ := factory.NewIdentity() - path := filepath.Join(dir, "client.json") - identity, err := ioutil.ReadFile(path) - if err != nil { - t.Error(err) - } - util.Unmarshal(identity, id, "identity") - regReq.Registrar = id _, err = c.Register(regReq) @@ -131,10 +123,8 @@ func TestRegisterUser(t *testing.T) { } func TestMisc(t *testing.T) { - copServer := `{"serverURL":"https://localhost:8888"}` - c, err := lib.NewClient(copServer) - if err != nil { - t.Errorf("TestMisc.NewClient failed: %s", err) + c := getClient(t) + if c == nil { return } id, err := c.LoadMyIdentity() @@ -152,8 +142,10 @@ func TestMisc(t *testing.T) { } func TestEnrollUser(t *testing.T) { - copServer := `{"serverURL":"https://localhost:8888"}` - c, _ := lib.NewClient(copServer) + c := getClient(t) + if c == nil { + return + } req := &idp.EnrollmentRequest{ Name: "testUser", @@ -184,8 +176,10 @@ func TestEnrollUser(t *testing.T) { } func TestRevoke(t *testing.T) { - copServer := `{"serverURL":"https://localhost:8888"}` - c, _ := lib.NewClient(copServer) + c := getClient(t) + if c == nil { + return + } req := &idp.EnrollmentRequest{ Name: "admin2", @@ -243,26 +237,25 @@ func TestGetTCerts(t *testing.T) { } func TestMaxEnrollment(t *testing.T) { - CFG.UsrReg.MaxEnrollments = 2 - - copServer := `{"serverURL":"https://localhost:8888"}` - c, _ := lib.NewClient(copServer) - - regReq := &idp.RegistrationRequest{ - Name: "MaxTestUser", - Type: "Client", - Group: "bank_a", + c := getClient(t) + if c == nil { + return } - id, _ := factory.NewIdentity() - path := filepath.Join(dir, "client.json") - identity, err := ioutil.ReadFile(path) + id, err := c.LoadMyIdentity() if err != nil { - t.Error(err) + t.Errorf("TestMisc.LoadMyIdentity failed: %s", err) + return } - util.Unmarshal(identity, id, "identity") - regReq.Registrar = id + CFG.UsrReg.MaxEnrollments = 2 + + regReq := &idp.RegistrationRequest{ + Name: "MaxTestUser", + Type: "Client", + Group: "bank_a", + Registrar: id, + } resp, err := c.Register(regReq) if err != nil { @@ -485,3 +478,13 @@ func testWithoutAuthHdr(c *lib.Client, t *testing.T) { t.Error("testWithAuthHdr.SendPost should have failed but passed") } } + +func getClient(t *testing.T) *lib.Client { + copServer := `{"serverURL":"https://localhost:8888"}` + c, err := lib.NewClient(copServer) + if err != nil { + t.Fatalf("TestMisc.NewClient failed: %s", err) + return nil + } + return c +} diff --git a/factory.go b/factory.go index e4b29d06d..107cfc326 100644 --- a/factory.go +++ b/factory.go @@ -27,8 +27,3 @@ import "github.com/hyperledger/fabric-cop/lib" func NewClient(config string) (*lib.Client, error) { return lib.NewClient(config) } - -// NewIdentity creates a new identity -func NewIdentity() (*lib.Identity, error) { - return new(lib.Identity), nil -} diff --git a/factory_test.go b/factory_test.go index 6b9436065..35d2343c3 100644 --- a/factory_test.go +++ b/factory_test.go @@ -33,10 +33,3 @@ func TestNewClientBadConfig(t *testing.T) { t.Error("TestNewClientBadConfig did not fail but should have") } } - -func TestNewIdentity(t *testing.T) { - _, err := NewIdentity() - if err != nil { - t.Error("Failed to create identity") - } -} diff --git a/idp/idp.go b/idp/idp.go index 9e2af2435..11b8f2d64 100644 --- a/idp/idp.go +++ b/idp/idp.go @@ -51,9 +51,6 @@ type ClientAPI interface { // ImportSigner imports a signer from an external CA // @param req The import request ImportSigner(req *ImportSignerRequest) (Signer, error) - - // DeserializeIdentity deserializes an identity - DeserializeIdentity([]byte) (Identity, error) } // PeerAPI is the API used by the peer pertaining to the IDP @@ -87,9 +84,6 @@ type Identity interface { // Delete this identity completely and revoke all of it's signers Delete() error - - // Serialize an identity - Serialize() ([]byte, error) } // TemporalSigner is a signer which can be renewed and revoked @@ -135,9 +129,6 @@ type Verifier interface { // VerifyAttributes verifies attributes given proofs VerifyAttributes(proof [][]byte, spec *AttributeProofSpec) error - - // Serialize verifier - Serialize() ([]byte, error) } // RegistrationRequest for a new identity diff --git a/lib/client.go b/lib/client.go index ce87e673e..8888a321a 100644 --- a/lib/client.go +++ b/lib/client.go @@ -54,7 +54,6 @@ func NewClient(config string) (*Client, error) { // Set defaults c.ServerURL = "http://localhost:8888" c.HomeDir = util.GetDefaultHomeDir() - c.MyIDFile = "client.json" if config != "" { // Override any defaults err := util.Unmarshal([]byte(config), c, "NewClient") @@ -71,8 +70,6 @@ type Client struct { ServerURL string `json:"serverURL,omitempty"` // HomeDir is the home directory HomeDir string `json:"homeDir,omitempty"` - // MyIDFIle is the name of ID file which gets loaded by LoadMyIdentity - MyIDFile string `json:"fileName,omitempty"` } // Capabilities returns the capabilities COP @@ -101,6 +98,7 @@ func (c *Client) Register(req *idp.RegistrationRequest) (*idp.RegistrationRespon if req.Registrar == nil { return nil, errors.New("Register was called without a Registrar identity set") } + var request cop.RegisterRequest request.User = req.Name request.Type = req.Type @@ -108,9 +106,6 @@ func (c *Client) Register(req *idp.RegistrationRequest) (*idp.RegistrationRespon request.Attributes = req.Attributes request.CallerID = req.Registrar.GetName() - newID := newIdentity(c, req.Registrar.GetName(), req.Registrar.(*Identity).GetMyKey(), req.Registrar.(*Identity).GetMyCert()) - req.Registrar = newID - reqBody, err := util.Marshal(request, "RegistrationRequest") if err != nil { return nil, err @@ -285,25 +280,65 @@ func (c *Client) ImportSigner(req *idp.ImportSignerRequest) (idp.Signer, error) // LoadMyIdentity loads the client's identity from disk func (c *Client) LoadMyIdentity() (*Identity, error) { - myIDFile := c.GetMyIdentityFile() - if !util.FileExists(myIDFile) { - return nil, fmt.Errorf("client is not enrolled; '%s' is not an existing file", myIDFile) + return c.LoadIdentity(c.GetMyKeyFile(), c.GetMyCertFile()) +} + +// StoreMyIdentity stores my identity to disk +func (c *Client) StoreMyIdentity(key, cert []byte) error { + err := util.WriteFile(c.GetMyKeyFile(), key, 0600) + if err != nil { + return err + } + return util.WriteFile(c.GetMyCertFile(), cert, 0644) +} + +// GetMyKeyFile returns the path to this identity's key file +func (c *Client) GetMyKeyFile() string { + file := os.Getenv("COP_KEY_FILE") + if file == "" { + file = path.Join(c.GetMyEnrollmentDir(), "key.pem") + } + return file +} + +// GetMyCertFile returns the path to this identity's certificate file +func (c *Client) GetMyCertFile() string { + file := os.Getenv("COP_CERT_FILE") + if file == "" { + file = path.Join(c.GetMyEnrollmentDir(), "cert.pem") } - return c.LoadIdentity(myIDFile) + return file } -// GetMyIdentityFile returns the path to this identity's ID file -func (c *Client) GetMyIdentityFile() string { - return path.Join(c.HomeDir, c.MyIDFile) +// GetMyEnrollmentDir returns the path to this identity's enrollment directory +func (c *Client) GetMyEnrollmentDir() string { + dir := os.Getenv("COP_ENROLLMENT_DIR") + if dir == "" { + dir = c.HomeDir + } + return dir } -// LoadIdentity loads an identity from a file on disk at path -func (c *Client) LoadIdentity(path string) (*Identity, error) { - buf, err := util.ReadFile(path) +// LoadIdentity loads an identity from disk +func (c *Client) LoadIdentity(keyFile, certFile string) (*Identity, error) { + key, err := util.ReadFile(keyFile) + if err != nil { + return nil, err + } + cert, err := util.ReadFile(certFile) if err != nil { return nil, err } - return c.DeserializeIdentity(buf) + return c.NewIdentity(key, cert) +} + +// NewIdentity creates a new identity +func (c *Client) NewIdentity(key, cert []byte) (*Identity, error) { + name, err := util.GetEnrollmentIDFromPEM(cert) + if err != nil { + return nil, err + } + return newIdentity(c, name, key, cert), nil } // LoadCSRInfo reads CSR (Certificate Signing Request) from a file @@ -321,14 +356,6 @@ func (c *Client) LoadCSRInfo(path string) (*idp.CSRInfo, error) { return &csrInfo, nil } -// DeserializeIdentity deserializes an identity -func (c *Client) DeserializeIdentity(buf []byte) (*Identity, error) { - id := new(Identity) - err := util.Unmarshal(buf, id, "Identity") - id.client = c - return id, err -} - // NewPost create a new post request func (c *Client) NewPost(endpoint string, reqBody []byte) (*http.Request, error) { curl, cerr := c.getURL(endpoint) diff --git a/lib/client_test.go b/lib/client_test.go index b1e194c18..ead2506d9 100644 --- a/lib/client_test.go +++ b/lib/client_test.go @@ -210,24 +210,6 @@ func testCapabilities(c *Client, t *testing.T) { } } -func TestDeserializeIdentity(t *testing.T) { - config := `{"serverURL":"https://localhost:8888"}` - c, err := NewClient(config) - if err != nil { - t.Error("Failed to create client object") - } - - idByte, err := ioutil.ReadFile("../testdata/client.json") - if err != nil { - t.Error("Error occured during reading of id file") - } - - _, err = c.DeserializeIdentity(idByte) - if err != nil { - t.Error("Error occured during deserialization, error: ", err) - } -} - func TestSendBadPost(t *testing.T) { c := new(Client) curl := "fake" diff --git a/lib/identity.go b/lib/identity.go index bc4c60ba6..d6a10be50 100644 --- a/lib/identity.go +++ b/lib/identity.go @@ -18,6 +18,7 @@ package lib import ( "errors" + "fmt" "net/http" "github.com/cloudflare/cfssl/log" @@ -111,27 +112,12 @@ func (i *Identity) Delete() error { return errors.New("NotImplemented") } -// Store write my identity info to my identity file +// Store write my identity info func (i *Identity) Store() error { - return i.StorePath(i.client.GetMyIdentityFile()) -} - -// StorePath stores my identity info to a file located at path -func (i *Identity) StorePath(path string) error { - idByte, err := i.Serialize() - if err != nil { - return err - } - err = util.WriteFile(path, idByte, 0600) - if err != nil { - return err + if i.client == nil { + return fmt.Errorf("An identity with no client may not be stored") } - return nil -} - -// Serialize this identity -func (i *Identity) Serialize() ([]byte, error) { - return util.Marshal(i, "identity") + return i.client.StoreMyIdentity(i.PublicSigner.Key, i.PublicSigner.Cert) } // Post sends arbtrary request body (reqBody) to an endpoint. diff --git a/lib/identity_test.go b/lib/identity_test.go index 5a150b0cb..ff4692640 100644 --- a/lib/identity_test.go +++ b/lib/identity_test.go @@ -30,22 +30,12 @@ func getIdentity() *Identity { func TestIdentity(t *testing.T) { id := getIdentity() - testIdentityMarshalling(id, t) testGetName(id, t) testGetPublicSigner(id, t) testGetAttributeNames(id, t) testDelete(id, t) } -func testIdentityMarshalling(id *Identity, t *testing.T) { - // identity := `{"registrar":{"name":"admin","publicSigner":{"cert":"LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUIvVENDQWFTZ0F3SUJBZ0lVVmE1WkpVd0ZTcU9MVjFRcU94clY3TkVadnJRd0NnWUlLb1pJemowRUF3SXcKYlRFTE1Ba0dBMVVFQmhNQ1ZWTXhFekFSQmdOVkJBZ1RDa05oYkdsbWIzSnVhV0V4RmpBVUJnTlZCQWNURFZOaApiaUJHY21GdVkybHpZMjh4RXpBUkJnTlZCQW9UQ2tOc2IzVmtSbXhoY21VeEhEQWFCZ05WQkFzVEUxTjVjM1JsCmJYTWdSVzVuYVc1bFpYSnBibWN3SGhjTk1UWXhNVEF6TURVeE9EQXdXaGNOTVRjeE1UQXpNRFV4T0RBd1dqQVEKTVE0d0RBWURWUVFERXdWaFpHMXBiakJaTUJNR0J5cUdTTTQ5QWdFR0NDcUdTTTQ5QXdFSEEwSUFCT0xtT081dwo3REh6RUtNdkpJZmxwZjhQb1Z5dk1Uays1UmorQ1NBcVhQQ0NoNndPTi9yMnAxZjF6cDRmQXhVak96S1VMNCtrCnRpVm9pVHJmUUJzY010bWpmekI5TUE0R0ExVWREd0VCL3dRRUF3SUZvREFkQmdOVkhTVUVGakFVQmdnckJnRUYKQlFjREFRWUlLd1lCQlFVSEF3SXdEQVlEVlIwVEFRSC9CQUl3QURBZEJnTlZIUTRFRmdRVUJqc2RIV3RPcEZQTQpSZ3VJT3VITm1iaDdKem93SHdZRFZSMGpCQmd3Rm9BVWZrMTRuOXM0M25NakNpNWdWWnZuRG4vUWhWY3dDZ1lJCktvWkl6ajBFQXdJRFJ3QXdSQUlnWjJLYVU5R29CYzhqQ0pRTDdTcDg2RUVXT282UXJzK0FpdWV5VVIwMVdtVUMKSUF1RE1wSTdMOXJvREpjV3Y5WWF3NmwzdEVBYTBmdVJGY21ncFFXWEQ4eUkKLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQo=","key":"LS0tLS1CRUdJTiBFQyBQUklWQVRFIEtFWS0tLS0tCk1IY0NBUUVFSUFMVkFWK044azdOOXhvSEtOV3pzUFc5N0g2TFAvRlNkb2lKeWtaY2xRTkFvQW9HQ0NxR1NNNDkKQXdFSG9VUURRZ0FFNHVZNDduRHNNZk1Rb3k4a2grV2wvdytoWEs4eE9UN2xHUDRKSUNwYzhJS0hyQTQzK3ZhbgpWL1hPbmg4REZTTTdNcFF2ajZTMkpXaUpPdDlBR3h3eTJRPT0KLS0tLS1FTkQgRUMgUFJJVkFURSBLRVktLS0tLQo="}}}` - - _, err := id.Serialize() - if err != nil { - t.Error("Failed to serialize to identity object") - } -} - func testGetName(id *Identity, t *testing.T) { name := id.GetName() if name != "test" { diff --git a/testdata/client.json b/testdata/client.json deleted file mode 100644 index 6a6528b7d..000000000 --- a/testdata/client.json +++ /dev/null @@ -1 +0,0 @@ -{"name":"admin","publicSigner":{"cert":"LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUNqRENDQWpLZ0F3SUJBZ0lVQkVWd3NTeDBUbXFkYnpOd2xlTkJCem9JVDB3d0NnWUlLb1pJemowRUF3SXcKZnpFTE1Ba0dBMVVFQmhNQ1ZWTXhFekFSQmdOVkJBZ1RDa05oYkdsbWIzSnVhV0V4RmpBVUJnTlZCQWNURFZOaApiaUJHY21GdVkybHpZMjh4SHpBZEJnTlZCQW9URmtsdWRHVnlibVYwSUZkcFpHZGxkSE1zSUVsdVl5NHhEREFLCkJnTlZCQXNUQTFkWFZ6RVVNQklHQTFVRUF4TUxaWGhoYlhCc1pTNWpiMjB3SGhjTk1UWXhNVEV4TVRjd056QXcKV2hjTk1UY3hNVEV4TVRjd056QXdXakJqTVFzd0NRWURWUVFHRXdKVlV6RVhNQlVHQTFVRUNCTU9UbTl5ZEdnZwpRMkZ5YjJ4cGJtRXhFREFPQmdOVkJBY1RCMUpoYkdWcFoyZ3hHekFaQmdOVkJBb1RFa2g1Y0dWeWJHVmtaMlZ5CklFWmhZbkpwWXpFTU1Bb0dBMVVFQ3hNRFEwOVFNRmt3RXdZSEtvWkl6ajBDQVFZSUtvWkl6ajBEQVFjRFFnQUUKSEJ1S3NBTzQzaHM0SkdwRmZpR01rQi94c0lMVHNPdm1OMldtd3BzUEhaTkw2dzhIV2UzeENQUXRkRy9YSkp2WgorQzc1NktFc1VCTTN5dzVQVGZrdThxT0JwekNCcERBT0JnTlZIUThCQWY4RUJBTUNCYUF3SFFZRFZSMGxCQll3CkZBWUlLd1lCQlFVSEF3RUdDQ3NHQVFVRkJ3TUNNQXdHQTFVZEV3RUIvd1FDTUFBd0hRWURWUjBPQkJZRUZPRkMKZGNVWjRlczNsdGlDZ0FWRG95TGZWcFBJTUI4R0ExVWRJd1FZTUJhQUZCZG5RajJxbm9JL3hNVWRuMXZEbWRHMQpuRWdRTUNVR0ExVWRFUVFlTUJ5Q0NtMTVhRzl6ZEM1amIyMkNEbmQzZHk1dGVXaHZjM1F1WTI5dE1Bb0dDQ3FHClNNNDlCQU1DQTBnQU1FVUNJRGY5SGJsNHhuM3o0RXdOS21pbE05bFgyRnE0aldwQWFSVkI5N09tVkVleUFpRUEKMjVhRFBRSEdHcTJBdmhLVDB3dnQwOGNYMUdUR0NJYmZtdUxwTXdLUWozOD0KLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQo=","key":"LS0tLS1CRUdJTiBFQyBQUklWQVRFIEtFWS0tLS0tCk1IY0NBUUVFSUFzV3dGdW5FenF6MVJoNm52RDRNaVBrS0N0bW94emgzalRxdUc1TVNiZUxvQW9HQ0NxR1NNNDkKQXdFSG9VUURRZ0FFSEJ1S3NBTzQzaHM0SkdwRmZpR01rQi94c0lMVHNPdm1OMldtd3BzUEhaTkw2dzhIV2UzeApDUFF0ZEcvWEpKdlorQzc1NktFc1VCTTN5dzVQVGZrdThnPT0KLS0tLS1FTkQgRUMgUFJJVkFURSBLRVktLS0tLQo="}} diff --git a/util/util.go b/util/util.go index 915c3e655..aead36210 100644 --- a/util/util.go +++ b/util/util.go @@ -35,6 +35,7 @@ import ( mrand "math/rand" "net/http" "os" + "path" "path/filepath" "strings" "time" @@ -337,7 +338,7 @@ func B64Decode(str string) (buf []byte, err error) { return base64.RawStdEncoding.DecodeString(str) } -// GetDB returns DB +// GetDB returns a handle to an established driver-specific database connection func GetDB(driver string, dbPath string) (*sqlx.DB, error) { return sqlx.Open(driver, dbPath) } @@ -374,12 +375,11 @@ func GetDefaultHomeDir() string { if home == "" { home = os.Getenv("HOME") if home != "" { - home = home + "/.cop" + home = path.Join(home, "/cop") + } else { + home = "/var/hyperledger/fabric/dev/fabric-cop" } } - if home == "" { - home = "/var/hyperledger/fabric/dev/.fabric-cop" - } return home } diff --git a/util/util_test.go b/util/util_test.go index ef62d0342..cf9881e2e 100644 --- a/util/util_test.go +++ b/util/util_test.go @@ -24,9 +24,12 @@ import ( _ "github.com/mattn/go-sqlite3" ) -func TestGetEnrollmentID(t *testing.T) { - cert, _ := ioutil.ReadFile(getPath("ec.pem")) - _, err := GetEnrollmentIDFromPEM(cert) +func TestGetEnrollmentIDFromPEM(t *testing.T) { + cert, err := ioutil.ReadFile(getPath("ec.pem")) + if err != nil { + t.Fatalf("TestGetEnrollmentIDFromPEM.ReadFile failed: %s", err) + } + _, err = GetEnrollmentIDFromPEM(cert) if err != nil { t.Fatalf("Failed to get enrollment ID from PEM: %s", err) } @@ -140,13 +143,13 @@ func TestGetDefaultHomeDir(t *testing.T) { os.Setenv("COP_HOME", "") os.Setenv("HOME", "") home := GetDefaultHomeDir() - if home != "/var/hyperledger/fabric/dev/.fabric-cop" { + if home != "/var/hyperledger/fabric/dev/fabric-cop" { t.Errorf("Incorrect default home (%s) path retrieved", home) } os.Setenv("HOME", "/tmp") home = GetDefaultHomeDir() - if home != "/tmp/.cop" { + if home != "/tmp/cop" { t.Errorf("Incorrect $HOME (%s) path retrieved", home) } @@ -215,3 +218,20 @@ func TestFileExists(t *testing.T) { t.Error("File does not exist") } } + +func TestMakeFileAbs(t *testing.T) { + makeFileAbs(t, "", "", "") + makeFileAbs(t, "/a/b/c", "", "/a/b/c") + makeFileAbs(t, "c", "/a/b", "/a/b/c") + makeFileAbs(t, "../c", "/a/b", "/a/c") +} + +func makeFileAbs(t *testing.T, file, dir, expect string) { + path, err := MakeFileAbs(file, dir) + if err != nil { + t.Errorf("Failed to make %s absolute: %s", file, err) + } + if path != expect { + t.Errorf("Absolute of file=%s with dir=%s expected %s but was %s", file, dir, expect, path) + } +}