git.frostfs.info/TrueCloudLab/frostfs-sdk-go@v0.0.0-20241022124111-5361f0ecebd3/eacl/target.go (about) 1 package eacl 2 3 import ( 4 "bytes" 5 "crypto/ecdsa" 6 7 v2acl "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/acl" 8 "github.com/nspcc-dev/neo-go/pkg/crypto/keys" 9 ) 10 11 // Target is a group of request senders to match ContainerEACL. Defined by role enum 12 // and set of public keys. 13 // 14 // Target is compatible with v2 acl.EACLRecord.Target message. 15 type Target struct { 16 role Role 17 keys [][]byte 18 } 19 20 func ecdsaKeysToPtrs(keys []ecdsa.PublicKey) []*ecdsa.PublicKey { 21 keysPtr := make([]*ecdsa.PublicKey, len(keys)) 22 23 for i := range keys { 24 keysPtr[i] = &keys[i] 25 } 26 27 return keysPtr 28 } 29 30 // BinaryKeys returns list of public keys to identify 31 // target subject in a binary format. 32 func (t *Target) BinaryKeys() [][]byte { 33 return t.keys 34 } 35 36 // SetBinaryKeys sets list of binary public keys to identify 37 // target subject. 38 func (t *Target) SetBinaryKeys(keys [][]byte) { 39 t.keys = keys 40 } 41 42 // SetTargetECDSAKeys converts ECDSA public keys to a binary 43 // format and stores them in Target. 44 func SetTargetECDSAKeys(t *Target, pubs ...*ecdsa.PublicKey) { 45 binKeys := t.BinaryKeys() 46 ln := len(pubs) 47 48 if cap(binKeys) >= ln { 49 binKeys = binKeys[:0] 50 } else { 51 binKeys = make([][]byte, 0, ln) 52 } 53 54 for i := range ln { 55 binKeys = append(binKeys, (*keys.PublicKey)(pubs[i]).Bytes()) 56 } 57 58 t.SetBinaryKeys(binKeys) 59 } 60 61 // TargetECDSAKeys interprets binary public keys of Target 62 // as ECDSA public keys. If any key has a different format, 63 // the corresponding element will be nil. 64 func TargetECDSAKeys(t *Target) []*ecdsa.PublicKey { 65 binKeys := t.BinaryKeys() 66 ln := len(binKeys) 67 68 pubs := make([]*ecdsa.PublicKey, ln) 69 70 for i := range ln { 71 p := new(keys.PublicKey) 72 if p.DecodeBytes(binKeys[i]) == nil { 73 pubs[i] = (*ecdsa.PublicKey)(p) 74 } 75 } 76 77 return pubs 78 } 79 80 // SetRole sets target subject's role class. 81 func (t *Target) SetRole(r Role) { 82 t.role = r 83 } 84 85 // Role returns target subject's role class. 86 func (t Target) Role() Role { 87 return t.role 88 } 89 90 // ToV2 converts Target to v2 acl.EACLRecord.Target message. 91 // 92 // Nil Target converts to nil. 93 func (t *Target) ToV2() *v2acl.Target { 94 if t == nil { 95 return nil 96 } 97 98 target := new(v2acl.Target) 99 target.SetRole(t.role.ToV2()) 100 target.SetKeys(t.keys) 101 102 return target 103 } 104 105 // NewTarget creates, initializes and returns blank Target instance. 106 // 107 // Defaults: 108 // - role: RoleUnknown; 109 // - keys: nil. 110 func NewTarget() *Target { 111 return NewTargetFromV2(new(v2acl.Target)) 112 } 113 114 // NewTargetFromV2 converts v2 acl.EACLRecord.Target message to Target. 115 func NewTargetFromV2(target *v2acl.Target) *Target { 116 if target == nil { 117 return new(Target) 118 } 119 120 return &Target{ 121 role: RoleFromV2(target.GetRole()), 122 keys: target.GetKeys(), 123 } 124 } 125 126 // Marshal marshals Target into a protobuf binary form. 127 func (t *Target) Marshal() ([]byte, error) { 128 return t.ToV2().StableMarshal(nil), nil 129 } 130 131 // Unmarshal unmarshals protobuf binary representation of Target. 132 func (t *Target) Unmarshal(data []byte) error { 133 fV2 := new(v2acl.Target) 134 if err := fV2.Unmarshal(data); err != nil { 135 return err 136 } 137 138 *t = *NewTargetFromV2(fV2) 139 140 return nil 141 } 142 143 // MarshalJSON encodes Target to protobuf JSON format. 144 func (t *Target) MarshalJSON() ([]byte, error) { 145 return t.ToV2().MarshalJSON() 146 } 147 148 // UnmarshalJSON decodes Target from protobuf JSON format. 149 func (t *Target) UnmarshalJSON(data []byte) error { 150 tV2 := new(v2acl.Target) 151 if err := tV2.UnmarshalJSON(data); err != nil { 152 return err 153 } 154 155 *t = *NewTargetFromV2(tV2) 156 157 return nil 158 } 159 160 // equalTargets compares Target with each other. 161 func equalTargets(t1, t2 Target) bool { 162 if t1.Role() != t2.Role() { 163 return false 164 } 165 166 keys1, keys2 := t1.BinaryKeys(), t2.BinaryKeys() 167 168 if len(keys1) != len(keys2) { 169 return false 170 } 171 172 for i := range len(keys1) { 173 if !bytes.Equal(keys1[i], keys2[i]) { 174 return false 175 } 176 } 177 178 return true 179 }