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 }