Skip to content

Commit

Permalink
[FAB-10097] Support for ecert flag in config.yaml
Browse files Browse the repository at this point in the history
The same method have been implemented for parsing user identity attribute values from
fabric-ca-server-config.yaml what fabric-ca-client already implements.

Change-Id: I9acb14e0150bcf41614cfaf7f68e7f6ed825bf57
Signed-off-by: Frank Felhoffer <ffelhoffer@gmail.com>
Signed-off-by: Christopher Ferris <chrisfer@us.ibm.com>
  • Loading branch information
silveraid authored and christo4ferris committed Jun 14, 2018
1 parent b28fdfd commit 2697db3
Show file tree
Hide file tree
Showing 6 changed files with 224 additions and 67 deletions.
37 changes: 15 additions & 22 deletions cmd/fabric-ca-client/command/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import (
"github.com/cloudflare/cfssl/log"
"github.com/hyperledger/fabric-ca/api"
"github.com/hyperledger/fabric-ca/lib"
"github.com/hyperledger/fabric-ca/lib/attr"
"github.com/hyperledger/fabric-ca/util"
)

Expand Down Expand Up @@ -326,31 +327,23 @@ func (c *ClientCmd) createDefaultConfigFile() error {
// processAttributes parses attributes from command line or env variable
func processAttributes(cfgAttrs []string, cfg *lib.ClientConfig) error {
if cfgAttrs != nil {
cfg.ID.Attributes = make([]api.Attribute, len(cfgAttrs))
for idx, attr := range cfgAttrs {
sattr := strings.Split(attr, ":")
if len(sattr) > 2 {
return fmt.Errorf("Multiple ':' characters not allowed in attribute specification; error at '%s'", attr)
attrMap := make(map[string]string)
for _, attr := range cfgAttrs {
// skipping empty attributes
if len(attr) == 0 {
continue
}
attrFlag := ""
if len(sattr) > 1 {
attrFlag = sattr[1]
}
sattr = strings.SplitN(sattr[0], "=", 2)
sattr := strings.SplitN(attr, "=", 2)
if len(sattr) != 2 {
return errors.Errorf("Attribute '%s' is missing '=' ; it must be of the form <name>=<value>", attr)
}
ecert := false
switch strings.ToLower(attrFlag) {
case "":
case "ecert":
ecert = true
default:
return fmt.Errorf("Invalid attribute flag: '%s'", attrFlag)
return errors.Errorf("Attribute '%s' is missing '=' ; it "+
"must be of the form <name>=<value>", attr)
}
cfg.ID.Attributes[idx].Name = sattr[0]
cfg.ID.Attributes[idx].Value = sattr[1]
cfg.ID.Attributes[idx].ECert = ecert
attrMap[sattr[0]] = sattr[1]
}
var err error
cfg.ID.Attributes, err = attr.ConvertAttrs(attrMap)
if err != nil {
return err
}
}
return nil
Expand Down
91 changes: 91 additions & 0 deletions cmd/fabric-ca-client/command/config_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
/*
Copyright IBM Corp. All Rights Reserved.
SPDX-License-Identifier: Apache-2.0
*/

package command

import (
"testing"

"github.com/hyperledger/fabric-ca/lib"
)

func TestProcessAttributes(t *testing.T) {
// test cases
positiveAttrs := []string{
"AttrList=peer,orderer,client,user",
"AttrListWithECertAttr=peer,orderer,client,user:ecert",
"AttrTrue=true",
"AttrTrueWithECertAttr=true:ecert",
"AttrFalse=false",
"AttrStar=*",
"AttrStarWithECertAttr=*:ecert",
}
negativeAttrs1 := []string{
"AttrTrueWithInvalidAttr=true:invalid",
}
negativeAttrs2 := []string{
"AttrTrueWithDuplicateAttrs=true:ecert:ecert",
}

clientCfg := lib.ClientConfig{}

err := processAttributes(positiveAttrs, &clientCfg)
if err != nil {
t.Error(err)
}

for _, attr := range clientCfg.ID.Attributes {
switch attr.Name {
case "AttrList":
if attr.Value != "peer,orderer,client,user" || attr.ECert != false {
t.Fatalf("Attr conversion of '%s' failed (value='%s', ecert='%v')",
attr.Name, attr.Value, attr.ECert)
}
case "AttrListWithECertAttr":
if attr.Value != "peer,orderer,client,user" || attr.ECert != true {
t.Fatalf("Attr conversion of '%s' failed (value='%s', ecert='%v')",
attr.Name, attr.Value, attr.ECert)
}
case "AttrTrue":
if attr.Value != "true" || attr.ECert != false {
t.Fatalf("Attr conversion of '%s' failed (value='%s', ecert='%v')",
attr.Name, attr.Value, attr.ECert)
}
case "AttrTrueWithECertAttr":
if attr.Value != "true" || attr.ECert != true {
t.Fatalf("Attr conversion of '%s' failed (value='%s', ecert='%v')",
attr.Name, attr.Value, attr.ECert)
}
case "AttrFalse":
if attr.Value != "false" || attr.ECert != false {
t.Fatalf("Attr conversion of '%s' failed (value='%s', ecert='%v')",
attr.Name, attr.Value, attr.ECert)
}
case "AttrStar":
if attr.Value != "*" || attr.ECert != false {
t.Fatalf("Attr conversion of '%s' failed (value='%s', ecert='%v')",
attr.Name, attr.Value, attr.ECert)
}
case "AttrStarWithECertAttr":
if attr.Value != "*" || attr.ECert != true {
t.Fatalf("Attr conversion of '%s' failed (value='%s', ecert='%v')",
attr.Name, attr.Value, attr.ECert)
}
default:
t.Fatal("Unknown test case")
}
}

err = processAttributes(negativeAttrs1, &clientCfg)
if err == nil {
t.Fatal("Negative test case 1 should have failed")
}

err = processAttributes(negativeAttrs2, &clientCfg)
if err == nil {
t.Fatal("Negative test case 2 should have failed")
}
}
42 changes: 31 additions & 11 deletions lib/attr/attribute.go
Original file line number Diff line number Diff line change
@@ -1,17 +1,7 @@
/*
Copyright IBM Corp. 2017 All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
SPDX-License-Identifier: Apache-2.0
*/

package attr
Expand Down Expand Up @@ -373,3 +363,33 @@ func GetAttrValue(attrs []api.Attribute, name string) string {
}
return ""
}

// ConvertAttrs converts attribute string into an Attribute object array
func ConvertAttrs(inAttrs map[string]string) ([]api.Attribute, error) {
var outAttrs []api.Attribute
for name, value := range inAttrs {
sattr := strings.Split(value, ":")
if len(sattr) > 2 {
return []api.Attribute{}, errors.Errorf("Multiple ':' characters not allowed "+
"in attribute specification '%s'; The attributes have been discarded!", value)
}
attrFlag := ""
if len(sattr) > 1 {
attrFlag = sattr[1]
}
ecert := false
switch strings.ToLower(attrFlag) {
case "":
case "ecert":
ecert = true
default:
return []api.Attribute{}, errors.Errorf("Invalid attribute flag: '%s'", attrFlag)
}
outAttrs = append(outAttrs, api.Attribute{
Name: name,
Value: sattr[0],
ECert: ecert,
})
}
return outAttrs, nil
}
88 changes: 77 additions & 11 deletions lib/attr/attribute_test.go
Original file line number Diff line number Diff line change
@@ -1,17 +1,7 @@
/*
Copyright IBM Corp. 2017 All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
SPDX-License-Identifier: Apache-2.0
*/

package attr
Expand Down Expand Up @@ -526,3 +516,79 @@ func positiveTests(t *testing.T) {
err = CanRegisterRequestedAttributes(requestedAttrs, user, registrar)
assert.NoError(t, err, "Should not fail, user being registered with 'hf.Revoker', must possess attribute to have as value for 'hf.Registrar.Attribute'")
}

func TestConvertAttrs(t *testing.T) {
positiveAttrs := map[string]string{
"AttrList": "peer,orderer,client,user",
"AttrListWithECertAttr": "peer,orderer,client,user:ecert",
"AttrTrue": "true",
"AttrTrueWithECertAttr": "true:ecert",
"AttrFalse": "false",
"AttrStar": "*",
"AttrStarWithECertAttr": "*:ecert",
}
negativeAttrs1 := map[string]string{
"AttrTrueWithInvalidAttr": "true:invalid",
}
negativeAttrs2 := map[string]string{
"AttrTrueWithDuplicateAttrs": "true:ecert:ecert",
}

attrs, err := ConvertAttrs(positiveAttrs)
if err != nil {
t.Fatal(err)
}

for _, attr := range attrs {
switch attr.Name {
case "AttrList":
if attr.Value != "peer,orderer,client,user" || attr.ECert != false {
t.Fatalf("Attr conversion of '%s' failed (value='%s', ecert='%v')",
attr.Name, attr.Value, attr.ECert)
}
case "AttrListWithECertAttr":
if attr.Value != "peer,orderer,client,user" || attr.ECert != true {
t.Fatalf("Attr conversion of '%s' failed (value='%s', ecert='%v')",
attr.Name, attr.Value, attr.ECert)
}
case "AttrTrue":
if attr.Value != "true" || attr.ECert != false {
t.Fatalf("Attr conversion of '%s' failed (value='%s', ecert='%v')",
attr.Name, attr.Value, attr.ECert)
}
case "AttrTrueWithECertAttr":
if attr.Value != "true" || attr.ECert != true {
t.Fatalf("Attr conversion of '%s' failed (value='%s', ecert='%v')",
attr.Name, attr.Value, attr.ECert)
}
case "AttrFalse":
if attr.Value != "false" || attr.ECert != false {
t.Fatalf("Attr conversion of '%s' failed (value='%s', ecert='%v')",
attr.Name, attr.Value, attr.ECert)
}
case "AttrStar":
if attr.Value != "*" || attr.ECert != false {
t.Fatalf("Attr conversion of '%s' failed (value='%s', ecert='%v')",
attr.Name, attr.Value, attr.ECert)
}
case "AttrStarWithECertAttr":
if attr.Value != "*" || attr.ECert != true {
t.Fatalf("Attr conversion of '%s' failed (value='%s', ecert='%v')",
attr.Name, attr.Value, attr.ECert)
}
default:
t.Fatal("Unknown test case")

}
}

_, err = ConvertAttrs(negativeAttrs1)
if err == nil {
t.Fatal("Negative test case 1 should have failed")
}

_, err = ConvertAttrs(negativeAttrs2)
if err == nil {
t.Fatal("Negative test case 2 should have failed")
}
}
20 changes: 8 additions & 12 deletions lib/ca.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ import (
"github.com/cloudflare/cfssl/signer"
cflocalsigner "github.com/cloudflare/cfssl/signer/local"
"github.com/hyperledger/fabric-ca/api"
"github.com/hyperledger/fabric-ca/lib/attr"
"github.com/hyperledger/fabric-ca/lib/common"
"github.com/hyperledger/fabric-ca/lib/dbutil"
"github.com/hyperledger/fabric-ca/lib/ldap"
Expand Down Expand Up @@ -827,12 +828,18 @@ func (ca *CA) addIdentity(id *CAConfigIdentity, errIfFound bool) error {
return newFatalError(ErrConfig, "Configuration Error: %s", err)
}

attrs, err := attr.ConvertAttrs(id.Attrs)

if err != nil {
return err
}

rec := spi.UserInfo{
Name: id.Name,
Pass: id.Pass,
Type: id.Type,
Affiliation: id.Affiliation,
Attributes: ca.convertAttrs(id.Attrs),
Attributes: attrs,
MaxEnrollments: id.MaxEnrollments,
Level: ca.levels.Identity,
}
Expand Down Expand Up @@ -863,17 +870,6 @@ func (ca *CA) GetDB() *dbutil.DB {
return ca.db
}

func (ca *CA) convertAttrs(inAttrs map[string]string) []api.Attribute {
var outAttrs []api.Attribute
for name, value := range inAttrs {
outAttrs = append(outAttrs, api.Attribute{
Name: name,
Value: value,
})
}
return outAttrs
}

// Make all file names in the CA config absolute
func (ca *CA) makeFileNamesAbsolute() error {
log.Debug("Making CA filenames absolute")
Expand Down
13 changes: 2 additions & 11 deletions lib/ca_test.go
Original file line number Diff line number Diff line change
@@ -1,18 +1,9 @@
/*
Copyright IBM Corp. 2016 All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
SPDX-License-Identifier: Apache-2.0
*/

package lib

import (
Expand Down

0 comments on commit 2697db3

Please sign in to comment.