diff --git a/api/client.go b/api/client.go index 4b37bd95c..4d5077714 100644 --- a/api/client.go +++ b/api/client.go @@ -36,7 +36,7 @@ type RegistrationRequest struct { Secret string `json:"secret,omitempty" mask:"password" 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" def:"-1" help:"The maximum number of times the secret can be reused to enroll."` + MaxEnrollments int `json:"max_enrollments,omitempty" help:"The maximum number of times the secret can be reused to enroll (default CA's Max Enrollment)"` // is returned in the response. // The identity's affiliation. // For example, an affiliation of "org1.department1" associates the identity with "department1" in "org1". @@ -200,7 +200,7 @@ type AddIdentityRequest struct { Type string `json:"type" def:"user" help:"Type of identity being registered (e.g. 'peer, app, user')"` Affiliation string `json:"affiliation" help:"The identity's affiliation"` Attributes []Attribute `json:"attrs" mapstructure:"attrs" ` - MaxEnrollments int `json:"max_enrollments" mapstructure:"max_enrollments" def:"-1" help:"The maximum number of times the secret can be reused to enroll."` + MaxEnrollments int `json:"max_enrollments" mapstructure:"max_enrollments" help:"The maximum number of times the secret can be reused to enroll (default CA's Max Enrollment)"` // Secret is an optional password. If not specified, // a random secret is generated. In both cases, the secret // is returned in the RegistrationResponse. @@ -215,7 +215,7 @@ type ModifyIdentityRequest struct { Type string `json:"type" def:"user" help:"Type of identity being registered (e.g. 'peer, app, user')"` Affiliation string `json:"affiliation" help:"The identity's affiliation"` Attributes []Attribute `mapstructure:"attrs" json:"attrs"` - MaxEnrollments int `mapstructure:"max_enrollments" json:"max_enrollments" def:"-1" help:"The maximum number of times the secret can be reused to enroll."` + MaxEnrollments int `mapstructure:"max_enrollments" json:"max_enrollments" def:"-1" help:"The maximum number of times the secret can be reused to enroll"` Secret string `json:"secret,omitempty" mask:"password" help:"The enrollment secret for the identity"` CAName string `json:"caname,omitempty" skip:"true"` } diff --git a/cmd/fabric-ca-client/config.go b/cmd/fabric-ca-client/config.go index a406e1360..6c92a7142 100644 --- a/cmd/fabric-ca-client/config.go +++ b/cmd/fabric-ca-client/config.go @@ -157,14 +157,15 @@ csr: # type - Type of identity being registered (e.g. 'peer, app, user') # affiliation - The identity's affiliation # maxenrollments - The maximum number of times the secret can be reused to enroll. -# Specially, -1 means unlimited; 0 means disabled +# Specially, -1 means unlimited; 0 means to use CA's max enrollment +# value. # attributes - List of name/value pairs of attribute for identity ############################################################################# id: name: type: affiliation: - maxenrollments: -1 + maxenrollments: 0 attributes: # - name: # value: diff --git a/cmd/fabric-ca-client/main_test.go b/cmd/fabric-ca-client/main_test.go index 4480984af..d82559108 100644 --- a/cmd/fabric-ca-client/main_test.go +++ b/cmd/fabric-ca-client/main_test.go @@ -698,6 +698,12 @@ func TestIdentityCmd(t *testing.T) { cmdName, "identity", "add", "testuser2", "--secret", "user2pw", "--type", "user", "--affiliation", ".", "--maxenrollments", "1", "--attrs", "hf.Revoker=true"}) assert.NoError(t, err, "Failed to add user 'testuser2'") + server.CA.Config.Registry.MaxEnrollments = 50 + // Test default max enrollment values for adding identity default to using CA's max enrollment value + err = RunMain([]string{ + cmdName, "identity", "add", "testuser3"}) + assert.NoError(t, err, "Failed to add user 'testuser3'") + // Check that the secret got correctly configured err = RunMain([]string{ cmdName, "enroll", "-u", "http://testuser2:user2pw@localhost:7090", "-d"}) @@ -723,7 +729,7 @@ func TestIdentityCmd(t *testing.T) { registry := server.CA.DBAccessor() user, err := registry.GetUser("testuser1", nil) - assert.NoError(t, err, "Failed to get user 'testuser1'") + util.FatalError(t, err, "Failed to get user 'testuser1'") _, err = user.GetAttribute("hf.IntermediateCA") assert.NoError(t, err, "Failed to get attribute") @@ -737,7 +743,7 @@ func TestIdentityCmd(t *testing.T) { assert.NoError(t, err, "Failed to modify user 'testuser1'") user, err = registry.GetUser("testuser1", nil) - assert.NoError(t, err, "Failed to get user 'testuser1'") + util.FatalError(t, err, "Failed to get user 'testuser1'") if user.GetType() != "peer" { t.Error("Failed to correctly modify user 'testuser1'") @@ -763,6 +769,10 @@ func TestIdentityCmd(t *testing.T) { cmdName, "identity", "remove", "testuser1"}) assert.Error(t, err, "Should have failed, identity removal not allowed on server") + user, err = registry.GetUser("testuser3", nil) + util.FatalError(t, err, "Failed to get user 'testuser1'") + assert.Equal(t, 50, user.GetMaxEnrollments()) + server.CA.Config.Cfg.Identities.AllowRemove = true err = RunMain([]string{ @@ -1504,6 +1514,18 @@ func testRegisterCommandLine(t *testing.T, srv *lib.Server) { assert.NoError(t, err) assert.Equal(t, "client", user.GetType(), "Identity type for '%s' should have been 'user'", userName) + // Register an identity with no max enrollment specified should pick up CA's make enrollment + srv.CA.Config.Registry.MaxEnrollments = 200 + + userName = "Test Register6" + err = RunMain([]string{cmdName, "register", "-d", "--id.name", userName, + "--id.affiliation", "hyperledger.org1"}) + assert.NoError(t, err, "Failed to register identity "+userName) + user, err = db.GetUser(userName, nil) + assert.NoError(t, err) + assert.Equal(t, "client", user.GetType(), "Identity type for '%s' should have been 'user'", userName) + assert.Equal(t, 200, user.GetMaxEnrollments()) + os.Remove(defYaml) // Delete default config file err = RunMain([]string{cmdName, "register", "-u", "http://localhost:7091"}) @@ -2069,7 +2091,7 @@ func TestCleanUp(t *testing.T) { func cleanMultiCADir() { caFolder := "../../testdata/ca/rootca" nestedFolders := []string{"ca1", "ca2"} - removeFiles := []string{"msp", "ec.pem", "ec-key.pem", + removeFiles := []string{"msp", "ca-cert.pem", "fabric-ca-server.db", "fabric-ca2-server.db", "ca-chain.pem"} for _, nestedFolder := range nestedFolders { diff --git a/docs/source/clientcli.rst b/docs/source/clientcli.rst index 3a1601708..213049bf6 100644 --- a/docs/source/clientcli.rst +++ b/docs/source/clientcli.rst @@ -33,7 +33,7 @@ Fabric-CA Client's CLI -H, --home string Client's home directory (default "$HOME/.fabric-ca-client") --id.affiliation string The identity's affiliation --id.attrs stringSlice A list of comma-separated attributes of the form = (e.g. foo=foo1,bar=bar1) - --id.maxenrollments int The maximum number of times the secret can be reused to enroll. (default -1) + --id.maxenrollments int The maximum number of times the secret can be reused to enroll (default CA's Max Enrollment) --id.name string Unique name of the identity --id.secret string The enrollment secret for the identity being registered --id.type string Type of identity being registered (e.g. 'peer, app, user') (default "client") diff --git a/docs/source/clientconfig.rst b/docs/source/clientconfig.rst index 54eb672ae..ccc66ae9e 100644 --- a/docs/source/clientconfig.rst +++ b/docs/source/clientconfig.rst @@ -117,14 +117,15 @@ Fabric-CA Client's Configuration File # type - Type of identity being registered (e.g. 'peer, app, user') # affiliation - The identity's affiliation # maxenrollments - The maximum number of times the secret can be reused to enroll. - # Specially, -1 means unlimited; 0 means disabled + # Specially, -1 means unlimited; 0 means to use CA's max enrollment + # value. # attributes - List of name/value pairs of attribute for identity ############################################################################# id: name: type: affiliation: - maxenrollments: -1 + maxenrollments: 0 attributes: # - name: # value: