github.com/hxx258456/fabric-ca-gm@v0.0.3-0.20221111064038-a268ad7e3a37/lib/attrmgr/attrmgr.go (about)

     1  /*
     2  Copyright IBM Corp. All Rights Reserved.
     3  
     4  SPDX-License-Identifier: Apache-2.0
     5  */
     6  
     7  /*
     8   * The attrmgr package contains utilities for managing attributes.
     9   * Attributes are added to an X509 certificate as an extension.
    10   */
    11  
    12  package attrmgr
    13  
    14  import (
    15  	"crypto/x509/pkix"
    16  	"encoding/asn1"
    17  	"encoding/json"
    18  	"fmt"
    19  
    20  	"github.com/hxx258456/ccgo/x509"
    21  	"github.com/pkg/errors"
    22  )
    23  
    24  var (
    25  	// AttrOID is the ASN.1 object identifier for an attribute extension in an
    26  	// X509 certificate
    27  	AttrOID = asn1.ObjectIdentifier{1, 2, 3, 4, 5, 6, 7, 8, 1}
    28  	// AttrOIDString is the string version of AttrOID
    29  	AttrOIDString = "1.2.3.4.5.6.7.8.1"
    30  )
    31  
    32  // Attribute is a name/value pair
    33  type Attribute interface {
    34  	// GetName returns the name of the attribute
    35  	GetName() string
    36  	// GetValue returns the value of the attribute
    37  	GetValue() string
    38  }
    39  
    40  // AttributeRequest is a request for an attribute
    41  type AttributeRequest interface {
    42  	// GetName returns the name of an attribute
    43  	GetName() string
    44  	// IsRequired returns true if the attribute is required
    45  	IsRequired() bool
    46  }
    47  
    48  // New constructs an attribute manager
    49  func New() *Mgr { return &Mgr{} }
    50  
    51  // Mgr is the attribute manager and is the main object for this package
    52  type Mgr struct{}
    53  
    54  // ProcessAttributeRequestsForCert add attributes to an X509 certificate, given
    55  // attribute requests and attributes.
    56  func (mgr *Mgr) ProcessAttributeRequestsForCert(requests []AttributeRequest, attributes []Attribute, cert *x509.Certificate) error {
    57  	attrs, err := mgr.ProcessAttributeRequests(requests, attributes)
    58  	if err != nil {
    59  		return err
    60  	}
    61  	return mgr.AddAttributesToCert(attrs, cert)
    62  }
    63  
    64  // ProcessAttributeRequests takes an array of attribute requests and an identity's attributes
    65  // and returns an Attributes object containing the requested attributes.
    66  // 根据请求的属性从所有属性列表中选取对应的属性
    67  func (mgr *Mgr) ProcessAttributeRequests(requests []AttributeRequest, attributes []Attribute) (*Attributes, error) {
    68  	attrsMap := map[string]string{}
    69  	attrs := &Attributes{Attrs: attrsMap}
    70  	missingRequiredAttrs := []string{}
    71  	// For each of the attribute requests
    72  	for _, req := range requests {
    73  		// Get the attribute
    74  		name := req.GetName()
    75  		attr := getAttrByName(name, attributes)
    76  		if attr == nil {
    77  			if req.IsRequired() {
    78  				// Didn't find attribute and it was required; return error below
    79  				missingRequiredAttrs = append(missingRequiredAttrs, name)
    80  			}
    81  			// Skip attribute requests which aren't required
    82  			continue
    83  		}
    84  		attrsMap[name] = attr.GetValue()
    85  	}
    86  	if len(missingRequiredAttrs) > 0 {
    87  		return nil, errors.Errorf("The following required attributes are missing: %+v",
    88  			missingRequiredAttrs)
    89  	}
    90  	return attrs, nil
    91  }
    92  
    93  // AddAttributesToCert adds public attribute info to an X509 certificate.
    94  func (mgr *Mgr) AddAttributesToCert(attrs *Attributes, cert *x509.Certificate) error {
    95  	buf, err := json.Marshal(attrs)
    96  	if err != nil {
    97  		return errors.Wrap(err, "Failed to marshal attributes")
    98  	}
    99  	ext := pkix.Extension{
   100  		Id:       AttrOID,
   101  		Critical: false,
   102  		Value:    buf,
   103  	}
   104  	cert.Extensions = append(cert.Extensions, ext)
   105  	return nil
   106  }
   107  
   108  // GetAttributesFromCert gets the attributes from a certificate.
   109  func (mgr *Mgr) GetAttributesFromCert(cert *x509.Certificate) (*Attributes, error) {
   110  	// Get certificate attributes from the certificate if it exists
   111  	buf, err := getAttributesFromCert(cert)
   112  	if err != nil {
   113  		return nil, err
   114  	}
   115  	// Unmarshal into attributes object
   116  	attrs := &Attributes{}
   117  	if buf != nil {
   118  		err := json.Unmarshal(buf, attrs)
   119  		if err != nil {
   120  			return nil, errors.Wrap(err, "Failed to unmarshal attributes from certificate")
   121  		}
   122  	}
   123  	return attrs, nil
   124  }
   125  
   126  // Attributes contains attribute names and values
   127  type Attributes struct {
   128  	Attrs map[string]string `json:"attrs"`
   129  }
   130  
   131  // Names returns the names of the attributes
   132  func (a *Attributes) Names() []string {
   133  	i := 0
   134  	names := make([]string, len(a.Attrs))
   135  	for name := range a.Attrs {
   136  		names[i] = name
   137  		i++
   138  	}
   139  	return names
   140  }
   141  
   142  // Contains returns true if the named attribute is found
   143  func (a *Attributes) Contains(name string) bool {
   144  	_, ok := a.Attrs[name]
   145  	return ok
   146  }
   147  
   148  // Value returns an attribute's value
   149  func (a *Attributes) Value(name string) (string, bool, error) {
   150  	attr, ok := a.Attrs[name]
   151  	return attr, ok, nil
   152  }
   153  
   154  // True returns nil if the value of attribute 'name' is true;
   155  // otherwise, an appropriate error is returned.
   156  func (a *Attributes) True(name string) error {
   157  	val, ok, err := a.Value(name)
   158  	if err != nil {
   159  		return err
   160  	}
   161  	if !ok {
   162  		return fmt.Errorf("Attribute '%s' was not found", name)
   163  	}
   164  	if val != "true" {
   165  		return fmt.Errorf("Attribute '%s' is not true", name)
   166  	}
   167  	return nil
   168  }
   169  
   170  // Get the attribute info from a certificate extension, or return nil if not found
   171  func getAttributesFromCert(cert *x509.Certificate) ([]byte, error) {
   172  	for _, ext := range cert.Extensions {
   173  		if isAttrOID(ext.Id) {
   174  			return ext.Value, nil
   175  		}
   176  	}
   177  	return nil, nil
   178  }
   179  
   180  // Is the object ID equal to the attribute info object ID?
   181  func isAttrOID(oid asn1.ObjectIdentifier) bool {
   182  	if len(oid) != len(AttrOID) {
   183  		return false
   184  	}
   185  	for idx, val := range oid {
   186  		if val != AttrOID[idx] {
   187  			return false
   188  		}
   189  	}
   190  	return true
   191  }
   192  
   193  // Get an attribute from 'attrs' by its name, or nil if not found
   194  func getAttrByName(name string, attrs []Attribute) Attribute {
   195  	for _, attr := range attrs {
   196  		if attr.GetName() == name {
   197  			return attr
   198  		}
   199  	}
   200  	return nil
   201  }