Skip to content

Commit

Permalink
Registration request part of client config
Browse files Browse the repository at this point in the history
Registration process simplified by incorporate registration
information in the overall client config file. This eliminates having
to provide a register file through a flag in the register CLI.
Registrar will update this config file with any relevant user
information before calling the register request from the command line.

This will be followed up with another change-set that will force
the client to only be able to execute enroll command as it first
command. This will create the enrollment data, client config file,
and client home directory. This is all pertinent information that is
needed for other commands to complete successfully.

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

Change-Id: I61bdabe75a7d14425864e9eed2be6dc771f8d31e
Signed-off-by: Saad Karim <[email protected]>
  • Loading branch information
Saad Karim committed Mar 2, 2017
1 parent 878804c commit 4d9e2e3
Show file tree
Hide file tree
Showing 9 changed files with 123 additions and 77 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,4 @@ testdata/fabric*ca.db
testdata/initFabricCaFvt.json
testdata/openssl.cnf.base.this
testdata/runFabricCaFvt.json
fabric-ca
12 changes: 7 additions & 5 deletions api/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,19 +26,21 @@ import (
// RegistrationRequest for a new identity
type RegistrationRequest struct {
// Name is the unique name of the identity
Name string `json:"id"`
Name string `json:"id" help:"Unique name of the identity"`
// Type of identity being registered (e.g. "peer, app, user")
Type string `json:"type"`
Type string `json:"type" help:"Type of identity being registered (e.g. 'peer, app, user')"`
// Secret is an optional password. If not specified,
// a random secret is generated. In both cases, the secret
// is returned in the RegistrationResponse.
Secret string `json:"secret,omitempty"`
Secret string `json:"secret,omitempty" help:"The enrollment secret for the identity being registered"`
// MaxEnrollments is the maximum number of times the secret can
// be reused to enroll.
MaxEnrollments int `json:"max_enrollments,omitempty"`
MaxEnrollments int `json:"max_enrollments,omitempty" help:"The maximum number of times the secret can be reused to enroll."`
// is returned in the response.
// Group name associated with the identity
Group string `json:"group"`
Group string `json:"group" help:"Name associated with the identity"`
// Attr is used to support a single attribute provided through the fabric-ca-client CLI
Attr string `help:"Attributes associated with this identity (e.g. hf.Revoker=true)"`
// Attributes associated with this identity
Attributes []Attribute `json:"attrs,omitempty"`
}
Expand Down
26 changes: 25 additions & 1 deletion cmd/fabric-ca-client/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,10 +53,14 @@ const (
# Examples:
# a) --url https://localhost:7054
# To set the fabric-ca server url
# b) --tls.client.certfile certfile.pem
# To set the client certificate for TLS
# 2) environment variable
# Examples:
# a) FABRIC_CA_CLIENT_URL=https://localhost:7054
# To set the fabric-ca server url
# b) FABRIC_CA_CLIENT_TLS_CLIENT_CERTFILE=certfile.pem
# To set the client certificate for TLS
# 3) configuration file
# 4) default value (if there is one)
# All default values are shown beside each element below.
Expand Down Expand Up @@ -110,6 +114,17 @@ csr:
pathlen:
pathlenzero:
expiry:
#############################################################################
# Registration section used to register a new user with fabric-ca server
#############################################################################
id:
name:
type:
group:
attributes:
- name:
value:
`
)

Expand Down Expand Up @@ -171,7 +186,9 @@ func configInit() error {
clientCfg.TLS.Enabled = purl.Scheme == "https"

processCertFiles(&clientCfg.TLS)

if clientCfg.ID.Attr != "" {
processAttributes()
}
return nil
}

Expand Down Expand Up @@ -213,3 +230,10 @@ func processCertFiles(cfg *tls.ClientTLSConfig) {
cfg.CertFilesList = append(cfg.CertFilesList, strings.TrimSpace(CertFiles[i]))
}
}

// processAttributes parses attributes from command line
func processAttributes() {
splitAttr := strings.Split(clientCfg.ID.Attr, "=")
clientCfg.ID.Attributes[0].Name = splitAttr[0]
clientCfg.ID.Attributes[0].Value = strings.Join(splitAttr[1:], "")
}
110 changes: 69 additions & 41 deletions cmd/fabric-ca-client/main_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,18 +30,25 @@ import (
)

const (
testYaml = "test.yaml"
myhost = "hostname"
certfile = "ec.pem"
keyfile = "ec-key.pem"
tdDir = "../../testdata"
db = "fabric-ca-server.db"
testYaml = "../../testdata/test.yaml"
myhost = "hostname"
certfile = "ec.pem"
keyfile = "ec-key.pem"
tlsCertFile = "tls_server-cert.pem"
tlsKeyFile = "tls_server-key.pem"
rootCert = "root.pem"
tlsClientCertFile = "tls_client-cert.pem"
tlsClientKeyFile = "tls_client-key.pem"
tdDir = "../../testdata"
db = "fabric-ca-server.db"
rootCertEnvVar = "FABRIC_CA_CLIENT_TLS_CERTFILES"
clientKeyEnvVar = "FABRIC_CA_CLIENT_TLS_CLIENT_KEYFILE"
clientCertEnvVar = "FABRIC_CA_CLIENT_TLS_CLIENT_CERTFILE"
)

var (
defYaml string
fabricCADB = path.Join(tdDir, db)
rrFile = path.Join(tdDir, "registerrequest.json")
)

// TestCreateDefaultConfigFile test to make sure default config file gets generated correctly
Expand Down Expand Up @@ -80,6 +87,7 @@ func TestClientCommandsNoTLS(t *testing.T) {

srv := getServer()
srv.HomeDir = tdDir
srv.Config.Debug = true

err := srv.RegisterBootstrapUser("admin", "adminpw", "bank1")
if err != nil {
Expand All @@ -103,7 +111,9 @@ func TestClientCommandsNoTLS(t *testing.T) {

testEnroll(t)
testReenroll(t)
testRegister(t)
testRegisterConfigFile(t)
testRegisterEnvVar(t)
testRegisterCommandLine(t)
testRevoke(t)
testBogus(t)

Expand Down Expand Up @@ -152,11 +162,6 @@ func testEnroll(t *testing.T) {
t.Errorf("client enroll -u failed: %s", err)
}

err = RunMain([]string{cmdName, "enroll", "-c", testYaml, "-u", "http://admin2:adminpw2@localhost:7054"})
if err != nil {
t.Errorf("client enroll -c -u failed: %s", err)
}

os.Remove(defYaml)

err = RunMain([]string{cmdName, "enroll", "-u", "http://admin2:adminpw2@localhost:7055"})
Expand All @@ -165,7 +170,6 @@ func testEnroll(t *testing.T) {
}

os.Remove(defYaml)
os.Remove(testYaml)
}

// TestReenroll tests fabric-ca-client reenroll
Expand All @@ -178,39 +182,66 @@ func testReenroll(t *testing.T) {
t.Errorf("client reenroll --url -f failed: %s", err)
}

err = RunMain([]string{cmdName, "reenroll", "-c", testYaml})
os.Remove(defYaml)
}

// testRegisterConfigFile tests fabric-ca-client register using the config file
func testRegisterConfigFile(t *testing.T) {
t.Log("Testing Register CMD")
defYaml = util.GetDefaultConfigFile("fabric-ca-client")

err := RunMain([]string{cmdName, "enroll", "-d", "-c", "../../testdata/fabric-ca-client-config.yaml", "-u", "http://admin2:adminpw2@localhost:7054"})
if err != nil {
t.Errorf("client enroll -u failed: %s", err)
}

err = RunMain([]string{cmdName, "register", "-d", "-c", "../../testdata/fabric-ca-client-config.yaml"})
if err != nil {
t.Errorf("client reenroll -c failed: %s", err)
t.Errorf("client register failed using config file: %s", err)
}

os.Remove(defYaml)
os.Remove(testYaml)
}

// TestRegister tests fabric-ca-client register
func testRegister(t *testing.T) {
// testRegisterEnvVar tests fabric-ca-client register using environment variables
func testRegisterEnvVar(t *testing.T) {
t.Log("Testing Register CMD")
defYaml = util.GetDefaultConfigFile("fabric-ca-client")

err := RunMain([]string{cmdName, "register", "-c", testYaml})
if err == nil {
t.Error("Should have failed, no register request file provided")
os.Setenv("FABRIC_CA_CLIENT_ID_NAME", "testRegister2")
os.Setenv("FABRIC_CA_CLIENT_ID_GROUP", "bank_a")
os.Setenv("FABRIC_CA_CLIENT_ID_TYPE", "client")

err := RunMain([]string{cmdName, "register"})
if err != nil {
t.Errorf("client register failed using environment variables: %s", err)
}

err = RunMain([]string{cmdName, "register", "-f", rrFile})
os.Unsetenv("FABRIC_CA_CLIENT_ID_NAME")
os.Unsetenv("FABRIC_CA_CLIENT_TLS_ID_GROUP")
os.Unsetenv("FABRIC_CA_CLIENT_TLS_ID_TYPE")

os.Remove(defYaml)
}

// testRegisterCommandLine tests fabric-ca-client register using command line input
func testRegisterCommandLine(t *testing.T) {
t.Log("Testing Register CMD")
defYaml = util.GetDefaultConfigFile("fabric-ca-client")

err := RunMain([]string{cmdName, "register", "-d", "--id.name", "testRegister3", "--id.group", "bank_a", "--id.type", "client", "--id.attr", "hf.test=a=b"})
if err != nil {
t.Errorf("client register -f failed: %s", err)
t.Errorf("client register failed: %s", err)
}

os.Remove(defYaml) // Delete default config file

err = RunMain([]string{cmdName, "register", "--url", "http://localhost:7055", "-f", rrFile})
err = RunMain([]string{cmdName, "register", "-u", "http://localhost:7055"})
if err == nil {
t.Error("Should have failed, client config file should have incorrect port (7055) for server")
}

os.Remove(defYaml)
os.Remove(testYaml)
}

// TestRevoke tests fabric-ca-client revoke
Expand Down Expand Up @@ -239,7 +270,6 @@ func testRevoke(t *testing.T) {
}

os.RemoveAll(filepath.Dir(defYaml))
os.Remove(testYaml)
}

// TestBogus tests a negative test case
Expand All @@ -263,8 +293,8 @@ func TestClientCommandsUsingConfigFile(t *testing.T) {

srv.HomeDir = tdDir
srv.Config.TLS.Enabled = true
srv.Config.TLS.CertFile = "tls_server-cert.pem"
srv.Config.TLS.KeyFile = "tls_server-key.pem"
srv.Config.TLS.CertFile = tlsCertFile
srv.Config.TLS.KeyFile = tlsKeyFile

err = srv.Start()
if err != nil {
Expand Down Expand Up @@ -300,19 +330,19 @@ func TestClientCommandsTLSEnvVar(t *testing.T) {

srv.HomeDir = tdDir
srv.Config.TLS.Enabled = true
srv.Config.TLS.CertFile = "tls_server-cert.pem"
srv.Config.TLS.KeyFile = "tls_server-key.pem"
srv.Config.TLS.CertFile = tlsCertFile
srv.Config.TLS.KeyFile = tlsKeyFile

err = srv.Start()
if err != nil {
t.Errorf("Server start failed: %s", err)
}

os.Setenv("FABRIC_CA_CLIENT_TLS_CERTFILES", "root.pem")
os.Setenv("FABRIC_CA_CLIENT_TLS_CLIENT_KEYFILE", "tls_client-key.pem")
os.Setenv("FABRIC_CA_CLIENT_TLS_CLIENT_CERTFILE", "tls_client-cert.pem")
os.Setenv(rootCertEnvVar, rootCert)
os.Setenv(clientKeyEnvVar, tlsClientKeyFile)
os.Setenv(clientCertEnvVar, tlsClientCertFile)

err = RunMain([]string{cmdName, "enroll", "-c", "../../testdata/test.yaml", "-u", "https://admin:adminpw@localhost:7054", "-d"})
err = RunMain([]string{cmdName, "enroll", "-c", testYaml, "-u", "https://admin:adminpw@localhost:7054", "-d"})
if err != nil {
t.Errorf("client enroll -c -u failed: %s", err)
}
Expand All @@ -322,9 +352,9 @@ func TestClientCommandsTLSEnvVar(t *testing.T) {
t.Errorf("Server stop failed: %s", err)
}

os.Unsetenv("FABRIC_CA_CLIENT_TLS_CERTFILES")
os.Unsetenv("FABRIC_CA_CLIENT_TLS_CLIENT_KEYFILE")
os.Unsetenv("FABRIC_CA_CLIENT_TLS_CLIENT_CERTFILE")
os.Unsetenv(rootCertEnvVar)
os.Unsetenv(clientKeyEnvVar)
os.Unsetenv(clientCertEnvVar)

}

Expand Down Expand Up @@ -366,10 +396,8 @@ func TestClientCommandsTLS(t *testing.T) {
}

func TestCleanUp(t *testing.T) {
os.Remove("cert.pem")
os.Remove("key.pem")
os.Remove("../../testdata/cert.pem")
os.Remove("../../testdata/key.pem")
os.Remove("../../testdata/test.yaml")
os.Remove(testYaml)
os.Remove(fabricCADB)
}
29 changes: 2 additions & 27 deletions cmd/fabric-ca-client/register.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,17 +17,12 @@ limitations under the License.
package main

import (
"encoding/json"
"errors"
"fmt"
"path/filepath"

"github.com/cloudflare/cfssl/log"
"github.com/hyperledger/fabric-ca/api"
"github.com/hyperledger/fabric-ca/lib"
"github.com/hyperledger/fabric-ca/util"
"github.com/spf13/cobra"
"github.com/spf13/viper"
)

// initCmd represents the init command
Expand All @@ -52,32 +47,12 @@ var registerCmd = &cobra.Command{

func init() {
rootCmd.AddCommand(registerCmd)
registerFlags := registerCmd.Flags()
util.FlagString(registerFlags, "regfile", "f", "", "File containing registration info")
}

// The client register main logic
func runRegister() error {
log.Debug("Entered Register")

regFile := viper.GetString("regfile")
if regFile == "" {
return errors.New("A registeration request file is required to register a user")
}

log.Debugf("Registeration Request File: %s", regFile)

buf, err := util.ReadFile(regFile)
if err != nil {
return err
}

regReq := new(api.RegistrationRequest)
err = json.Unmarshal(buf, regReq)
if err != nil {
return fmt.Errorf("Failure json unmarshaling file '%s': %s", regFile, err)
}

client := lib.Client{
HomeDir: filepath.Dir(cfgFileName),
Config: clientCfg,
Expand All @@ -88,12 +63,12 @@ func runRegister() error {
return err
}

resp, err := id.Register(regReq)
resp, err := id.Register(&clientCfg.ID)
if err != nil {
return err
}

fmt.Printf("One time password: %s\n", resp.Secret)
fmt.Printf("Password: %s\n", resp.Secret)

return nil
}
1 change: 1 addition & 0 deletions lib/clientconfig.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ type ClientConfig struct {
TLS tls.ClientTLSConfig
Enrollment api.EnrollmentRequest
CSR csr.CertificateRequest
ID api.RegistrationRequest
}

// Enroll a client given the server's URL and the client's home directory.
Expand Down
2 changes: 2 additions & 0 deletions lib/server_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,8 @@ func TestRunningTLSServer(t *testing.T) {
t.Errorf("Failed to enroll over TLS: %s", err)
}

time.Sleep(1 * time.Second)

err = srv.Stop()
if err != nil {
t.Errorf("Server stop failed: %s", err)
Expand Down
2 changes: 1 addition & 1 deletion lib/serverregister.go
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ func (h *registerHandler) Handle(w http.ResponseWriter, r *http.Request) error {

// RegisterUser will register a user
func (h *registerHandler) RegisterUser(id string, userType string, group string, attributes []api.Attribute, registrar string, opt ...string) (string, error) {
log.Debugf("Received request to register user with id: %s, group: %s, attributes: %s, registrar: %s\n",
log.Debugf("Received request to register user with id: %s, group: %s, attributes: %+v, registrar: %s\n",
id, group, attributes, registrar)

var tok string
Expand Down
Loading

0 comments on commit 4d9e2e3

Please sign in to comment.