[#199] sdk/eacl: Correct linter's remarks
Signed-off-by: Leonard Lyubich <leonard@nspcc.ru>
This commit is contained in:
parent
2b3502d6c0
commit
c6884f9823
7 changed files with 137 additions and 55 deletions
|
@ -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:
|
||||||
|
|
|
@ -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)
|
||||||
|
|
||||||
|
|
|
@ -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.
|
||||||
action Action
|
type Record struct {
|
||||||
operation Operation
|
action Action
|
||||||
filters []Filter
|
operation Operation
|
||||||
targets []Target
|
filters []*Filter
|
||||||
}
|
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
|
||||||
|
|
|
@ -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()
|
||||||
|
|
|
@ -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.
|
||||||
version pkg.Version
|
type Table struct {
|
||||||
cid *container.ID
|
version pkg.Version
|
||||||
records []Record
|
cid *container.ID
|
||||||
}
|
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
|
||||||
|
|
|
@ -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())
|
||||||
|
|
|
@ -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)
|
||||||
|
|
Loading…
Reference in a new issue