github.com/canhui/fabric_ca2_2@v2.0.0-alpha+incompatible/lib/attr/attribute.go (about)

     1  /*
     2  Copyright IBM Corp. 2017 All Rights Reserved.
     3  
     4  SPDX-License-Identifier: Apache-2.0
     5  */
     6  
     7  package attr
     8  
     9  import (
    10  	"fmt"
    11  	"strconv"
    12  	"strings"
    13  
    14  	"github.com/cloudflare/cfssl/log"
    15  	"github.com/hyperledger/fabric-ca/api"
    16  	"github.com/hyperledger/fabric-ca/util"
    17  	"github.com/pkg/errors"
    18  )
    19  
    20  // AttributeControl interface gets the attributes associated with an identity
    21  type AttributeControl interface {
    22  	// GetAttribute returns the value for an attribute name
    23  	GetAttribute(name string) (*api.Attribute, error)
    24  }
    25  
    26  type attributeType int
    27  
    28  const (
    29  	// BOOLEAN indicates that the attribute is of type boolean
    30  	BOOLEAN attributeType = 1 + iota
    31  	// LIST indicates that the attribute is of type list
    32  	LIST
    33  	// FIXED indicates that the attribute value is fixed and can't be modified
    34  	FIXED
    35  	// CUSTOM indicates that the attribute is a custom attribute
    36  	CUSTOM
    37  )
    38  
    39  // Attribute names
    40  const (
    41  	Roles          = "hf.Registrar.Roles"
    42  	DelegateRoles  = "hf.Registrar.DelegateRoles"
    43  	Revoker        = "hf.Revoker"
    44  	IntermediateCA = "hf.IntermediateCA"
    45  	GenCRL         = "hf.GenCRL"
    46  	RegistrarAttr  = "hf.Registrar.Attributes"
    47  	AffiliationMgr = "hf.AffiliationMgr"
    48  	EnrollmentID   = "hf.EnrollmentID"
    49  	Type           = "hf.Type"
    50  	Affiliation    = "hf.Affiliation"
    51  )
    52  
    53  // CanRegisterRequestedAttributes validates that the registrar can register the requested attributes
    54  func CanRegisterRequestedAttributes(reqAttrs []api.Attribute, user, registrar AttributeControl) error {
    55  	if len(reqAttrs) == 0 {
    56  		return nil
    57  	}
    58  
    59  	log.Debugf("Checking to see if registrar can register the requested attributes: %+v", reqAttrs)
    60  
    61  	for _, reqAttr := range reqAttrs {
    62  		// Check if registrar is allowed to register requested attributes
    63  		err := CanRegisterAttribute(&reqAttr, reqAttrs, user, registrar)
    64  		if err != nil {
    65  			return err
    66  		}
    67  	}
    68  
    69  	return nil
    70  }
    71  
    72  // CanRegisterAttribute will iterate through the values of registrar's 'hf.Registrar.Attributes' attribute to check if registrar can register the requested attributes
    73  func CanRegisterAttribute(requestedAttr *api.Attribute, allRequestedAttrs []api.Attribute, user, registrar AttributeControl) error {
    74  	// Get registrar's 'hf.Registrar.Attributes' attribute to see which attributes registrar is allowed to register
    75  	registrarAttrs, err := registrar.GetAttribute(RegistrarAttr)
    76  	if err != nil {
    77  		return errors.Errorf("Failed to get attribute '%s': %s", RegistrarAttr, err)
    78  	}
    79  	if registrarAttrs.Value == "" {
    80  		return errors.Errorf("Registrar does not have any values for '%s' thus can't register any attributes", RegistrarAttr)
    81  	}
    82  	log.Debugf("Validating that registrar with the following values for hf.Registrar.Attributes '%+v' is authorized to register the requested attribute '%+v'", registrarAttrs.GetValue(), requestedAttr)
    83  	callerHfRegisterAttrSlice := util.GetSliceFromList(registrarAttrs.Value, ",") // Remove any whitespace between the values and split on comma
    84  
    85  	requestedAttrName := requestedAttr.GetName()
    86  
    87  	err = canRegisterAttr(requestedAttrName, callerHfRegisterAttrSlice)
    88  	if err != nil {
    89  		return err
    90  	}
    91  
    92  	attrControl, err := getAttributeControl(requestedAttrName)
    93  	if err != nil {
    94  		return err
    95  	}
    96  
    97  	err = attrControl.isRegistrarAuthorized(requestedAttr, allRequestedAttrs, user, registrar)
    98  	if err != nil {
    99  		return errors.Errorf("Registrar is not authorized to register attribute: %s", err)
   100  	}
   101  
   102  	return nil
   103  }
   104  
   105  // attributeMap contains the control definition for reserverd (hf.) attributes
   106  var attributeMap = initAttrs()
   107  
   108  func initAttrs() map[string]*attributeControl {
   109  	var attributeMap = make(map[string]*attributeControl)
   110  
   111  	booleanAttributes := []string{Revoker, IntermediateCA, GenCRL, AffiliationMgr}
   112  
   113  	for _, attr := range booleanAttributes {
   114  		attributeMap[attr] = &attributeControl{
   115  			name:              attr,
   116  			requiresOwnership: true,
   117  			attrType:          BOOLEAN,
   118  		}
   119  	}
   120  
   121  	listAttributes := []string{Roles, DelegateRoles, RegistrarAttr}
   122  
   123  	for _, attr := range listAttributes {
   124  		attributeMap[attr] = &attributeControl{
   125  			name:              attr,
   126  			requiresOwnership: true,
   127  			attrType:          LIST,
   128  		}
   129  	}
   130  
   131  	fixedValueAttributes := []string{EnrollmentID, Type, Affiliation}
   132  
   133  	for _, attr := range fixedValueAttributes {
   134  		attributeMap[attr] = &attributeControl{
   135  			name:              attr,
   136  			requiresOwnership: false,
   137  			attrType:          FIXED,
   138  		}
   139  	}
   140  
   141  	return attributeMap
   142  }
   143  
   144  type attributeControl struct {
   145  	name              string
   146  	requiresOwnership bool
   147  	attrType          attributeType
   148  }
   149  
   150  func (ac *attributeControl) getName() string {
   151  	return ac.name
   152  }
   153  
   154  func (ac *attributeControl) isOwnershipRequired() bool {
   155  	return ac.requiresOwnership
   156  }
   157  
   158  func (ac *attributeControl) isRegistrarAuthorized(requestedAttr *api.Attribute, allRequestedAttrs []api.Attribute, user, registrar AttributeControl) error {
   159  	log.Debug("Performing authorization check...")
   160  	requestedAttrName := requestedAttr.GetName()
   161  
   162  	var callersAttrValue string
   163  	if ac.isOwnershipRequired() {
   164  		callersAttribute, err := registrar.GetAttribute(requestedAttrName)
   165  		if err != nil {
   166  			return errors.Errorf("Attribute '%s' requires ownership but the caller does not own this attribute: %s", requestedAttrName, err)
   167  		}
   168  		callersAttrValue = callersAttribute.GetValue()
   169  
   170  		log.Debugf("Checking if caller is authorized to register attribute '%s' with the requested value of '%s'", requestedAttrName, requestedAttr.GetValue())
   171  	}
   172  
   173  	switch ac.attrType {
   174  	case BOOLEAN:
   175  		return ac.validateBooleanAttribute(requestedAttr, callersAttrValue)
   176  	case LIST:
   177  		return ac.validateListAttribute(requestedAttr, callersAttrValue, allRequestedAttrs, user)
   178  	case FIXED:
   179  		log.Debug("Requested attribute type is fixed")
   180  		return errors.Errorf("Cannot register fixed value attribute '%s'", ac.getName())
   181  	case CUSTOM:
   182  		return nil
   183  	}
   184  
   185  	return nil
   186  }
   187  
   188  func (ac *attributeControl) validateBooleanAttribute(requestedAttr *api.Attribute, callersAttrValue string) error {
   189  	log.Debug("Requested attribute type is boolean")
   190  	requestedAttrValue := requestedAttr.GetValue()
   191  
   192  	callerAttrValueBool, err := strconv.ParseBool(callersAttrValue)
   193  	if err != nil {
   194  		return errors.Wrap(err, fmt.Sprintf("Failed to get boolean value of '%s'", callersAttrValue))
   195  	}
   196  	if callerAttrValueBool {
   197  		// Deleting an attribute if empty string is requested as value for attribute, no further validation necessary
   198  		if requestedAttrValue == "" {
   199  			return nil
   200  		}
   201  		_, err := strconv.ParseBool(requestedAttrValue)
   202  		if err != nil {
   203  			return errors.Wrap(err, fmt.Sprintf("Failed to get boolean value of '%s'", requestedAttrValue))
   204  		}
   205  		return nil
   206  	}
   207  	return errors.Errorf("Caller has a value of 'false' for boolean attribute '%s', can't perform any actions on this attribute", ac.getName())
   208  }
   209  
   210  func (ac *attributeControl) validateListAttribute(requestedAttr *api.Attribute, callersAttrValue string, allRequestedAttrs []api.Attribute, user AttributeControl) error {
   211  	log.Debug("Requested attribute type is list")
   212  	requestedAttrValue := requestedAttr.GetValue()
   213  
   214  	// Deleting an attribute if empty string is requested as value for attribute, no further validation necessary
   215  	if requestedAttrValue == "" {
   216  		return nil
   217  	}
   218  
   219  	callerRegisterAttrSlice := util.GetSliceFromList(callersAttrValue, ",") // Remove any whitespace between the values and split on comma
   220  
   221  	// hf.Registrar.Attribute is a special type of list attribute. Need to check all the
   222  	// requested attribute names as values to this attribute to make sure caller is allowed to register
   223  	if ac.getName() == RegistrarAttr {
   224  		err := checkHfRegistrarAttrValues(requestedAttr, allRequestedAttrs, user, callerRegisterAttrSlice)
   225  		if err != nil {
   226  			return err
   227  		}
   228  		return nil
   229  	}
   230  	// Make sure the values requested for attribute is equal to or a subset of the registrar's attribute
   231  	err := ac.IsSubsetOf(requestedAttrValue, callersAttrValue)
   232  	if err != nil {
   233  		return err
   234  	}
   235  	// If requested attribute is 'hf.Registrar.DeletegateRoles', make sure it is equal or a subset of the user's hf.Registrar.Roles attribute
   236  	if ac.getName() == DelegateRoles {
   237  		err := checkDelegateRoleValues(allRequestedAttrs, user)
   238  		if err != nil {
   239  			return err
   240  		}
   241  	}
   242  	return nil
   243  }
   244  
   245  func (ac *attributeControl) IsSubsetOf(requestedAttrValue, callersAttrValue string) error {
   246  	if (ac.getName() == Roles || ac.getName() == DelegateRoles) && util.ListContains(callersAttrValue, "*") {
   247  		return nil
   248  	}
   249  	err := util.IsSubsetOf(requestedAttrValue, callersAttrValue)
   250  	if err != nil {
   251  		return errors.WithMessage(err, fmt.Sprintf("The requested values for attribute '%s' is a superset of the caller's attribute value", ac.getName()))
   252  	}
   253  	return nil
   254  }
   255  
   256  // Check if registrar has the proper authority to register the values for 'hf.Registrar.Attributes'.
   257  // Registering 'hf.Registrar.Attributes' with a value that has a 'hf.' prefix requires that the user
   258  // being registered to possess that hf. attribute. For example, if attribute is 'hf.Registrar.Attributes=hf.Revoker'
   259  // then user being registered must possess 'hf.Revoker' for this to be a valid request.
   260  func checkHfRegistrarAttrValues(reqAttr *api.Attribute, reqAttrs []api.Attribute, user AttributeControl, callerRegisterAttrSlice []string) error {
   261  	log.Debug("Perform ownshership check for requested 'hf.' attributes for the values of 'hf.Registrar.Attributes'")
   262  
   263  	valuesRequestedForHfRegistrarAttr := util.GetSliceFromList(reqAttr.Value, ",") // Remove any whitespace between the values and split on comma
   264  	for _, requestedAttrValue := range valuesRequestedForHfRegistrarAttr {
   265  		err := canRegisterAttr(requestedAttrValue, callerRegisterAttrSlice)
   266  		if err != nil {
   267  			return err
   268  		}
   269  		if strings.HasPrefix(requestedAttrValue, "hf.") {
   270  			log.Debugf("Checking if value '%s' for hf.Registrar.Attribute is owned by user", requestedAttrValue)
   271  			if !Exists(reqAttrs, requestedAttrValue) {
   272  				// Attribute not present in the list of attributes being requested along side 'hf.Registrar.Attributes'
   273  				// if user equals nil, this is a new user registration request
   274  				if user == nil {
   275  					return errors.Errorf("Requesting value of '%s' for 'hf.Registrar.Attributes', but the identity being registered is not being registered with this attribute", requestedAttrValue)
   276  				}
   277  				// If user not equal nil (modify user request), check to see if it possesses the attribute
   278  				_, err := user.GetAttribute(requestedAttrValue)
   279  				if err != nil {
   280  					return errors.Errorf("Requesting value of '%s' for 'hf.Registrar.Attributes', but the identity does not possess this attribute nor is it being registered with this attribute", requestedAttrValue)
   281  				}
   282  			}
   283  		}
   284  	}
   285  	return nil
   286  }
   287  
   288  func canRegisterAttr(requestedAttrName string, callerRegisterAttrSlice []string) error {
   289  	log.Debugf("Checking if registrar can register attribute: %s", requestedAttrName)
   290  
   291  	for _, regAttr := range callerRegisterAttrSlice {
   292  		if strings.HasSuffix(regAttr, "*") { // Wildcard matching
   293  			if strings.HasPrefix(requestedAttrName, strings.TrimRight(regAttr, "*")) {
   294  				return nil
   295  			}
   296  		} else {
   297  			if requestedAttrName == regAttr { // Exact name matching
   298  				return nil
   299  			}
   300  		}
   301  	}
   302  
   303  	return errors.Errorf("Attribute is not part of caller's '%s' attribute list", callerRegisterAttrSlice)
   304  }
   305  
   306  // Make sure delegateRoles is not larger than roles
   307  func checkDelegateRoleValues(reqAttrs []api.Attribute, user AttributeControl) error {
   308  	roles := GetAttrValue(reqAttrs, Roles)
   309  	if roles == "" { // If roles is not being updated in this request, query to get the current value of roles of user
   310  		if user != nil { // If the is a user modify request, check to see if attribute already exists for user
   311  			currentRoles, err := user.GetAttribute(Roles)
   312  			if err == nil {
   313  				roles = currentRoles.GetValue()
   314  			}
   315  		}
   316  	}
   317  	if util.ListContains(roles, "*") {
   318  		return nil
   319  	}
   320  	delegateRoles := GetAttrValue(reqAttrs, DelegateRoles)
   321  	err := util.IsSubsetOf(delegateRoles, roles)
   322  	if err != nil {
   323  		return errors.New("The delegateRoles field is a superset of roles")
   324  	}
   325  	return nil
   326  }
   327  
   328  func getAttributeControl(attrName string) (*attributeControl, error) {
   329  	attrControl, found := attributeMap[attrName]
   330  	if found {
   331  		return attrControl, nil
   332  	}
   333  
   334  	if strings.HasPrefix(attrName, "hf.") {
   335  		return nil, errors.Errorf("Registering attribute '%s' using a reserved prefix 'hf.', however this not a supported reserved attribute", attrName)
   336  	}
   337  
   338  	return &attributeControl{
   339  		name:              attrName,
   340  		requiresOwnership: false,
   341  		attrType:          CUSTOM,
   342  	}, nil
   343  }
   344  
   345  // Exists searches 'attrs' for the attribute with name 'name' and returns
   346  // true if found
   347  func Exists(attrs []api.Attribute, name string) bool {
   348  	for _, attr := range attrs {
   349  		if attr.Name == name {
   350  			return true
   351  		}
   352  	}
   353  	return false
   354  }
   355  
   356  // GetAttrValue searches 'attrs' for the attribute with name 'name' and returns
   357  // its value, or "" if not found.
   358  func GetAttrValue(attrs []api.Attribute, name string) string {
   359  	for _, attr := range attrs {
   360  		if attr.Name == name {
   361  			return attr.Value
   362  		}
   363  	}
   364  	return ""
   365  }
   366  
   367  // ConvertAttrs converts attribute string into an Attribute object array
   368  func ConvertAttrs(inAttrs map[string]string) ([]api.Attribute, error) {
   369  	var outAttrs []api.Attribute
   370  	for name, value := range inAttrs {
   371  		sattr := strings.Split(value, ":")
   372  		if len(sattr) > 2 {
   373  			return []api.Attribute{}, errors.Errorf("Multiple ':' characters not allowed "+
   374  				"in attribute specification '%s'; The attributes have been discarded!", value)
   375  		}
   376  		attrFlag := ""
   377  		if len(sattr) > 1 {
   378  			attrFlag = sattr[1]
   379  		}
   380  		ecert := false
   381  		switch strings.ToLower(attrFlag) {
   382  		case "":
   383  		case "ecert":
   384  			ecert = true
   385  		default:
   386  			return []api.Attribute{}, errors.Errorf("Invalid attribute flag: '%s'", attrFlag)
   387  		}
   388  		outAttrs = append(outAttrs, api.Attribute{
   389  			Name:  name,
   390  			Value: sattr[0],
   391  			ECert: ecert,
   392  		})
   393  	}
   394  	return outAttrs, nil
   395  }