Skip to content

Commit

Permalink
COP Client Configuration File
Browse files Browse the repository at this point in the history
COP client will now make use of a configuration file. This will
simply the CLI commands on the client side. The config file will
be passed in using -config file.

Example:
cop client enroll -config ../testdata/cop_client.json admin adminpw

https://jira.hyperledger.org/browse/FAB-1622

Change-Id: I985ed5744eb8baef2c40ebedb3b1e0abf0fc1696
Signed-off-by: Saad Karim <[email protected]>
  • Loading branch information
Saad Karim authored and Keith Smith committed Jan 31, 2017
1 parent 6294c57 commit 5105f60
Show file tree
Hide file tree
Showing 22 changed files with 311 additions and 255 deletions.
29 changes: 23 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -232,7 +232,7 @@ Run the following command to start fabric-ca server:
# fabric-ca server start -config ../testdata/server-config.json
```

It is now listening on localhost port 8888.
It is now listening on localhost port 7054.

You can customize your fabric-ca config file at `../testdata/server-config.json`. For example,
if you want to disable authentication, you can do so by setting `authentication` to
Expand All @@ -241,13 +241,30 @@ Auhentication is added by fabric-ca since CFSSL does not perform authentication.
basic authentication header is required for the enroll request. All other requests
to the fabric-ca server will require a JWT-like token, but this work is not yet complete.

### Create Client Configuration File

The client requires a configuration file to enable TLS and successfully connect
to server. A sample client configuration file can be found at
`../testdata/client-config.json`. The configuration file is passed in using
a config flag.


The table below defines all the properties that can be set in the config file.

| Property | Description |
|-------------|--------------------------------------------------------------|
|serverURL | URL of the server |
|ca_certfiles | File path to root certificate of which server certificate is signed by |
|keyfile | File path to client TLS key on file system |
|certfile | File path to client TLS certificate on file system |

### Enroll the admin client

See the `FABRIC_CA/testdata/server-config.json` file and note the "admin" user with a password of "adminpw".
The following command gets an ecert for the admin user.

```
# fabric-ca client enroll admin adminpw http://localhost:8888
# fabric-ca client enroll -config ../testdata/client-config.json admin adminpw http://localhost:7054
```

The enrollment certificate is stored at `$FABRIC_CA_ENROLLMENT_DIR/cert.pem` by default, but a different
Expand All @@ -268,15 +285,15 @@ command except no username or password is required. Instead, your previously st
key is used to authenticate to the fabric-ca server.

```
# fabric-ca client reenroll http://localhost:8888
# fabric-ca client reenroll -config ../testdata/client-config.json http://localhost:7054
```

The enrollment certificate and enrollment key are stored in the same location as described in the previous section for the `enroll` command.

You can specify a new Certificate Signing Request JSON information when issue the reenroll command

```
# fabric-ca client reenroll http://localhost:8888 ../testdata/csr.json
# fabric-ca client reenroll -config ../testdata/client-config.json http://localhost:7054 ../testdata/csr.json
```

### Register a new user
Expand Down Expand Up @@ -311,7 +328,7 @@ registerrequest.json:
The following command will register the user.

```
# fabric-ca client register ../testdata/registerrequest.json http://localhost:8888
# fabric-ca client register -config ../testdata/client-config.json ../testdata/registerrequest.json http://localhost:7054
```

### LDAP
Expand Down Expand Up @@ -397,7 +414,7 @@ defaults
timeout server 50000
listen http-in
bind *:8888
bind *:7054
balance roundrobin
server server1 <hostname:port>
server server2 <hostname:port>
Expand Down
6 changes: 5 additions & 1 deletion cli/client/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,14 +25,18 @@ import (
_ "github.com/mattn/go-sqlite3" // import to support SQLite3
)

var configFile string

// Command are the client commands
func Command() error {
util.SetDefaultServerPort()
cmds := map[string]*cli.Command{
"register": RegisterCommand,
"enroll": EnrollCommand,
"reenroll": ReenrollCommand,
"revoke": RevokeCommand,
}

configFile = util.GetCommandLineOptValue("-config", true)

return cli.Start(cmds)
}
126 changes: 65 additions & 61 deletions cli/client/client_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,28 +20,38 @@ import (
"fmt"
"io/ioutil"
"os"
"path/filepath"
"path"
"testing"
"time"

"github.com/cloudflare/cfssl/cli"
"github.com/hyperledger/fabric-ca/cli/server"
"github.com/hyperledger/fabric-ca/util"
)

var serverStarted bool
var serverExitCode = 0
var dir string

const (
ClientTLSConfig = "client-config.json"
FabricCADB = "../../testdata/fabric-ca.db"
CFGFile = "testconfig.json"
var (
tdDir = "../../testdata"
cfgFile = "testconfig.json"
fabricCADB = path.Join(tdDir, "fabric-ca.db")
clientConfig = path.Join(tdDir, "client-config.json")
rrFile = path.Join(tdDir, "registerrequest.json")
)

// TestNewClient tests constructing a client
// TestNewClient tests constructing a client with a client config provided
func TestNewClient(t *testing.T) {
_, err := NewClient(util.GetServerURL())
loadMyIdentity := true
_, _, err := loadClient(loadMyIdentity, clientConfig)
if err != nil {
t.Errorf("Failed to create a client: %s", err)
}
}

// TestNewClient tests constructing a client without a client config provided, will use default values
func TestNewClientNoConfig(t *testing.T) {
loadMyIdentity := true
_, _, err := loadClient(loadMyIdentity, "")
if err != nil {
t.Errorf("Failed to create a client: %s", err)
}
Expand All @@ -50,26 +60,20 @@ func TestNewClient(t *testing.T) {
func TestEnrollCLI(t *testing.T) {
startServer()

clientConfig := filepath.Join(dir, ClientTLSConfig)
os.Link("../../testdata/client-config2.json", clientConfig)
os.Args = []string{"client", "enroll", "-config", clientConfig, "admin", "adminpw"}

c := new(cli.Config)

args := []string{"admin", "adminpw", util.GetServerURL()}

err := enrollMain(args, *c)
err := Command()
if err != nil {
t.Error("Failed to register, err: ", err)
}

}

func TestReenrollCLI(t *testing.T) {
c := new(cli.Config)

args := []string{util.GetServerURL()}
os.Args = []string{"client", "reenroll", "-config", clientConfig}

err := reenrollMain(args, *c)
err := Command()
if err != nil {
t.Error("Failed to reenroll, err: ", err)
}
Expand All @@ -78,47 +82,41 @@ func TestReenrollCLI(t *testing.T) {

func TestRegister(t *testing.T) {

c := new(cli.Config)

args := []string{"../../testdata/registerrequest.json", util.GetServerURL()}
os.Args = []string{"client", "register", "-config", clientConfig, rrFile}

err := registerMain(args, *c)
err := Command()
if err != nil {
t.Error("Failed to register, err: ", err)
}

}

func TestRegisterNotEnoughArgs(t *testing.T) {
c := new(cli.Config)

args := []string{"../../testdata/registerrequest.json"}
os.Args = []string{"client", "register", "-config", clientConfig, rrFile}

err := registerMain(args, *c)
err := Command()
if err == nil {
t.Error("Should have failed, not enough arguments provided")
}

}

func TestRegisterNoJSON(t *testing.T) {
c := new(cli.Config)

args := []string{"", "admin", util.GetServerURL()}
os.Args = []string{"client", "register", "-config", clientConfig, "", "admin"}

err := registerMain(args, *c)
err := Command()
if err == nil {
t.Error("Should result in failure if registration json file not specificied, error: ", err)
}

}

func TestRegisterMissingRegistrar(t *testing.T) {
c := new(cli.Config)
os.Args = []string{"client", "register", "-config", clientConfig, "", ""}

args := []string{"", "", util.GetServerURL()}

err := registerMain(args, *c)
err := Command()
if err == nil {
t.Error("Should result in failure if no registrar identity exists")
}
Expand All @@ -127,11 +125,9 @@ func TestRegisterMissingRegistrar(t *testing.T) {

func TestRevoke(t *testing.T) {

c := new(cli.Config)
os.Args = []string{"client", "revoke", "-config", clientConfig, "admin"}

args := []string{util.GetServerURL(), "admin"}

err := revokeMain(args, *c)
err := Command()
if err != nil {
t.Errorf("TestRevoke failed: %s", err)
}
Expand All @@ -140,11 +136,9 @@ func TestRevoke(t *testing.T) {

func TestEnrollCLINotEnoughArgs(t *testing.T) {

c := new(cli.Config)

args := []string{"testUser"}
os.Args = []string{"client", "enroll", "-config", clientConfig, "testUser"}

err := enrollMain(args, *c)
err := Command()
if err == nil {
t.Error("Should have failed, not enough argument provided")
}
Expand All @@ -153,11 +147,9 @@ func TestEnrollCLINotEnoughArgs(t *testing.T) {

func TestEnrollCLIWithCSR(t *testing.T) {

c := new(cli.Config)

args := []string{"notadmin", "pass", util.GetServerURL(), "../../testdata/csr.json"}
os.Args = []string{"client", "enroll", "-config", clientConfig, "notadmin", "pass", rrFile}

err := enrollMain(args, *c)
err := Command()
if err != nil {
t.Error("Failed to enroll, err: ", err)
}
Expand All @@ -166,41 +158,53 @@ func TestEnrollCLIWithCSR(t *testing.T) {

func TestReenrollCLIWithCSR(t *testing.T) {

c := new(cli.Config)

args := []string{util.GetServerURL(), "../../testdata/csr.json"}
os.Args = []string{"client", "reenroll", "-config", clientConfig, rrFile}

err := reenrollMain(args, *c)
err := Command()
if err != nil {
t.Error("Failed to reenroll, err: ", err)
}
}

func TestRevokeNoArg(t *testing.T) {

c := new(cli.Config)
os.Args = []string{"client", "revoke", "-config", clientConfig}

args := []string{util.GetServerURL()}

err := revokeMain(args, *c)
err := Command()
if err == nil {
t.Error("TestRevokeNoArg succeeded but should have failed")
}
}

func TestRevokeNotAdmin(t *testing.T) {

c := new(cli.Config)
os.Args = []string{"client", "revoke", "-config", clientConfig, "admin"}

args := []string{util.GetServerURL(), "admin"}

err := revokeMain(args, *c)
err := Command()
if err == nil {
t.Error("TestRevokeNotAdmin should have failed but didn't")
}

}

func TestIncompleteCommand(t *testing.T) {
os.Args = []string{"client"}

err := Command()
if err == nil {
t.Error("Expected an error stating no command was given")
}
}

func TestUnsupportedCommand(t *testing.T) {
os.Args = []string{"client", "unsupportedCMD"}

err := Command()
if err == nil {
t.Error("Expected an error stating command is not defined")
}
}

func TestBogusCommand(t *testing.T) {
err := Command()
if err == nil {
Expand All @@ -210,15 +214,15 @@ func TestBogusCommand(t *testing.T) {

func TestLast(t *testing.T) {
// Cleanup
os.Remove(FabricCADB)
os.Remove(fabricCADB)
os.RemoveAll(dir)
}

func runServer() {
os.Setenv("FABRIC_CA_DEBUG", "true")
s := new(server.Server)
s.ConfigDir = "../../testdata"
s.ConfigFile = CFGFile
s.ConfigDir = tdDir
s.ConfigFile = cfgFile
s.StartFromConfig = false
s.Start()
}
Expand All @@ -232,7 +236,7 @@ func startServer() {
}

if !serverStarted {
os.Remove(FabricCADB)
os.Remove(fabricCADB)
os.RemoveAll(dir)
serverStarted = true
fmt.Println("starting fabric-ca server ...")
Expand Down
Loading

0 comments on commit 5105f60

Please sign in to comment.