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  }