[#199] sdk/eacl: Correct linter's remarks

Signed-off-by: Leonard Lyubich <leonard@nspcc.ru>
This commit is contained in:
Leonard Lyubich 2020-11-16 17:24:06 +03:00 committed by Alex Vanin
parent 2b3502d6c0
commit c6884f9823
7 changed files with 137 additions and 55 deletions

View file

@ -5,60 +5,100 @@ import (
) )
// Action taken if EACL record matched request. // Action taken if EACL record matched request.
// Action is compatible with v2 acl.Action enum.
type Action uint32 type Action uint32
const ( const (
// ActionUnknown is an Action value used to mark action as undefined.
ActionUnknown Action = iota ActionUnknown Action = iota
// ActionAllow is an Action value that allows access to the operation from context.
ActionAllow ActionAllow
// ActionDeny is an Action value that denies access to the operation from context.
ActionDeny ActionDeny
) )
// Operation is a object service method to match request. // Operation is a object service method to match request.
// Operation is compatible with v2 acl.Operation enum.
type Operation uint32 type Operation uint32
const ( const (
// OperationUnknown is an Operation value used to mark operation as undefined.
OperationUnknown Operation = iota OperationUnknown Operation = iota
// OperationGet is an object get Operation.
OperationGet OperationGet
// OperationHead is an Operation of getting the object header.
OperationHead OperationHead
// OperationPut is an object put Operation.
OperationPut OperationPut
// OperationDelete is an object delete Operation.
OperationDelete OperationDelete
// OperationSearch is an object search Operation.
OperationSearch OperationSearch
// OperationRange is an object payload range retrieval Operation.
OperationRange OperationRange
// OperationRangeHash is an object payload range hashing Operation.
OperationRangeHash OperationRangeHash
) )
// Role is a group of request senders to match request. // Role is a group of request senders to match request.
// Role is compatible with v2 acl.Role enum.
type Role uint32 type Role uint32
const ( const (
// RoleUnknown is a Role value used to mark role as undefined.
RoleUnknown Role = iota RoleUnknown Role = iota
// RoleUser is a group of senders that contains only key of container owner. // RoleUser is a group of senders that contains only key of container owner.
RoleUser RoleUser
// RoleSystem is a group of senders that contains keys of container nodes and // RoleSystem is a group of senders that contains keys of container nodes and
// inner ring nodes. // inner ring nodes.
RoleSystem RoleSystem
// RoleOthers is a group of senders that contains none of above keys. // RoleOthers is a group of senders that contains none of above keys.
RoleOthers RoleOthers
) )
// Match is binary operation on filer name and value to check if request is matched. // Match is binary operation on filer name and value to check if request is matched.
// Match is compatible with v2 acl.MatchType enum.
type Match uint32 type Match uint32
const ( const (
// MatchUnknown is a Match value used to mark matcher as undefined.
MatchUnknown Match = iota MatchUnknown Match = iota
// MatchStringEqual is a Match of string equality.
MatchStringEqual MatchStringEqual
// MatchStringNotEqual is a Match of string inequality.
MatchStringNotEqual MatchStringNotEqual
) )
// FilterHeaderType indicates source of headers to make matches. // FilterHeaderType indicates source of headers to make matches.
// FilterHeaderType is compatible with v2 acl.HeaderType enum.
type FilterHeaderType uint32 type FilterHeaderType uint32
const ( const (
// HeaderTypeUnknown is a FilterHeaderType value used to mark header type as undefined.
HeaderTypeUnknown FilterHeaderType = iota HeaderTypeUnknown FilterHeaderType = iota
// HeaderFromRequest is a FilterHeaderType for request X-Header.
HeaderFromRequest HeaderFromRequest
// HeaderFromObject is a FilterHeaderType for object header.
HeaderFromObject HeaderFromObject
) )
// ToV2 converts Action to v2 Action enum value.
func (a Action) ToV2() v2acl.Action { func (a Action) ToV2() v2acl.Action {
switch a { switch a {
case ActionAllow: case ActionAllow:
@ -70,6 +110,7 @@ func (a Action) ToV2() v2acl.Action {
} }
} }
// ActionFromV2 converts v2 Action enum value to Action.
func ActionFromV2(action v2acl.Action) (a Action) { func ActionFromV2(action v2acl.Action) (a Action) {
switch action { switch action {
case v2acl.ActionAllow: case v2acl.ActionAllow:
@ -83,6 +124,7 @@ func ActionFromV2(action v2acl.Action) (a Action) {
return a return a
} }
// ToV2 converts Operation to v2 Operation enum value.
func (o Operation) ToV2() v2acl.Operation { func (o Operation) ToV2() v2acl.Operation {
switch o { switch o {
case OperationGet: case OperationGet:
@ -104,6 +146,7 @@ func (o Operation) ToV2() v2acl.Operation {
} }
} }
// OperationFromV2 converts v2 Operation enum value to Operation.
func OperationFromV2(operation v2acl.Operation) (o Operation) { func OperationFromV2(operation v2acl.Operation) (o Operation) {
switch operation { switch operation {
case v2acl.OperationGet: case v2acl.OperationGet:
@ -127,6 +170,7 @@ func OperationFromV2(operation v2acl.Operation) (o Operation) {
return o return o
} }
// ToV2 converts Role to v2 Role enum value.
func (r Role) ToV2() v2acl.Role { func (r Role) ToV2() v2acl.Role {
switch r { switch r {
case RoleUser: case RoleUser:
@ -140,6 +184,7 @@ func (r Role) ToV2() v2acl.Role {
} }
} }
// RoleFromV2 converts v2 Role enum value to Role.
func RoleFromV2(role v2acl.Role) (r Role) { func RoleFromV2(role v2acl.Role) (r Role) {
switch role { switch role {
case v2acl.RoleUser: case v2acl.RoleUser:
@ -155,6 +200,7 @@ func RoleFromV2(role v2acl.Role) (r Role) {
return r return r
} }
// ToV2 converts Match to v2 MatchType enum value.
func (m Match) ToV2() v2acl.MatchType { func (m Match) ToV2() v2acl.MatchType {
switch m { switch m {
case MatchStringEqual: case MatchStringEqual:
@ -166,6 +212,7 @@ func (m Match) ToV2() v2acl.MatchType {
} }
} }
// MatchFromV2 converts v2 MatchType enum value to Match.
func MatchFromV2(match v2acl.MatchType) (m Match) { func MatchFromV2(match v2acl.MatchType) (m Match) {
switch match { switch match {
case v2acl.MatchTypeStringEqual: case v2acl.MatchTypeStringEqual:
@ -179,6 +226,7 @@ func MatchFromV2(match v2acl.MatchType) (m Match) {
return m return m
} }
// ToV2 converts FilterHeaderType to v2 HeaderType enum value.
func (h FilterHeaderType) ToV2() v2acl.HeaderType { func (h FilterHeaderType) ToV2() v2acl.HeaderType {
switch h { switch h {
case HeaderFromRequest: case HeaderFromRequest:
@ -190,6 +238,7 @@ func (h FilterHeaderType) ToV2() v2acl.HeaderType {
} }
} }
// FilterHeaderTypeFromV2 converts v2 HeaderType enum value to FilterHeaderType.
func FilterHeaderTypeFromV2(header v2acl.HeaderType) (h FilterHeaderType) { func FilterHeaderTypeFromV2(header v2acl.HeaderType) (h FilterHeaderType) {
switch header { switch header {
case v2acl.HeaderTypeRequest: case v2acl.HeaderTypeRequest:

View file

@ -8,10 +8,12 @@ import (
// Filter defines check conditions if request header is matched or not. Matched // Filter defines check conditions if request header is matched or not. Matched
// header means that request should be processed according to EACL action. // header means that request should be processed according to EACL action.
//
// Filter is compatible with v2 acl.EACLRecord.Filter message.
type Filter struct { type Filter struct {
from FilterHeaderType from FilterHeaderType
key filterKey
matcher Match matcher Match
key filterKey
value fmt.Stringer value fmt.Stringer
} }
@ -43,22 +45,27 @@ func (s staticStringer) String() string {
return string(s) return string(s)
} }
// Value returns filtered string value.
func (f Filter) Value() string { func (f Filter) Value() string {
return f.value.String() return f.value.String()
} }
// Matcher returns filter Match type.
func (f Filter) Matcher() Match { func (f Filter) Matcher() Match {
return f.matcher return f.matcher
} }
// Key returns key to the filtered header.
func (f Filter) Key() string { func (f Filter) Key() string {
return f.key.String() return f.key.String()
} }
// From returns FilterHeaderType that defined which header will be filtered.
func (f Filter) From() FilterHeaderType { func (f Filter) From() FilterHeaderType {
return f.from return f.from
} }
// ToV2 converts Filter to v2 acl.EACLRecord.Filter message.
func (f *Filter) ToV2() *v2acl.HeaderFilter { func (f *Filter) ToV2() *v2acl.HeaderFilter {
filter := new(v2acl.HeaderFilter) filter := new(v2acl.HeaderFilter)
filter.SetValue(f.value.String()) filter.SetValue(f.value.String())
@ -94,10 +101,12 @@ func (k filterKey) String() string {
} }
} }
// NewFilter creates, initializes and returns blank Filter instance.
func NewFilter() *Filter { func NewFilter() *Filter {
return NewFilterFromV2(new(v2acl.HeaderFilter)) return NewFilterFromV2(new(v2acl.HeaderFilter))
} }
// NewFilterFromV2 converts v2 acl.EACLRecord.Filter message to Filter.
func NewFilterFromV2(filter *v2acl.HeaderFilter) *Filter { func NewFilterFromV2(filter *v2acl.HeaderFilter) *Filter {
f := new(Filter) f := new(Filter)

View file

@ -10,43 +10,50 @@ import (
v2acl "github.com/nspcc-dev/neofs-api-go/v2/acl" v2acl "github.com/nspcc-dev/neofs-api-go/v2/acl"
) )
type (
// Record of the EACL rule, that defines EACL action, targets for this action, // Record of the EACL rule, that defines EACL action, targets for this action,
// object service operation and filters for request headers. // object service operation and filters for request headers.
Record struct { //
// Record is compatible with v2 acl.EACLRecord message.
type Record struct {
action Action action Action
operation Operation operation Operation
filters []Filter filters []*Filter
targets []Target targets []*Target
} }
)
func (r Record) Targets() []Target { // Targets returns list of target subjects to apply ACL rule to.
func (r Record) Targets() []*Target {
return r.targets return r.targets
} }
func (r Record) Filters() []Filter { // Filters returns list of filters to match and see if rule is applicable.
func (r Record) Filters() []*Filter {
return r.filters return r.filters
} }
// Operation returns NeoFS request verb to match.
func (r Record) Operation() Operation { func (r Record) Operation() Operation {
return r.operation return r.operation
} }
// SetOperation sets NeoFS request verb to match.
func (r *Record) SetOperation(operation Operation) { func (r *Record) SetOperation(operation Operation) {
r.operation = operation r.operation = operation
} }
// Action returns rule execution result.
func (r Record) Action() Action { func (r Record) Action() Action {
return r.action return r.action
} }
// SetAction sets rule execution result.
func (r *Record) SetAction(action Action) { func (r *Record) SetAction(action Action) {
r.action = action r.action = action
} }
// AddTarget adds target subject with specified Role and key list.
func (r *Record) AddTarget(role Role, keys ...ecdsa.PublicKey) { func (r *Record) AddTarget(role Role, keys ...ecdsa.PublicKey) {
t := Target{ t := &Target{
role: role, role: role,
keys: make([]ecdsa.PublicKey, 0, len(keys)), keys: make([]ecdsa.PublicKey, 0, len(keys)),
} }
@ -59,7 +66,7 @@ func (r *Record) AddTarget(role Role, keys ...ecdsa.PublicKey) {
} }
func (r *Record) addFilter(from FilterHeaderType, m Match, keyTyp filterKeyType, key string, val fmt.Stringer) { func (r *Record) addFilter(from FilterHeaderType, m Match, keyTyp filterKeyType, key string, val fmt.Stringer) {
filter := Filter{ filter := &Filter{
from: from, from: from,
key: filterKey{ key: filterKey{
typ: keyTyp, typ: keyTyp,
@ -80,28 +87,34 @@ func (r *Record) addObjectReservedFilter(m Match, typ filterKeyType, val fmt.Str
r.addObjectFilter(m, typ, "", val) r.addObjectFilter(m, typ, "", val)
} }
// AddFilter adds generic filter.
func (r *Record) AddFilter(from FilterHeaderType, matcher Match, name, value string) { func (r *Record) AddFilter(from FilterHeaderType, matcher Match, name, value string) {
r.addFilter(from, matcher, 0, name, staticStringer(value)) r.addFilter(from, matcher, 0, name, staticStringer(value))
} }
// AddObjectAttributeFilter adds filter by object attribute.
func (r *Record) AddObjectAttributeFilter(m Match, key, value string) { func (r *Record) AddObjectAttributeFilter(m Match, key, value string) {
r.addObjectFilter(m, 0, key, staticStringer(value)) r.addObjectFilter(m, 0, key, staticStringer(value))
} }
// AddObjectVersionFilter adds filter by object version.
func (r *Record) AddObjectVersionFilter(m Match, v *pkg.Version) { func (r *Record) AddObjectVersionFilter(m Match, v *pkg.Version) {
r.addObjectReservedFilter(m, fKeyObjVersion, v) r.addObjectReservedFilter(m, fKeyObjVersion, v)
} }
// AddObjectContainerIDFilter adds filter by object container ID.
func (r *Record) AddObjectContainerIDFilter(m Match, id *container.ID) { func (r *Record) AddObjectContainerIDFilter(m Match, id *container.ID) {
r.addObjectReservedFilter(m, fKeyObjContainerID, id) r.addObjectReservedFilter(m, fKeyObjContainerID, id)
} }
// AddObjectOwnerIDFilter adds filter by object owner ID.
func (r *Record) AddObjectOwnerIDFilter(m Match, id *owner.ID) { func (r *Record) AddObjectOwnerIDFilter(m Match, id *owner.ID) {
r.addObjectReservedFilter(m, fKeyObjOwnerID, id) r.addObjectReservedFilter(m, fKeyObjOwnerID, id)
} }
// TODO: add remaining filters after neofs-api#72 // TODO: add remaining filters after neofs-api#72
// ToV2 converts Record to v2 acl.EACLRecord message.
func (r *Record) ToV2() *v2acl.Record { func (r *Record) ToV2() *v2acl.Record {
targets := make([]*v2acl.Target, 0, len(r.targets)) targets := make([]*v2acl.Target, 0, len(r.targets))
for _, target := range r.targets { for _, target := range r.targets {
@ -123,20 +136,23 @@ func (r *Record) ToV2() *v2acl.Record {
return v2 return v2
} }
// NewRecord creates and returns blank Record instance.
func NewRecord() *Record { func NewRecord() *Record {
return new(Record) return new(Record)
} }
// CreateRecord creates, initializes with parameters and returns Record instance.
func CreateRecord(action Action, operation Operation) *Record { func CreateRecord(action Action, operation Operation) *Record {
r := NewRecord() r := NewRecord()
r.action = action r.action = action
r.operation = operation r.operation = operation
r.targets = []Target{} r.targets = []*Target{}
r.filters = []Filter{} r.filters = []*Filter{}
return r return r
} }
// NewRecordFromV2 converts v2 acl.EACLRecord message to Record.
func NewRecordFromV2(record *v2acl.Record) *Record { func NewRecordFromV2(record *v2acl.Record) *Record {
r := NewRecord() r := NewRecord()
@ -150,14 +166,14 @@ func NewRecordFromV2(record *v2acl.Record) *Record {
v2targets := record.GetTargets() v2targets := record.GetTargets()
v2filters := record.GetFilters() v2filters := record.GetFilters()
r.targets = make([]Target, 0, len(v2targets)) r.targets = make([]*Target, 0, len(v2targets))
for i := range v2targets { for i := range v2targets {
r.targets = append(r.targets, *NewTargetFromV2(v2targets[i])) r.targets = append(r.targets, NewTargetFromV2(v2targets[i]))
} }
r.filters = make([]Filter, 0, len(v2filters)) r.filters = make([]*Filter, 0, len(v2filters))
for i := range v2filters { for i := range v2filters {
r.filters = append(r.filters, *NewFilterFromV2(v2filters[i])) r.filters = append(r.filters, NewFilterFromV2(v2filters[i]))
} }
return r return r

View file

@ -39,7 +39,7 @@ func TestRecord(t *testing.T) {
} }
func TestRecord_AddTarget(t *testing.T) { func TestRecord_AddTarget(t *testing.T) {
targets := []Target{ targets := []*Target{
{ {
role: RoleUnknown, role: RoleUnknown,
keys: []ecdsa.PublicKey{test.DecodeKey(1).PublicKey}, keys: []ecdsa.PublicKey{test.DecodeKey(1).PublicKey},
@ -59,9 +59,9 @@ func TestRecord_AddTarget(t *testing.T) {
} }
func TestRecord_AddFilter(t *testing.T) { func TestRecord_AddFilter(t *testing.T) {
filters := []Filter{ filters := []*Filter{
*newObjectFilter(MatchStringEqual, "some name", "ContainerID"), newObjectFilter(MatchStringEqual, "some name", "ContainerID"),
*newObjectFilter(MatchStringNotEqual, "X-Header-Name", "X-Header-Value"), newObjectFilter(MatchStringNotEqual, "X-Header-Name", "X-Header-Value"),
} }
r := NewRecord() r := NewRecord()

View file

@ -8,41 +8,48 @@ import (
v2acl "github.com/nspcc-dev/neofs-api-go/v2/acl" v2acl "github.com/nspcc-dev/neofs-api-go/v2/acl"
) )
type (
// Table is a group of EACL records for single container. // Table is a group of EACL records for single container.
Table struct { //
// Table is compatible with v2 acl.EACLTable message.
type Table struct {
version pkg.Version version pkg.Version
cid *container.ID cid *container.ID
records []Record records []*Record
} }
)
// CID returns identifier of the container that should use given access control rules.
func (t Table) CID() *container.ID { func (t Table) CID() *container.ID {
return t.cid return t.cid
} }
// SetCID sets identifier of the container that should use given access control rules.
func (t *Table) SetCID(cid *container.ID) { func (t *Table) SetCID(cid *container.ID) {
t.cid = cid t.cid = cid
} }
// Version returns version of eACL format.
func (t Table) Version() pkg.Version { func (t Table) Version() pkg.Version {
return t.version return t.version
} }
// SetVersion sets version of eACL format.
func (t *Table) SetVersion(version pkg.Version) { func (t *Table) SetVersion(version pkg.Version) {
t.version = version t.version = version
} }
func (t Table) Records() []Record { // Records returns list of extended ACL rules.
func (t Table) Records() []*Record {
return t.records return t.records
} }
// AddRecord adds single eACL rule.
func (t *Table) AddRecord(r *Record) { func (t *Table) AddRecord(r *Record) {
if r != nil { if r != nil {
t.records = append(t.records, *r) t.records = append(t.records, r)
} }
} }
// ToV2 converts Table to v2 acl.EACLTable message.
func (t *Table) ToV2() *v2acl.Table { func (t *Table) ToV2() *v2acl.Table {
v2 := new(v2acl.Table) v2 := new(v2acl.Table)
@ -61,6 +68,7 @@ func (t *Table) ToV2() *v2acl.Table {
return v2 return v2
} }
// NewTable creates, initializes and returns blank Table instance.
func NewTable() *Table { func NewTable() *Table {
t := new(Table) t := new(Table)
t.SetVersion(*pkg.SDKVersion()) t.SetVersion(*pkg.SDKVersion())
@ -68,6 +76,7 @@ func NewTable() *Table {
return t return t
} }
// CreateTable creates, initializes with parameters and returns Table instance.
func CreateTable(cid container.ID) *Table { func CreateTable(cid container.ID) *Table {
t := NewTable() t := NewTable()
t.SetCID(&cid) t.SetCID(&cid)
@ -75,6 +84,7 @@ func CreateTable(cid container.ID) *Table {
return t return t
} }
// NewTableFromV2 converts v2 acl.EACLTable message to Table.
func NewTableFromV2(table *v2acl.Table) *Table { func NewTableFromV2(table *v2acl.Table) *Table {
t := new(Table) t := new(Table)
@ -98,15 +108,17 @@ func NewTableFromV2(table *v2acl.Table) *Table {
} }
var h [sha256.Size]byte var h [sha256.Size]byte
copy(h[:], table.GetContainerID().GetValue()) copy(h[:], table.GetContainerID().GetValue())
t.cid.SetSHA256(h) t.cid.SetSHA256(h)
} }
// set eacl records // set eacl records
v2records := table.GetRecords() v2records := table.GetRecords()
t.records = make([]Record, 0, len(v2records)) t.records = make([]*Record, 0, len(v2records))
for i := range v2records { for i := range v2records {
t.records = append(t.records, *NewRecordFromV2(v2records[i])) t.records = append(t.records, NewRecordFromV2(v2records[i]))
} }
return t return t

View file

@ -7,23 +7,9 @@ import (
"github.com/nspcc-dev/neofs-api-go/pkg" "github.com/nspcc-dev/neofs-api-go/pkg"
"github.com/nspcc-dev/neofs-api-go/pkg/acl/eacl" "github.com/nspcc-dev/neofs-api-go/pkg/acl/eacl"
"github.com/nspcc-dev/neofs-api-go/pkg/container" "github.com/nspcc-dev/neofs-api-go/pkg/container"
"github.com/nspcc-dev/neofs-crypto/test"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
) )
// example how to create eACL tables in applications
func example() {
record := eacl.CreateRecord(eacl.ActionDeny, eacl.OperationPut)
record.AddFilter(eacl.HeaderFromObject, eacl.MatchStringEqual, "filename", "cat.jpg")
record.AddTarget(eacl.RoleOthers, test.DecodeKey(1).PublicKey, test.DecodeKey(2).PublicKey)
var cid container.ID
cid.SetSHA256(sha256.Sum256([]byte("container id")))
table := eacl.CreateTable(cid)
table.AddRecord(record)
}
func TestTable(t *testing.T) { func TestTable(t *testing.T) {
var ( var (
v pkg.Version v pkg.Version
@ -66,14 +52,14 @@ func TestTable(t *testing.T) {
} }
func TestTable_AddRecord(t *testing.T) { func TestTable_AddRecord(t *testing.T) {
records := []eacl.Record{ records := []*eacl.Record{
*eacl.CreateRecord(eacl.ActionDeny, eacl.OperationDelete), eacl.CreateRecord(eacl.ActionDeny, eacl.OperationDelete),
*eacl.CreateRecord(eacl.ActionAllow, eacl.OperationPut), eacl.CreateRecord(eacl.ActionAllow, eacl.OperationPut),
} }
table := eacl.NewTable() table := eacl.NewTable()
for _, record := range records { for _, record := range records {
table.AddRecord(&record) table.AddRecord(record)
} }
require.Equal(t, records, table.Records()) require.Equal(t, records, table.Records())

View file

@ -9,27 +9,34 @@ import (
// Target is a group of request senders to match EACL. Defined by role enum // Target is a group of request senders to match EACL. Defined by role enum
// and set of public keys. // and set of public keys.
//
// Target is compatible with v2 acl.EACLRecord.Target message.
type Target struct { type Target struct {
role Role role Role
keys []ecdsa.PublicKey keys []ecdsa.PublicKey
} }
// SetKeys sets list of public keys to identify target subject.
func (t *Target) SetKeys(keys ...ecdsa.PublicKey) { func (t *Target) SetKeys(keys ...ecdsa.PublicKey) {
t.keys = keys t.keys = keys
} }
// Keys returns list of public keys to identify target subject.
func (t Target) Keys() []ecdsa.PublicKey { func (t Target) Keys() []ecdsa.PublicKey {
return t.keys return t.keys
} }
// SetRole sets target subject's role class.
func (t *Target) SetRole(r Role) { func (t *Target) SetRole(r Role) {
t.role = r t.role = r
} }
// Role returns target subject's role class.
func (t Target) Role() Role { func (t Target) Role() Role {
return t.role return t.role
} }
// ToV2 converts Target to v2 acl.EACLRecord.Target message.
func (t *Target) ToV2() *v2acl.Target { func (t *Target) ToV2() *v2acl.Target {
keys := make([][]byte, 0, len(t.keys)) keys := make([][]byte, 0, len(t.keys))
for i := range t.keys { for i := range t.keys {
@ -45,10 +52,12 @@ func (t *Target) ToV2() *v2acl.Target {
return target return target
} }
// NewTarget creates, initializes and returns blank Target instance.
func NewTarget() *Target { func NewTarget() *Target {
return NewTargetFromV2(new(v2acl.Target)) return NewTargetFromV2(new(v2acl.Target))
} }
// NewTargetFromV2 converts v2 acl.EACLRecord.Target message to Target.
func NewTargetFromV2(target *v2acl.Target) *Target { func NewTargetFromV2(target *v2acl.Target) *Target {
t := new(Target) t := new(Target)
@ -59,6 +68,7 @@ func NewTargetFromV2(target *v2acl.Target) *Target {
t.role = RoleFromV2(target.GetRole()) t.role = RoleFromV2(target.GetRole())
v2keys := target.GetKeys() v2keys := target.GetKeys()
t.keys = make([]ecdsa.PublicKey, 0, len(v2keys)) t.keys = make([]ecdsa.PublicKey, 0, len(v2keys))
for i := range v2keys { for i := range v2keys {
key := crypto.UnmarshalPublicKey(v2keys[i]) key := crypto.UnmarshalPublicKey(v2keys[i])
t.keys = append(t.keys, *key) t.keys = append(t.keys, *key)