forked from TrueCloudLab/frostfs-api-go
Merge branch 'release/1.2.0'
This commit is contained in:
commit
3cc34a823f
14 changed files with 1181 additions and 19 deletions
18
CHANGELOG.md
18
CHANGELOG.md
|
@ -1,6 +1,23 @@
|
||||||
# Changelog
|
# Changelog
|
||||||
This is the changelog for NeoFS-API-Go
|
This is the changelog for NeoFS-API-Go
|
||||||
|
|
||||||
|
## [1.2.0] - 2020-07-08
|
||||||
|
|
||||||
|
### Added
|
||||||
|
|
||||||
|
- Extended ACL types.
|
||||||
|
- Getters and setters of ```EACLTable``` and its internal messages.
|
||||||
|
- Wrappers over ```EACLTable``` and its internal messages.
|
||||||
|
- Getters, setters and marshaling methods of wrappers.
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
- Mechanism for signing requests on the principle of Matryoshka.
|
||||||
|
|
||||||
|
### Updated
|
||||||
|
|
||||||
|
- NeoFS API v1.1.0 => 1.2.0
|
||||||
|
|
||||||
## [1.1.0] - 2020-06-18
|
## [1.1.0] - 2020-06-18
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
@ -357,3 +374,4 @@ Initial public release
|
||||||
[0.7.6]: https://github.com/nspcc-dev/neofs-api-go/compare/v0.7.5...v0.7.6
|
[0.7.6]: https://github.com/nspcc-dev/neofs-api-go/compare/v0.7.5...v0.7.6
|
||||||
[1.0.0]: https://github.com/nspcc-dev/neofs-api-go/compare/v0.7.6...v1.0.0
|
[1.0.0]: https://github.com/nspcc-dev/neofs-api-go/compare/v0.7.6...v1.0.0
|
||||||
[1.1.0]: https://github.com/nspcc-dev/neofs-api-go/compare/v1.0.0...v1.1.0
|
[1.1.0]: https://github.com/nspcc-dev/neofs-api-go/compare/v1.0.0...v1.1.0
|
||||||
|
[1.2.0]: https://github.com/nspcc-dev/neofs-api-go/compare/v1.1.0...v1.2.0
|
||||||
|
|
2
Makefile
2
Makefile
|
@ -1,4 +1,4 @@
|
||||||
PROTO_VERSION=v1.1.0
|
PROTO_VERSION=v1.2.0
|
||||||
PROTO_URL=https://github.com/nspcc-dev/neofs-api/archive/$(PROTO_VERSION).tar.gz
|
PROTO_URL=https://github.com/nspcc-dev/neofs-api/archive/$(PROTO_VERSION).tar.gz
|
||||||
|
|
||||||
B=\033[0;1m
|
B=\033[0;1m
|
||||||
|
|
|
@ -15,7 +15,11 @@ can be used for integration with NeoFS.
|
||||||
|
|
||||||
[neofs-api v1.1.0]: https://github.com/nspcc-dev/neofs-api/releases/tag/v1.1.0
|
[neofs-api v1.1.0]: https://github.com/nspcc-dev/neofs-api/releases/tag/v1.1.0
|
||||||
[neofs-api-go v1.1.0]: https://github.com/nspcc-dev/neofs-api-go/releases/tag/v1.1.0
|
[neofs-api-go v1.1.0]: https://github.com/nspcc-dev/neofs-api-go/releases/tag/v1.1.0
|
||||||
[neofs-api-go v1.1.0] supports [neofs-api v1.1.0]
|
* [neofs-api-go v1.1.0] supports [neofs-api v1.1.0]
|
||||||
|
|
||||||
|
[neofs-api v1.2.0]: https://github.com/nspcc-dev/neofs-api/releases/tag/v1.2.0
|
||||||
|
[neofs-api-go v1.2.0]: https://github.com/nspcc-dev/neofs-api-go/releases/tag/v1.2.0
|
||||||
|
* [neofs-api-go v1.2.0] supports [neofs-api v1.2.0]
|
||||||
|
|
||||||
## Description
|
## Description
|
||||||
|
|
||||||
|
|
93
acl/extended.go
Normal file
93
acl/extended.go
Normal file
|
@ -0,0 +1,93 @@
|
||||||
|
package acl
|
||||||
|
|
||||||
|
// OperationType is an enumeration of operation types for extended ACL.
|
||||||
|
type OperationType uint32
|
||||||
|
|
||||||
|
// HeaderType is an enumeration of header types for extended ACL.
|
||||||
|
type HeaderType uint32
|
||||||
|
|
||||||
|
// MatchType is an enumeration of match types for extended ACL.
|
||||||
|
type MatchType uint32
|
||||||
|
|
||||||
|
// ExtendedACLAction is an enumeration of extended ACL actions.
|
||||||
|
type ExtendedACLAction uint32
|
||||||
|
|
||||||
|
// Header is an interface of string key-value pair,
|
||||||
|
type Header interface {
|
||||||
|
// Must return string identifier of header.
|
||||||
|
Name() string
|
||||||
|
|
||||||
|
// Must return string value of header.
|
||||||
|
Value() string
|
||||||
|
}
|
||||||
|
|
||||||
|
// TypedHeader is an interface of Header and HeaderType pair.
|
||||||
|
type TypedHeader interface {
|
||||||
|
Header
|
||||||
|
|
||||||
|
// Must return type of filtered header.
|
||||||
|
HeaderType() HeaderType
|
||||||
|
}
|
||||||
|
|
||||||
|
// HeaderFilter is an interface of grouped information about filtered header.
|
||||||
|
type HeaderFilter interface {
|
||||||
|
// Must return match type of filter.
|
||||||
|
MatchType() MatchType
|
||||||
|
|
||||||
|
TypedHeader
|
||||||
|
}
|
||||||
|
|
||||||
|
// ExtendedACLTarget is an interface of grouped information about extended ACL rule target.
|
||||||
|
type ExtendedACLTarget interface {
|
||||||
|
// Must return ACL target type.
|
||||||
|
Target() Target
|
||||||
|
|
||||||
|
// Must return public key list of ACL targets.
|
||||||
|
KeyList() [][]byte
|
||||||
|
}
|
||||||
|
|
||||||
|
// ExtendedACLRecord is an interface of record of extended ACL rule table.
|
||||||
|
type ExtendedACLRecord interface {
|
||||||
|
// Must return operation type of extended ACL rule.
|
||||||
|
OperationType() OperationType
|
||||||
|
|
||||||
|
// Must return list of header filters of extended ACL rule.
|
||||||
|
HeaderFilters() []HeaderFilter
|
||||||
|
|
||||||
|
// Must return target list of extended ACL rule.
|
||||||
|
TargetList() []ExtendedACLTarget
|
||||||
|
|
||||||
|
// Must return action of extended ACL rule.
|
||||||
|
Action() ExtendedACLAction
|
||||||
|
}
|
||||||
|
|
||||||
|
// ExtendedACLTable is an interface of extended ACL table.
|
||||||
|
type ExtendedACLTable interface {
|
||||||
|
// Must return list of extended ACL rules.
|
||||||
|
Records() []ExtendedACLRecord
|
||||||
|
}
|
||||||
|
|
||||||
|
const (
|
||||||
|
_ OperationType = iota
|
||||||
|
|
||||||
|
// OpTypeGet is an OperationType for object.Get RPC
|
||||||
|
OpTypeGet
|
||||||
|
|
||||||
|
// OpTypePut is an OperationType for object.Put RPC
|
||||||
|
OpTypePut
|
||||||
|
|
||||||
|
// OpTypeHead is an OperationType for object.Head RPC
|
||||||
|
OpTypeHead
|
||||||
|
|
||||||
|
// OpTypeSearch is an OperationType for object.Search RPC
|
||||||
|
OpTypeSearch
|
||||||
|
|
||||||
|
// OpTypeDelete is an OperationType for object.Delete RPC
|
||||||
|
OpTypeDelete
|
||||||
|
|
||||||
|
// OpTypeRange is an OperationType for object.GetRange RPC
|
||||||
|
OpTypeRange
|
||||||
|
|
||||||
|
// OpTypeRangeHash is an OperationType for object.GetRangeHash RPC
|
||||||
|
OpTypeRangeHash
|
||||||
|
)
|
130
acl/types.go
Normal file
130
acl/types.go
Normal file
|
@ -0,0 +1,130 @@
|
||||||
|
package acl
|
||||||
|
|
||||||
|
const (
|
||||||
|
_ MatchType = iota
|
||||||
|
|
||||||
|
// StringEqual is a MatchType of string equality.
|
||||||
|
StringEqual
|
||||||
|
|
||||||
|
// StringNotEqual is a MatchType of string inequality.
|
||||||
|
StringNotEqual
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
// ActionUndefined is ExtendedACLAction used to mark value as undefined.
|
||||||
|
// Most of the tools consider ActionUndefined as incalculable.
|
||||||
|
// Using ActionUndefined in ExtendedACLRecord is unsafe.
|
||||||
|
ActionUndefined ExtendedACLAction = iota
|
||||||
|
|
||||||
|
// ActionAllow is ExtendedACLAction used to mark an applicability of ACL rule.
|
||||||
|
ActionAllow
|
||||||
|
|
||||||
|
// ActionDeny is ExtendedACLAction used to mark an inapplicability of ACL rule.
|
||||||
|
ActionDeny
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
_ HeaderType = iota
|
||||||
|
|
||||||
|
// HdrTypeRequest is a HeaderType for request header.
|
||||||
|
HdrTypeRequest
|
||||||
|
|
||||||
|
// HdrTypeObjSys is a HeaderType for system headers of object.
|
||||||
|
HdrTypeObjSys
|
||||||
|
|
||||||
|
// HdrTypeObjUsr is a HeaderType for user headers of object.
|
||||||
|
HdrTypeObjUsr
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
// HdrObjSysNameID is a name of ID field in system header of object.
|
||||||
|
HdrObjSysNameID = "ID"
|
||||||
|
|
||||||
|
// HdrObjSysNameCID is a name of CID field in system header of object.
|
||||||
|
HdrObjSysNameCID = "CID"
|
||||||
|
|
||||||
|
// HdrObjSysNameOwnerID is a name of OwnerID field in system header of object.
|
||||||
|
HdrObjSysNameOwnerID = "OWNER_ID"
|
||||||
|
|
||||||
|
// HdrObjSysNameVersion is a name of Version field in system header of object.
|
||||||
|
HdrObjSysNameVersion = "VERSION"
|
||||||
|
|
||||||
|
// HdrObjSysNamePayloadLength is a name of PayloadLength field in system header of object.
|
||||||
|
HdrObjSysNamePayloadLength = "PAYLOAD_LENGTH"
|
||||||
|
|
||||||
|
// HdrObjSysNameCreatedUnix is a name of CreatedAt.UnitTime field in system header of object.
|
||||||
|
HdrObjSysNameCreatedUnix = "CREATED_UNIX"
|
||||||
|
|
||||||
|
// HdrObjSysNameCreatedEpoch is a name of CreatedAt.Epoch field in system header of object.
|
||||||
|
HdrObjSysNameCreatedEpoch = "CREATED_EPOCH"
|
||||||
|
|
||||||
|
// HdrObjSysLinkPrev is a name of previous link header in extended headers of object.
|
||||||
|
HdrObjSysLinkPrev = "LINK_PREV"
|
||||||
|
|
||||||
|
// HdrObjSysLinkNext is a name of next link header in extended headers of object.
|
||||||
|
HdrObjSysLinkNext = "LINK_NEXT"
|
||||||
|
|
||||||
|
// HdrObjSysLinkChild is a name of child link header in extended headers of object.
|
||||||
|
HdrObjSysLinkChild = "LINK_CHILD"
|
||||||
|
|
||||||
|
// HdrObjSysLinkPar is a name of parent link header in extended headers of object.
|
||||||
|
HdrObjSysLinkPar = "LINK_PAR"
|
||||||
|
|
||||||
|
// HdrObjSysLinkSG is a name of storage group link header in extended headers of object.
|
||||||
|
HdrObjSysLinkSG = "LINK_SG"
|
||||||
|
)
|
||||||
|
|
||||||
|
// SetMatchType is MatchType field setter.
|
||||||
|
func (m *EACLRecord_FilterInfo) SetMatchType(v EACLRecord_FilterInfo_MatchType) {
|
||||||
|
m.MatchType = v
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetHeader is a Header field setter.
|
||||||
|
func (m *EACLRecord_FilterInfo) SetHeader(v EACLRecord_FilterInfo_Header) {
|
||||||
|
m.Header = v
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetHeaderName is a HeaderName field setter.
|
||||||
|
func (m *EACLRecord_FilterInfo) SetHeaderName(v string) {
|
||||||
|
m.HeaderName = v
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetHeaderVal is a HeaderVal field setter.
|
||||||
|
func (m *EACLRecord_FilterInfo) SetHeaderVal(v string) {
|
||||||
|
m.HeaderVal = v
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetTarget is a Target field setter.
|
||||||
|
func (m *EACLRecord_TargetInfo) SetTarget(v Target) {
|
||||||
|
m.Target = v
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetKeyList is a KeyList field setter.
|
||||||
|
func (m *EACLRecord_TargetInfo) SetKeyList(v [][]byte) {
|
||||||
|
m.KeyList = v
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetOperation is an Operation field setter.
|
||||||
|
func (m *EACLRecord) SetOperation(v EACLRecord_Operation) {
|
||||||
|
m.Operation = v
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetAction is an Action field setter.
|
||||||
|
func (m *EACLRecord) SetAction(v EACLRecord_Action) {
|
||||||
|
m.Action = v
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetFilters is a Filters field setter.
|
||||||
|
func (m *EACLRecord) SetFilters(v []*EACLRecord_FilterInfo) {
|
||||||
|
m.Filters = v
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetTargets is a Targets field setter.
|
||||||
|
func (m *EACLRecord) SetTargets(v []*EACLRecord_TargetInfo) {
|
||||||
|
m.Targets = v
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetRecords is a Records field setter.
|
||||||
|
func (m *EACLTable) SetRecords(v []*EACLRecord) {
|
||||||
|
m.Records = v
|
||||||
|
}
|
BIN
acl/types.pb.go
BIN
acl/types.pb.go
Binary file not shown.
|
@ -25,3 +25,82 @@ enum Target {
|
||||||
// extended ACL.
|
// extended ACL.
|
||||||
PubKey = 4;
|
PubKey = 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// EACLRecord groups information about extended ACL rule.
|
||||||
|
message EACLRecord {
|
||||||
|
// Operation is an enumeration of operation types.
|
||||||
|
enum Operation {
|
||||||
|
OPERATION_UNKNOWN = 0;
|
||||||
|
GET = 1;
|
||||||
|
HEAD = 2;
|
||||||
|
PUT = 3;
|
||||||
|
DELETE = 4;
|
||||||
|
SEARCH = 5;
|
||||||
|
GETRANGE = 6;
|
||||||
|
GETRANGEHASH = 7;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Operation carries type of operation.
|
||||||
|
Operation operation = 1 [(gogoproto.customname) = "Operation", json_name="Operation"];
|
||||||
|
|
||||||
|
// Action is an enumeration of EACL actions.
|
||||||
|
enum Action {
|
||||||
|
ActionUnknown = 0;
|
||||||
|
Allow = 1;
|
||||||
|
Deny = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Action carries ACL target action.
|
||||||
|
Action action = 2 [(gogoproto.customname) = "Action", json_name="Action"];
|
||||||
|
|
||||||
|
// FilterInfo groups information about filter.
|
||||||
|
message FilterInfo {
|
||||||
|
// Header is an enumeration of filtering header types.
|
||||||
|
enum Header {
|
||||||
|
HeaderUnknown = 0;
|
||||||
|
Request = 1;
|
||||||
|
ObjectSystem = 2;
|
||||||
|
ObjectUser = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Header carries type of header.
|
||||||
|
Header header = 1 [(gogoproto.customname) = "Header", json_name="HeaderType"];
|
||||||
|
|
||||||
|
// MatchType is an enumeration of match types.
|
||||||
|
enum MatchType {
|
||||||
|
MatchUnknown = 0;
|
||||||
|
StringEqual = 1;
|
||||||
|
StringNotEqual = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
// MatchType carries type of match.
|
||||||
|
MatchType matchType = 2 [(gogoproto.customname) = "MatchType", json_name="MatchType"];
|
||||||
|
|
||||||
|
// HeaderName carries name of filtering header.
|
||||||
|
string HeaderName = 3 [json_name="Name"];
|
||||||
|
|
||||||
|
// HeaderVal carries value of filtering header.
|
||||||
|
string HeaderVal = 4 [json_name="Value"];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Filters carries set of filters.
|
||||||
|
repeated FilterInfo Filters = 3 [json_name="Filters"];
|
||||||
|
|
||||||
|
// TargetInfo groups information about extended ACL target.
|
||||||
|
message TargetInfo {
|
||||||
|
// Target carries target of ACL rule.
|
||||||
|
acl.Target Target = 1 [json_name="Role"];
|
||||||
|
|
||||||
|
// KeyList carries public keys of ACL target.
|
||||||
|
repeated bytes KeyList = 2 [json_name="Keys"];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Targets carries information about extended ACL target list.
|
||||||
|
repeated TargetInfo Targets = 4 [json_name="Targets"];
|
||||||
|
}
|
||||||
|
|
||||||
|
// EACLRecord carries the information about extended ACL rules.
|
||||||
|
message EACLTable {
|
||||||
|
// Records carries list of extended ACL rule records.
|
||||||
|
repeated EACLRecord Records = 1 [json_name="Records"];
|
||||||
|
}
|
||||||
|
|
498
acl/wrappers.go
Normal file
498
acl/wrappers.go
Normal file
|
@ -0,0 +1,498 @@
|
||||||
|
package acl
|
||||||
|
|
||||||
|
// EACLFilterWrapper is a wrapper over EACLRecord_FilterInfo pointer.
|
||||||
|
type EACLFilterWrapper struct {
|
||||||
|
filter *EACLRecord_FilterInfo
|
||||||
|
}
|
||||||
|
|
||||||
|
// EACLTargetWrapper is a wrapper over EACLRecord_TargetInfo pointer.
|
||||||
|
type EACLTargetWrapper struct {
|
||||||
|
target *EACLRecord_TargetInfo
|
||||||
|
}
|
||||||
|
|
||||||
|
// EACLRecordWrapper is a wrapper over EACLRecord pointer.
|
||||||
|
type EACLRecordWrapper struct {
|
||||||
|
record *EACLRecord
|
||||||
|
}
|
||||||
|
|
||||||
|
// EACLTableWrapper is a wrapper over EACLTable pointer.
|
||||||
|
type EACLTableWrapper struct {
|
||||||
|
table *EACLTable
|
||||||
|
}
|
||||||
|
|
||||||
|
// WrapFilterInfo wraps EACLRecord_FilterInfo pointer.
|
||||||
|
//
|
||||||
|
// If argument is nil, new EACLRecord_FilterInfo is initialized.
|
||||||
|
func WrapFilterInfo(v *EACLRecord_FilterInfo) EACLFilterWrapper {
|
||||||
|
if v == nil {
|
||||||
|
v = new(EACLRecord_FilterInfo)
|
||||||
|
}
|
||||||
|
|
||||||
|
return EACLFilterWrapper{
|
||||||
|
filter: v,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// WrapEACLTarget wraps EACLRecord_TargetInfo pointer.
|
||||||
|
//
|
||||||
|
// If argument is nil, new EACLRecord_TargetInfo is initialized.
|
||||||
|
func WrapEACLTarget(v *EACLRecord_TargetInfo) EACLTargetWrapper {
|
||||||
|
if v == nil {
|
||||||
|
v = new(EACLRecord_TargetInfo)
|
||||||
|
}
|
||||||
|
|
||||||
|
return EACLTargetWrapper{
|
||||||
|
target: v,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// WrapEACLRecord wraps EACLRecord pointer.
|
||||||
|
//
|
||||||
|
// If argument is nil, new EACLRecord is initialized.
|
||||||
|
func WrapEACLRecord(v *EACLRecord) EACLRecordWrapper {
|
||||||
|
if v == nil {
|
||||||
|
v = new(EACLRecord)
|
||||||
|
}
|
||||||
|
|
||||||
|
return EACLRecordWrapper{
|
||||||
|
record: v,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// WrapEACLTable wraps EACLTable pointer.
|
||||||
|
//
|
||||||
|
// If argument is nil, new EACLTable is initialized.
|
||||||
|
func WrapEACLTable(v *EACLTable) EACLTableWrapper {
|
||||||
|
if v == nil {
|
||||||
|
v = new(EACLTable)
|
||||||
|
}
|
||||||
|
|
||||||
|
return EACLTableWrapper{
|
||||||
|
table: v,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// MatchType returns casted result of MatchType field getter.
|
||||||
|
//
|
||||||
|
// If filter is not initialized, 0 returns.
|
||||||
|
//
|
||||||
|
// Returns 0 if MatchType is not one of:
|
||||||
|
// - EACLRecord_FilterInfo_StringEqual;
|
||||||
|
// - EACLRecord_FilterInfo_StringNotEqual.
|
||||||
|
func (s EACLFilterWrapper) MatchType() (res MatchType) {
|
||||||
|
if s.filter != nil {
|
||||||
|
switch s.filter.GetMatchType() {
|
||||||
|
case EACLRecord_FilterInfo_StringEqual:
|
||||||
|
res = StringEqual
|
||||||
|
case EACLRecord_FilterInfo_StringNotEqual:
|
||||||
|
res = StringNotEqual
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetMatchType passes casted argument to MatchType field setter.
|
||||||
|
//
|
||||||
|
// If filter is not initialized, nothing changes.
|
||||||
|
//
|
||||||
|
// MatchType is set to EACLRecord_FilterInfo_MatchUnknown if argument is not one of:
|
||||||
|
// - StringEqual;
|
||||||
|
// - StringNotEqual.
|
||||||
|
func (s EACLFilterWrapper) SetMatchType(v MatchType) {
|
||||||
|
if s.filter != nil {
|
||||||
|
switch v {
|
||||||
|
case StringEqual:
|
||||||
|
s.filter.SetMatchType(EACLRecord_FilterInfo_StringEqual)
|
||||||
|
case StringNotEqual:
|
||||||
|
s.filter.SetMatchType(EACLRecord_FilterInfo_StringNotEqual)
|
||||||
|
default:
|
||||||
|
s.filter.SetMatchType(EACLRecord_FilterInfo_MatchUnknown)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Name returns the result of HeaderName field getter.
|
||||||
|
//
|
||||||
|
// If filter is not initialized, empty string returns.
|
||||||
|
func (s EACLFilterWrapper) Name() string {
|
||||||
|
if s.filter == nil {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
return s.filter.GetHeaderName()
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetName passes argument to HeaderName field setter.
|
||||||
|
//
|
||||||
|
// If filter is not initialized, nothing changes.
|
||||||
|
func (s EACLFilterWrapper) SetName(v string) {
|
||||||
|
if s.filter != nil {
|
||||||
|
s.filter.SetHeaderName(v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Value returns the result of HeaderVal field getter.
|
||||||
|
//
|
||||||
|
// If filter is not initialized, empty string returns.
|
||||||
|
func (s EACLFilterWrapper) Value() string {
|
||||||
|
if s.filter == nil {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
return s.filter.GetHeaderVal()
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetValue passes argument to HeaderVal field setter.
|
||||||
|
//
|
||||||
|
// If filter is not initialized, nothing changes.
|
||||||
|
func (s EACLFilterWrapper) SetValue(v string) {
|
||||||
|
if s.filter != nil {
|
||||||
|
s.filter.SetHeaderVal(v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// HeaderType returns the result of Header field getter.
|
||||||
|
//
|
||||||
|
// If filter is not initialized, 0 returns.
|
||||||
|
//
|
||||||
|
// Returns 0 if Header is not one of:
|
||||||
|
// - EACLRecord_FilterInfo_Request;
|
||||||
|
// - EACLRecord_FilterInfo_ObjectSystem;
|
||||||
|
// - EACLRecord_FilterInfo_ObjectUser.
|
||||||
|
func (s EACLFilterWrapper) HeaderType() (res HeaderType) {
|
||||||
|
if s.filter != nil {
|
||||||
|
switch s.filter.GetHeader() {
|
||||||
|
case EACLRecord_FilterInfo_Request:
|
||||||
|
res = HdrTypeRequest
|
||||||
|
case EACLRecord_FilterInfo_ObjectSystem:
|
||||||
|
res = HdrTypeObjSys
|
||||||
|
case EACLRecord_FilterInfo_ObjectUser:
|
||||||
|
res = HdrTypeObjUsr
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetHeaderType passes casted argument to Header field setter.
|
||||||
|
//
|
||||||
|
// If filter is not initialized, nothing changes.
|
||||||
|
//
|
||||||
|
// Header is set to EACLRecord_FilterInfo_HeaderUnknown if argument is not one of:
|
||||||
|
// - HdrTypeRequest;
|
||||||
|
// - HdrTypeObjSys;
|
||||||
|
// - HdrTypeObjUsr.
|
||||||
|
func (s EACLFilterWrapper) SetHeaderType(t HeaderType) {
|
||||||
|
if s.filter != nil {
|
||||||
|
switch t {
|
||||||
|
case HdrTypeRequest:
|
||||||
|
s.filter.SetHeader(EACLRecord_FilterInfo_Request)
|
||||||
|
case HdrTypeObjSys:
|
||||||
|
s.filter.SetHeader(EACLRecord_FilterInfo_ObjectSystem)
|
||||||
|
case HdrTypeObjUsr:
|
||||||
|
s.filter.SetHeader(EACLRecord_FilterInfo_ObjectUser)
|
||||||
|
default:
|
||||||
|
s.filter.SetHeader(EACLRecord_FilterInfo_HeaderUnknown)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Target returns the result of Target field getter.
|
||||||
|
//
|
||||||
|
// If target is not initialized, Target_Unknown returns.
|
||||||
|
func (s EACLTargetWrapper) Target() Target {
|
||||||
|
if s.target == nil {
|
||||||
|
return Target_Unknown
|
||||||
|
}
|
||||||
|
|
||||||
|
return s.target.GetTarget()
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetTarget passes argument to Target field setter.
|
||||||
|
//
|
||||||
|
// If target is not initialized, nothing changes.
|
||||||
|
func (s EACLTargetWrapper) SetTarget(v Target) {
|
||||||
|
if s.target != nil {
|
||||||
|
s.target.SetTarget(v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// KeyList returns the result of KeyList field getter.
|
||||||
|
//
|
||||||
|
// If target is not initialized, nil returns.
|
||||||
|
func (s EACLTargetWrapper) KeyList() [][]byte {
|
||||||
|
if s.target == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return s.target.GetKeyList()
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetKeyList passes argument to KeyList field setter.
|
||||||
|
//
|
||||||
|
// If target is not initialized, nothing changes.
|
||||||
|
func (s EACLTargetWrapper) SetKeyList(v [][]byte) {
|
||||||
|
if s.target != nil {
|
||||||
|
s.target.SetKeyList(v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// OperationType returns casted result of Operation field getter.
|
||||||
|
//
|
||||||
|
// If record is not initialized, 0 returns.
|
||||||
|
//
|
||||||
|
// Returns 0 if Operation is not one of:
|
||||||
|
// - EACLRecord_HEAD;
|
||||||
|
// - EACLRecord_PUT;
|
||||||
|
// - EACLRecord_SEARCH;
|
||||||
|
// - EACLRecord_GET;
|
||||||
|
// - EACLRecord_GETRANGE;
|
||||||
|
// - EACLRecord_GETRANGEHASH;
|
||||||
|
// - EACLRecord_DELETE.
|
||||||
|
func (s EACLRecordWrapper) OperationType() (res OperationType) {
|
||||||
|
if s.record != nil {
|
||||||
|
switch s.record.GetOperation() {
|
||||||
|
case EACLRecord_HEAD:
|
||||||
|
res = OpTypeHead
|
||||||
|
case EACLRecord_PUT:
|
||||||
|
res = OpTypePut
|
||||||
|
case EACLRecord_SEARCH:
|
||||||
|
res = OpTypeSearch
|
||||||
|
case EACLRecord_GET:
|
||||||
|
res = OpTypeGet
|
||||||
|
case EACLRecord_GETRANGE:
|
||||||
|
res = OpTypeRange
|
||||||
|
case EACLRecord_GETRANGEHASH:
|
||||||
|
res = OpTypeRangeHash
|
||||||
|
case EACLRecord_DELETE:
|
||||||
|
res = OpTypeDelete
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetOperationType passes casted argument to Operation field setter.
|
||||||
|
//
|
||||||
|
// If record is not initialized, nothing changes.
|
||||||
|
//
|
||||||
|
// Operation is set to EACLRecord_OPERATION_UNKNOWN if argument is not one of:
|
||||||
|
// - OpTypeHead;
|
||||||
|
// - OpTypePut;
|
||||||
|
// - OpTypeSearch;
|
||||||
|
// - OpTypeGet;
|
||||||
|
// - OpTypeRange;
|
||||||
|
// - OpTypeRangeHash;
|
||||||
|
// - OpTypeDelete.
|
||||||
|
func (s EACLRecordWrapper) SetOperationType(v OperationType) {
|
||||||
|
if s.record != nil {
|
||||||
|
switch v {
|
||||||
|
case OpTypeHead:
|
||||||
|
s.record.SetOperation(EACLRecord_HEAD)
|
||||||
|
case OpTypePut:
|
||||||
|
s.record.SetOperation(EACLRecord_PUT)
|
||||||
|
case OpTypeSearch:
|
||||||
|
s.record.SetOperation(EACLRecord_SEARCH)
|
||||||
|
case OpTypeGet:
|
||||||
|
s.record.SetOperation(EACLRecord_GET)
|
||||||
|
case OpTypeRange:
|
||||||
|
s.record.SetOperation(EACLRecord_GETRANGE)
|
||||||
|
case OpTypeRangeHash:
|
||||||
|
s.record.SetOperation(EACLRecord_GETRANGEHASH)
|
||||||
|
case OpTypeDelete:
|
||||||
|
s.record.SetOperation(EACLRecord_DELETE)
|
||||||
|
default:
|
||||||
|
s.record.SetOperation(EACLRecord_OPERATION_UNKNOWN)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Action returns casted result of Action field getter.
|
||||||
|
//
|
||||||
|
// If record is not initialized, 0 returns.
|
||||||
|
//
|
||||||
|
// Returns 0 if Action is not one of:
|
||||||
|
// - EACLRecord_Deny;
|
||||||
|
// - EACLRecord_Allow.
|
||||||
|
func (s EACLRecordWrapper) Action() (res ExtendedACLAction) {
|
||||||
|
if s.record != nil {
|
||||||
|
switch s.record.GetAction() {
|
||||||
|
case EACLRecord_Deny:
|
||||||
|
res = ActionDeny
|
||||||
|
case EACLRecord_Allow:
|
||||||
|
res = ActionAllow
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetAction passes casted argument to Action field setter.
|
||||||
|
//
|
||||||
|
// If record is not initialized, nothing changes.
|
||||||
|
//
|
||||||
|
// Action is set to EACLRecord_ActionUnknown if argument is not one of:
|
||||||
|
// - ActionDeny;
|
||||||
|
// - ActionAllow.
|
||||||
|
func (s EACLRecordWrapper) SetAction(v ExtendedACLAction) {
|
||||||
|
if s.record != nil {
|
||||||
|
switch v {
|
||||||
|
case ActionDeny:
|
||||||
|
s.record.SetAction(EACLRecord_Deny)
|
||||||
|
case ActionAllow:
|
||||||
|
s.record.SetAction(EACLRecord_Allow)
|
||||||
|
default:
|
||||||
|
s.record.SetAction(EACLRecord_ActionUnknown)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// HeaderFilters wraps all elements from Filters field getter result and returns HeaderFilter list.
|
||||||
|
//
|
||||||
|
// If record is not initialized, nil returns.
|
||||||
|
func (s EACLRecordWrapper) HeaderFilters() []HeaderFilter {
|
||||||
|
if s.record == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
filters := s.record.GetFilters()
|
||||||
|
|
||||||
|
res := make([]HeaderFilter, 0, len(filters))
|
||||||
|
|
||||||
|
for i := range filters {
|
||||||
|
res = append(res, WrapFilterInfo(filters[i]))
|
||||||
|
}
|
||||||
|
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetHeaderFilters converts HeaderFilter list to EACLRecord_FilterInfo list and passes it to Filters field setter.
|
||||||
|
//
|
||||||
|
// Ignores nil elements of argument.
|
||||||
|
// If record is not initialized, nothing changes.
|
||||||
|
func (s EACLRecordWrapper) SetHeaderFilters(v []HeaderFilter) {
|
||||||
|
if s.record == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
filters := make([]*EACLRecord_FilterInfo, 0, len(v))
|
||||||
|
|
||||||
|
for i := range v {
|
||||||
|
if v[i] == nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
w := WrapFilterInfo(nil)
|
||||||
|
w.SetMatchType(v[i].MatchType())
|
||||||
|
w.SetHeaderType(v[i].HeaderType())
|
||||||
|
w.SetName(v[i].Name())
|
||||||
|
w.SetValue(v[i].Value())
|
||||||
|
|
||||||
|
filters = append(filters, w.filter)
|
||||||
|
}
|
||||||
|
|
||||||
|
s.record.SetFilters(filters)
|
||||||
|
}
|
||||||
|
|
||||||
|
// TargetList wraps all elements from Targets field getter result and returns ExtendedACLTarget list.
|
||||||
|
//
|
||||||
|
// If record is not initialized, nil returns.
|
||||||
|
func (s EACLRecordWrapper) TargetList() []ExtendedACLTarget {
|
||||||
|
if s.record == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
targets := s.record.GetTargets()
|
||||||
|
|
||||||
|
res := make([]ExtendedACLTarget, 0, len(targets))
|
||||||
|
|
||||||
|
for i := range targets {
|
||||||
|
res = append(res, WrapEACLTarget(targets[i]))
|
||||||
|
}
|
||||||
|
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetTargetList converts ExtendedACLTarget list to EACLRecord_TargetInfo list and passes it to Targets field setter.
|
||||||
|
//
|
||||||
|
// Ignores nil elements of argument.
|
||||||
|
// If record is not initialized, nothing changes.
|
||||||
|
func (s EACLRecordWrapper) SetTargetList(v []ExtendedACLTarget) {
|
||||||
|
if s.record == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
targets := make([]*EACLRecord_TargetInfo, 0, len(v))
|
||||||
|
|
||||||
|
for i := range v {
|
||||||
|
if v[i] == nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
w := WrapEACLTarget(nil)
|
||||||
|
w.SetTarget(v[i].Target())
|
||||||
|
w.SetKeyList(v[i].KeyList())
|
||||||
|
|
||||||
|
targets = append(targets, w.target)
|
||||||
|
}
|
||||||
|
|
||||||
|
s.record.SetTargets(targets)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Records wraps all elements from Records field getter result and returns ExtendedACLRecord list.
|
||||||
|
//
|
||||||
|
// If table is not initialized, nil returns.
|
||||||
|
func (s EACLTableWrapper) Records() []ExtendedACLRecord {
|
||||||
|
if s.table == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
records := s.table.GetRecords()
|
||||||
|
|
||||||
|
res := make([]ExtendedACLRecord, 0, len(records))
|
||||||
|
|
||||||
|
for i := range records {
|
||||||
|
res = append(res, WrapEACLRecord(records[i]))
|
||||||
|
}
|
||||||
|
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetRecords converts ExtendedACLRecord list to EACLRecord list and passes it to Records field setter.
|
||||||
|
//
|
||||||
|
// Ignores nil elements of argument.
|
||||||
|
// If table is not initialized, nothing changes.
|
||||||
|
func (s EACLTableWrapper) SetRecords(v []ExtendedACLRecord) {
|
||||||
|
if s.table == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
records := make([]*EACLRecord, 0, len(v))
|
||||||
|
|
||||||
|
for i := range v {
|
||||||
|
if v[i] == nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
w := WrapEACLRecord(nil)
|
||||||
|
w.SetOperationType(v[i].OperationType())
|
||||||
|
w.SetAction(v[i].Action())
|
||||||
|
w.SetHeaderFilters(v[i].HeaderFilters())
|
||||||
|
w.SetTargetList(v[i].TargetList())
|
||||||
|
|
||||||
|
records = append(records, w.record)
|
||||||
|
}
|
||||||
|
|
||||||
|
s.table.SetRecords(records)
|
||||||
|
}
|
||||||
|
|
||||||
|
// MarshalBinary returns the result of Marshal method.
|
||||||
|
func (s EACLTableWrapper) MarshalBinary() ([]byte, error) {
|
||||||
|
return s.table.Marshal()
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnmarshalBinary passes argument to Unmarshal method and returns its result.
|
||||||
|
func (s EACLTableWrapper) UnmarshalBinary(data []byte) error {
|
||||||
|
return s.table.Unmarshal(data)
|
||||||
|
}
|
139
acl/wrappers_test.go
Normal file
139
acl/wrappers_test.go
Normal file
|
@ -0,0 +1,139 @@
|
||||||
|
package acl
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestEACLFilterWrapper(t *testing.T) {
|
||||||
|
s := WrapFilterInfo(nil)
|
||||||
|
|
||||||
|
mt := StringEqual
|
||||||
|
s.SetMatchType(mt)
|
||||||
|
require.Equal(t, mt, s.MatchType())
|
||||||
|
|
||||||
|
ht := HdrTypeObjUsr
|
||||||
|
s.SetHeaderType(ht)
|
||||||
|
require.Equal(t, ht, s.HeaderType())
|
||||||
|
|
||||||
|
n := "name"
|
||||||
|
s.SetName(n)
|
||||||
|
require.Equal(t, n, s.Name())
|
||||||
|
|
||||||
|
v := "value"
|
||||||
|
s.SetValue(v)
|
||||||
|
require.Equal(t, v, s.Value())
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestEACLTargetWrapper(t *testing.T) {
|
||||||
|
s := WrapEACLTarget(nil)
|
||||||
|
|
||||||
|
target := Target(10)
|
||||||
|
s.SetTarget(target)
|
||||||
|
require.Equal(t, target, s.Target())
|
||||||
|
|
||||||
|
keys := [][]byte{
|
||||||
|
{1, 2, 3},
|
||||||
|
{4, 5, 6},
|
||||||
|
}
|
||||||
|
s.SetKeyList(keys)
|
||||||
|
require.Equal(t, keys, s.KeyList())
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestEACLRecordWrapper(t *testing.T) {
|
||||||
|
s := WrapEACLRecord(nil)
|
||||||
|
|
||||||
|
action := ActionAllow
|
||||||
|
s.SetAction(action)
|
||||||
|
require.Equal(t, action, s.Action())
|
||||||
|
|
||||||
|
opType := OperationType(5)
|
||||||
|
s.SetOperationType(opType)
|
||||||
|
require.Equal(t, opType, s.OperationType())
|
||||||
|
|
||||||
|
f1Name := "name1"
|
||||||
|
f1 := WrapFilterInfo(nil)
|
||||||
|
f1.SetName(f1Name)
|
||||||
|
|
||||||
|
f2Name := "name2"
|
||||||
|
f2 := WrapFilterInfo(nil)
|
||||||
|
f2.SetName(f2Name)
|
||||||
|
|
||||||
|
s.SetHeaderFilters([]HeaderFilter{f1, f2})
|
||||||
|
|
||||||
|
filters := s.HeaderFilters()
|
||||||
|
require.Len(t, filters, 2)
|
||||||
|
require.Equal(t, f1Name, filters[0].Name())
|
||||||
|
require.Equal(t, f2Name, filters[1].Name())
|
||||||
|
|
||||||
|
target1 := Target(1)
|
||||||
|
t1 := WrapEACLTarget(nil)
|
||||||
|
t1.SetTarget(target1)
|
||||||
|
|
||||||
|
target2 := Target(2)
|
||||||
|
t2 := WrapEACLTarget(nil)
|
||||||
|
t2.SetTarget(target2)
|
||||||
|
|
||||||
|
s.SetTargetList([]ExtendedACLTarget{t1, t2})
|
||||||
|
|
||||||
|
targets := s.TargetList()
|
||||||
|
require.Len(t, targets, 2)
|
||||||
|
require.Equal(t, target1, targets[0].Target())
|
||||||
|
require.Equal(t, target2, targets[1].Target())
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestEACLTableWrapper(t *testing.T) {
|
||||||
|
s := WrapEACLTable(nil)
|
||||||
|
|
||||||
|
action1 := ExtendedACLAction(1)
|
||||||
|
r1 := WrapEACLRecord(nil)
|
||||||
|
r1.SetAction(action1)
|
||||||
|
|
||||||
|
action2 := ExtendedACLAction(2)
|
||||||
|
r2 := WrapEACLRecord(nil)
|
||||||
|
r2.SetAction(action2)
|
||||||
|
|
||||||
|
s.SetRecords([]ExtendedACLRecord{r1, r2})
|
||||||
|
|
||||||
|
records := s.Records()
|
||||||
|
require.Len(t, records, 2)
|
||||||
|
require.Equal(t, action1, records[0].Action())
|
||||||
|
require.Equal(t, action2, records[1].Action())
|
||||||
|
|
||||||
|
data, err := s.MarshalBinary()
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
s2 := WrapEACLTable(nil)
|
||||||
|
require.NoError(t, s2.UnmarshalBinary(data))
|
||||||
|
|
||||||
|
records1 := s.Records()
|
||||||
|
records2 := s2.Records()
|
||||||
|
require.Len(t, records1, len(records2))
|
||||||
|
|
||||||
|
for i := range records1 {
|
||||||
|
require.Equal(t, records1[i].Action(), records2[i].Action())
|
||||||
|
require.Equal(t, records1[i].OperationType(), records2[i].OperationType())
|
||||||
|
|
||||||
|
targets1 := records1[i].TargetList()
|
||||||
|
targets2 := records2[i].TargetList()
|
||||||
|
require.Len(t, targets1, len(targets2))
|
||||||
|
|
||||||
|
for j := range targets1 {
|
||||||
|
require.Equal(t, targets1[j].Target(), targets2[j].Target())
|
||||||
|
require.Equal(t, targets1[j].KeyList(), targets2[j].KeyList())
|
||||||
|
}
|
||||||
|
|
||||||
|
filters1 := records1[i].HeaderFilters()
|
||||||
|
filters2 := records2[i].HeaderFilters()
|
||||||
|
require.Len(t, filters1, len(filters2))
|
||||||
|
|
||||||
|
for j := range filters1 {
|
||||||
|
require.Equal(t, filters1[j].MatchType(), filters2[j].MatchType())
|
||||||
|
require.Equal(t, filters1[j].HeaderType(), filters2[j].HeaderType())
|
||||||
|
require.Equal(t, filters1[j].Name(), filters2[j].Name())
|
||||||
|
require.Equal(t, filters1[j].Value(), filters2[j].Value())
|
||||||
|
require.Equal(t, filters1[j].Value(), filters2[j].Value())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
116
docs/acl.md
116
docs/acl.md
|
@ -5,7 +5,12 @@
|
||||||
|
|
||||||
- [acl/types.proto](#acl/types.proto)
|
- [acl/types.proto](#acl/types.proto)
|
||||||
|
|
||||||
|
- Messages
|
||||||
|
- [EACLRecord](#acl.EACLRecord)
|
||||||
|
- [EACLRecord.FilterInfo](#acl.EACLRecord.FilterInfo)
|
||||||
|
- [EACLRecord.TargetInfo](#acl.EACLRecord.TargetInfo)
|
||||||
|
- [EACLTable](#acl.EACLTable)
|
||||||
|
|
||||||
|
|
||||||
- [Scalar Value Types](#scalar-value-types)
|
- [Scalar Value Types](#scalar-value-types)
|
||||||
|
|
||||||
|
@ -19,9 +24,118 @@
|
||||||
|
|
||||||
<!-- end services -->
|
<!-- end services -->
|
||||||
|
|
||||||
|
|
||||||
|
<a name="acl.EACLRecord"></a>
|
||||||
|
|
||||||
|
### Message EACLRecord
|
||||||
|
EACLRecord groups information about extended ACL rule.
|
||||||
|
|
||||||
|
|
||||||
|
| Field | Type | Label | Description |
|
||||||
|
| ----- | ---- | ----- | ----------- |
|
||||||
|
| operation | [EACLRecord.Operation](#acl.EACLRecord.Operation) | | Operation carries type of operation. |
|
||||||
|
| action | [EACLRecord.Action](#acl.EACLRecord.Action) | | Action carries ACL target action. |
|
||||||
|
| Filters | [EACLRecord.FilterInfo](#acl.EACLRecord.FilterInfo) | repeated | Filters carries set of filters. |
|
||||||
|
| Targets | [EACLRecord.TargetInfo](#acl.EACLRecord.TargetInfo) | repeated | Targets carries information about extended ACL target list. |
|
||||||
|
|
||||||
|
|
||||||
|
<a name="acl.EACLRecord.FilterInfo"></a>
|
||||||
|
|
||||||
|
### Message EACLRecord.FilterInfo
|
||||||
|
FilterInfo groups information about filter.
|
||||||
|
|
||||||
|
|
||||||
|
| Field | Type | Label | Description |
|
||||||
|
| ----- | ---- | ----- | ----------- |
|
||||||
|
| header | [EACLRecord.FilterInfo.Header](#acl.EACLRecord.FilterInfo.Header) | | Header carries type of header. |
|
||||||
|
| matchType | [EACLRecord.FilterInfo.MatchType](#acl.EACLRecord.FilterInfo.MatchType) | | MatchType carries type of match. |
|
||||||
|
| HeaderName | [string](#string) | | HeaderName carries name of filtering header. |
|
||||||
|
| HeaderVal | [string](#string) | | HeaderVal carries value of filtering header. |
|
||||||
|
|
||||||
|
|
||||||
|
<a name="acl.EACLRecord.TargetInfo"></a>
|
||||||
|
|
||||||
|
### Message EACLRecord.TargetInfo
|
||||||
|
TargetInfo groups information about extended ACL target.
|
||||||
|
|
||||||
|
|
||||||
|
| Field | Type | Label | Description |
|
||||||
|
| ----- | ---- | ----- | ----------- |
|
||||||
|
| Target | [Target](#acl.Target) | | Target carries target of ACL rule. |
|
||||||
|
| KeyList | [bytes](#bytes) | repeated | KeyList carries public keys of ACL target. |
|
||||||
|
|
||||||
|
|
||||||
|
<a name="acl.EACLTable"></a>
|
||||||
|
|
||||||
|
### Message EACLTable
|
||||||
|
EACLRecord carries the information about extended ACL rules.
|
||||||
|
|
||||||
|
|
||||||
|
| Field | Type | Label | Description |
|
||||||
|
| ----- | ---- | ----- | ----------- |
|
||||||
|
| Records | [EACLRecord](#acl.EACLRecord) | repeated | Records carries list of extended ACL rule records. |
|
||||||
|
|
||||||
<!-- end messages -->
|
<!-- end messages -->
|
||||||
|
|
||||||
|
|
||||||
|
<a name="acl.EACLRecord.Action"></a>
|
||||||
|
|
||||||
|
### EACLRecord.Action
|
||||||
|
Action is an enumeration of EACL actions.
|
||||||
|
|
||||||
|
| Name | Number | Description |
|
||||||
|
| ---- | ------ | ----------- |
|
||||||
|
| ActionUnknown | 0 | |
|
||||||
|
| Allow | 1 | |
|
||||||
|
| Deny | 2 | |
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<a name="acl.EACLRecord.FilterInfo.Header"></a>
|
||||||
|
|
||||||
|
### EACLRecord.FilterInfo.Header
|
||||||
|
Header is an enumeration of filtering header types.
|
||||||
|
|
||||||
|
| Name | Number | Description |
|
||||||
|
| ---- | ------ | ----------- |
|
||||||
|
| HeaderUnknown | 0 | |
|
||||||
|
| Request | 1 | |
|
||||||
|
| ObjectSystem | 2 | |
|
||||||
|
| ObjectUser | 3 | |
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<a name="acl.EACLRecord.FilterInfo.MatchType"></a>
|
||||||
|
|
||||||
|
### EACLRecord.FilterInfo.MatchType
|
||||||
|
MatchType is an enumeration of match types.
|
||||||
|
|
||||||
|
| Name | Number | Description |
|
||||||
|
| ---- | ------ | ----------- |
|
||||||
|
| MatchUnknown | 0 | |
|
||||||
|
| StringEqual | 1 | |
|
||||||
|
| StringNotEqual | 2 | |
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<a name="acl.EACLRecord.Operation"></a>
|
||||||
|
|
||||||
|
### EACLRecord.Operation
|
||||||
|
Operation is an enumeration of operation types.
|
||||||
|
|
||||||
|
| Name | Number | Description |
|
||||||
|
| ---- | ------ | ----------- |
|
||||||
|
| OPERATION_UNKNOWN | 0 | |
|
||||||
|
| GET | 1 | |
|
||||||
|
| HEAD | 2 | |
|
||||||
|
| PUT | 3 | |
|
||||||
|
| DELETE | 4 | |
|
||||||
|
| SEARCH | 5 | |
|
||||||
|
| GETRANGE | 6 | |
|
||||||
|
| GETRANGEHASH | 7 | |
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<a name="acl.Target"></a>
|
<a name="acl.Target"></a>
|
||||||
|
|
||||||
### Target
|
### Target
|
||||||
|
|
|
@ -137,11 +137,24 @@ func verifySignatures(src SignedDataSource, items ...SignKeyPair) error {
|
||||||
}
|
}
|
||||||
defer bytesPool.Put(data)
|
defer bytesPool.Put(data)
|
||||||
|
|
||||||
for _, signKey := range items {
|
for i := range items {
|
||||||
|
if i > 0 {
|
||||||
|
// add previous key bytes to the signed message
|
||||||
|
|
||||||
|
signKeyDataSrc := SignKeyPairsSignedData(items[i-1])
|
||||||
|
|
||||||
|
signKeyData, err := signKeyDataSrc.SignedData()
|
||||||
|
if err != nil {
|
||||||
|
return errors.Wrapf(err, "could not get signed data of key-signature #%d", i)
|
||||||
|
}
|
||||||
|
|
||||||
|
data = append(data, signKeyData...)
|
||||||
|
}
|
||||||
|
|
||||||
if err := crypto.Verify(
|
if err := crypto.Verify(
|
||||||
signKey.GetPublicKey(),
|
items[i].GetPublicKey(),
|
||||||
data,
|
data,
|
||||||
signKey.GetSignature(),
|
items[i].GetSignature(),
|
||||||
); err != nil {
|
); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -213,6 +226,7 @@ func SignRequestData(key *ecdsa.PrivateKey, src RequestSignedData) error {
|
||||||
src.GetBearerToken(),
|
src.GetBearerToken(),
|
||||||
),
|
),
|
||||||
ExtendedHeadersSignedData(src),
|
ExtendedHeadersSignedData(src),
|
||||||
|
SignKeyPairsSignedData(src.GetSignKeyPairs()...),
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
|
|
@ -15,13 +15,13 @@ import (
|
||||||
type testSignedDataSrc struct {
|
type testSignedDataSrc struct {
|
||||||
err error
|
err error
|
||||||
data []byte
|
data []byte
|
||||||
sig []byte
|
|
||||||
key *ecdsa.PublicKey
|
|
||||||
token SessionToken
|
token SessionToken
|
||||||
|
|
||||||
bearer BearerToken
|
bearer BearerToken
|
||||||
|
|
||||||
extHdrs []ExtendedHeader
|
extHdrs []ExtendedHeader
|
||||||
|
|
||||||
|
signKeys []SignKeyPair
|
||||||
}
|
}
|
||||||
|
|
||||||
type testSignedDataReader struct {
|
type testSignedDataReader struct {
|
||||||
|
@ -29,13 +29,15 @@ type testSignedDataReader struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s testSignedDataSrc) GetSignature() []byte {
|
func (s testSignedDataSrc) GetSignature() []byte {
|
||||||
return s.sig
|
if len(s.signKeys) > 0 {
|
||||||
|
return s.signKeys[0].GetSignature()
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s testSignedDataSrc) GetSignKeyPairs() []SignKeyPair {
|
func (s testSignedDataSrc) GetSignKeyPairs() []SignKeyPair {
|
||||||
return []SignKeyPair{
|
return s.signKeys
|
||||||
newSignatureKeyPair(s.key, s.sig),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s testSignedDataSrc) SignedData() ([]byte, error) {
|
func (s testSignedDataSrc) SignedData() ([]byte, error) {
|
||||||
|
@ -43,8 +45,9 @@ func (s testSignedDataSrc) SignedData() ([]byte, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *testSignedDataSrc) AddSignKey(sig []byte, key *ecdsa.PublicKey) {
|
func (s *testSignedDataSrc) AddSignKey(sig []byte, key *ecdsa.PublicKey) {
|
||||||
s.key = key
|
s.signKeys = append(s.signKeys,
|
||||||
s.sig = sig
|
newSignatureKeyPair(key, sig),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
func testData(t *testing.T, sz int) []byte {
|
func testData(t *testing.T, sz int) []byte {
|
||||||
|
@ -209,23 +212,27 @@ func TestVerifyAccumulatedSignatures(t *testing.T) {
|
||||||
// create test private key
|
// create test private key
|
||||||
sk := test.DecodeKey(0)
|
sk := test.DecodeKey(0)
|
||||||
|
|
||||||
|
signKey := new(RequestVerificationHeader_Signature)
|
||||||
|
signKey.Peer = crypto.MarshalPublicKey(&sk.PublicKey)
|
||||||
|
|
||||||
// create signature source
|
// create signature source
|
||||||
src := &testSignedDataSrc{
|
src := &testSignedDataSrc{
|
||||||
data: testData(t, 10),
|
data: testData(t, 10),
|
||||||
key: &sk.PublicKey,
|
|
||||||
|
signKeys: []SignKeyPair{signKey},
|
||||||
}
|
}
|
||||||
|
|
||||||
var err error
|
var err error
|
||||||
|
|
||||||
// calculate a signature
|
// calculate a signature
|
||||||
src.sig, err = crypto.Sign(sk, src.data)
|
signKey.Sign, err = crypto.Sign(sk, src.data)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
// ascertain that verification is passed
|
// ascertain that verification is passed
|
||||||
require.NoError(t, VerifyAccumulatedSignatures(src))
|
require.NoError(t, VerifyAccumulatedSignatures(src))
|
||||||
|
|
||||||
// break the signature
|
// break the signature
|
||||||
src.sig[0]++
|
signKey.Sign[0]++
|
||||||
|
|
||||||
// ascertain that verification is failed
|
// ascertain that verification is failed
|
||||||
require.Error(t, VerifyAccumulatedSignatures(src))
|
require.Error(t, VerifyAccumulatedSignatures(src))
|
||||||
|
@ -238,9 +245,13 @@ func TestVerifySignatureWithKey(t *testing.T) {
|
||||||
ErrEmptyDataWithSignature.Error(),
|
ErrEmptyDataWithSignature.Error(),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
signKey := new(RequestVerificationHeader_Signature)
|
||||||
|
|
||||||
// create test signature source
|
// create test signature source
|
||||||
src := &testSignedDataSrc{
|
src := &testSignedDataSrc{
|
||||||
data: testData(t, 10),
|
data: testData(t, 10),
|
||||||
|
|
||||||
|
signKeys: []SignKeyPair{signKey},
|
||||||
}
|
}
|
||||||
|
|
||||||
// nil public key
|
// nil public key
|
||||||
|
@ -255,14 +266,14 @@ func TestVerifySignatureWithKey(t *testing.T) {
|
||||||
var err error
|
var err error
|
||||||
|
|
||||||
// calculate a signature
|
// calculate a signature
|
||||||
src.sig, err = crypto.Sign(sk, src.data)
|
signKey.Sign, err = crypto.Sign(sk, src.data)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
// ascertain that verification is passed
|
// ascertain that verification is passed
|
||||||
require.NoError(t, VerifySignatureWithKey(&sk.PublicKey, src))
|
require.NoError(t, VerifySignatureWithKey(&sk.PublicKey, src))
|
||||||
|
|
||||||
// break the signature
|
// break the signature
|
||||||
src.sig[0]++
|
signKey.Sign[0]++
|
||||||
|
|
||||||
// ascertain that verification is failed
|
// ascertain that verification is failed
|
||||||
require.Error(t, VerifySignatureWithKey(&sk.PublicKey, src))
|
require.Error(t, VerifySignatureWithKey(&sk.PublicKey, src))
|
||||||
|
@ -375,4 +386,15 @@ func TestSignVerifyRequestData(t *testing.T) {
|
||||||
|
|
||||||
// ascertain that verification is passed
|
// ascertain that verification is passed
|
||||||
require.NoError(t, VerifyRequestData(rdr))
|
require.NoError(t, VerifyRequestData(rdr))
|
||||||
|
|
||||||
|
if len(rdr.GetSignKeyPairs()) < 2 {
|
||||||
|
// add one more signature
|
||||||
|
require.NoError(t, SignRequestData(test.DecodeKey(1), rdr))
|
||||||
|
}
|
||||||
|
|
||||||
|
// change key-signature order
|
||||||
|
rdr.signKeys[0], rdr.signKeys[1] = rdr.signKeys[1], rdr.signKeys[0]
|
||||||
|
|
||||||
|
// ascertain that verification is failed
|
||||||
|
require.Error(t, VerifyRequestData(src))
|
||||||
}
|
}
|
||||||
|
|
|
@ -262,6 +262,7 @@ type RequestData interface {
|
||||||
type RequestSignedData interface {
|
type RequestSignedData interface {
|
||||||
RequestData
|
RequestData
|
||||||
SignKeyPairAccumulator
|
SignKeyPairAccumulator
|
||||||
|
SignKeyPairSource
|
||||||
}
|
}
|
||||||
|
|
||||||
// RequestVerifyData is an interface of request information with signature read access.
|
// RequestVerifyData is an interface of request information with signature read access.
|
||||||
|
|
|
@ -2,11 +2,16 @@ package service
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"crypto/ecdsa"
|
"crypto/ecdsa"
|
||||||
|
"io"
|
||||||
|
|
||||||
"github.com/nspcc-dev/neofs-api-go/internal"
|
"github.com/nspcc-dev/neofs-api-go/internal"
|
||||||
crypto "github.com/nspcc-dev/neofs-crypto"
|
crypto "github.com/nspcc-dev/neofs-crypto"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type signKeyPairsWrapper struct {
|
||||||
|
items []SignKeyPair
|
||||||
|
}
|
||||||
|
|
||||||
// GetSessionToken returns SessionToken interface of Token field.
|
// GetSessionToken returns SessionToken interface of Token field.
|
||||||
//
|
//
|
||||||
// If token field value is nil, nil returns.
|
// If token field value is nil, nil returns.
|
||||||
|
@ -114,3 +119,48 @@ func (m RequestVerificationHeader) GetBearerToken() BearerToken {
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SignKeyPairsSignedData wraps passed SignKeyPair slice and returns SignedDataSource interface.
|
||||||
|
func SignKeyPairsSignedData(v ...SignKeyPair) SignedDataSource {
|
||||||
|
return &signKeyPairsWrapper{
|
||||||
|
items: v,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// SignedData returns signed SignKeyPair slice in a binary representation.
|
||||||
|
func (s signKeyPairsWrapper) SignedData() ([]byte, error) {
|
||||||
|
return SignedDataFromReader(s)
|
||||||
|
}
|
||||||
|
|
||||||
|
// SignedDataSize returns the length of signed SignKeyPair slice.
|
||||||
|
func (s signKeyPairsWrapper) SignedDataSize() (sz int) {
|
||||||
|
for i := range s.items {
|
||||||
|
// add key length
|
||||||
|
sz += len(
|
||||||
|
crypto.MarshalPublicKey(s.items[i].GetPublicKey()),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// ReadSignedData copies a binary representation of the signed SignKeyPair slice to passed buffer.
|
||||||
|
//
|
||||||
|
// If buffer length is less than required, io.ErrUnexpectedEOF returns.
|
||||||
|
func (s signKeyPairsWrapper) ReadSignedData(p []byte) (int, error) {
|
||||||
|
sz := s.SignedDataSize()
|
||||||
|
if len(p) < sz {
|
||||||
|
return 0, io.ErrUnexpectedEOF
|
||||||
|
}
|
||||||
|
|
||||||
|
off := 0
|
||||||
|
|
||||||
|
for i := range s.items {
|
||||||
|
// copy public key bytes
|
||||||
|
off += copy(p[off:], crypto.MarshalPublicKey(
|
||||||
|
s.items[i].GetPublicKey(),
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
|
return off, nil
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue