forked from TrueCloudLab/frostfs-node
95893927aa
Signed-off-by: Evgenii Stratonikov <evgeniy@nspcc.ru>
195 lines
5.2 KiB
Go
195 lines
5.2 KiB
Go
package acl
|
|
|
|
import (
|
|
"github.com/nspcc-dev/neofs-sdk-go/eacl"
|
|
)
|
|
|
|
// wrapper around basic ACL to provide easy access to basic ACL fields
|
|
type basicACLHelper uint32
|
|
|
|
const (
|
|
reservedBitNumber = 2 // first left bits are reserved
|
|
stickyBitPos = reservedBitNumber // X-bit after reserved bits
|
|
finalBitPos = stickyBitPos + 1 // F-bit after X-bit
|
|
)
|
|
|
|
const (
|
|
opOffset = finalBitPos + 1 // offset of operation bits
|
|
bitsPerOp = 4 // number of bits per operation
|
|
opNumber = 7 // number of operation bit sections
|
|
)
|
|
|
|
const (
|
|
bitUser uint8 = iota
|
|
bitSystem
|
|
bitOthers
|
|
bitBearer
|
|
)
|
|
|
|
const leftACLBitPos = opOffset + bitsPerOp*opNumber - 1
|
|
|
|
var (
|
|
order = map[eacl.Operation]uint8{
|
|
eacl.OperationRangeHash: 0,
|
|
eacl.OperationRange: 1,
|
|
eacl.OperationSearch: 2,
|
|
eacl.OperationDelete: 3,
|
|
eacl.OperationPut: 4,
|
|
eacl.OperationHead: 5,
|
|
eacl.OperationGet: 6,
|
|
}
|
|
)
|
|
|
|
// returns true if n-th left bit is set (starting at 0).
|
|
func isLeftBitSet(value basicACLHelper, n uint8) bool {
|
|
bitMask := basicACLHelper(1 << (leftACLBitPos - n))
|
|
return bitMask != 0 && value&bitMask == bitMask
|
|
}
|
|
|
|
// sets n-th left bit (starting at 0).
|
|
func setLeftBit(value *basicACLHelper, n uint8) {
|
|
*value |= basicACLHelper(1 << (leftACLBitPos - n))
|
|
}
|
|
|
|
// resets n-th left bit (starting at 0).
|
|
func resetLeftBit(value *basicACLHelper, n uint8) {
|
|
*value &= ^basicACLHelper(1 << (leftACLBitPos - n))
|
|
}
|
|
|
|
// Final returns true if final option is enabled in ACL.
|
|
func (a basicACLHelper) Final() bool {
|
|
return isLeftBitSet(a, finalBitPos)
|
|
}
|
|
|
|
// SetFinal enables final option in ACL.
|
|
func (a *basicACLHelper) SetFinal() {
|
|
setLeftBit(a, finalBitPos)
|
|
}
|
|
|
|
// ResetFinal disables final option in ACL.
|
|
func (a *basicACLHelper) ResetFinal() {
|
|
resetLeftBit(a, finalBitPos)
|
|
}
|
|
|
|
// Sticky returns true if sticky option is enabled in ACL.
|
|
func (a basicACLHelper) Sticky() bool {
|
|
return isLeftBitSet(a, stickyBitPos)
|
|
}
|
|
|
|
// SetSticky enables the sticky option in ACL.
|
|
func (a *basicACLHelper) SetSticky() {
|
|
setLeftBit(a, stickyBitPos)
|
|
}
|
|
|
|
// ResetSticky disables the sticky option in ACL.
|
|
func (a *basicACLHelper) ResetSticky() {
|
|
resetLeftBit(a, stickyBitPos)
|
|
}
|
|
|
|
// UserAllowed returns true if user allowed the n-th operation in ACL.
|
|
func (a basicACLHelper) UserAllowed(op eacl.Operation) bool {
|
|
if n, ok := order[op]; ok {
|
|
return isLeftBitSet(a, opOffset+n*bitsPerOp+bitUser)
|
|
}
|
|
return false
|
|
}
|
|
|
|
// AllowUser allows user the n-th operation in ACL.
|
|
func (a *basicACLHelper) AllowUser(op eacl.Operation) {
|
|
if n, ok := order[op]; ok {
|
|
setLeftBit(a, opOffset+n*bitsPerOp+bitUser)
|
|
}
|
|
}
|
|
|
|
// ForbidUser forbids user the n-th operation in ACL.
|
|
func (a *basicACLHelper) ForbidUser(op eacl.Operation) {
|
|
if n, ok := order[op]; ok {
|
|
resetLeftBit(a, opOffset+n*bitsPerOp+bitUser)
|
|
}
|
|
}
|
|
|
|
// SystemAllowed returns true if System group allowed the n-th operation is set in ACL.
|
|
func (a basicACLHelper) SystemAllowed(op eacl.Operation) bool {
|
|
if op != eacl.OperationDelete && op != eacl.OperationRange {
|
|
return true
|
|
}
|
|
|
|
if n, ok := order[op]; ok {
|
|
return isLeftBitSet(a, opOffset+n*bitsPerOp+bitSystem)
|
|
}
|
|
|
|
return false
|
|
}
|
|
|
|
// InnerRingAllowed returns true if the operation is allowed by ACL for
|
|
// InnerRing nodes, as part of System group.
|
|
func (a basicACLHelper) InnerRingAllowed(op eacl.Operation) bool {
|
|
switch op {
|
|
case eacl.OperationSearch, eacl.OperationRangeHash, eacl.OperationHead, eacl.OperationGet:
|
|
return true
|
|
default:
|
|
if n, ok := order[op]; ok {
|
|
return isLeftBitSet(a, opOffset+n*bitsPerOp+bitSystem)
|
|
}
|
|
|
|
return false
|
|
}
|
|
}
|
|
|
|
// AllowSystem allows System group the n-th operation in ACL.
|
|
func (a *basicACLHelper) AllowSystem(op eacl.Operation) {
|
|
if n, ok := order[op]; ok {
|
|
setLeftBit(a, opOffset+n*bitsPerOp+bitSystem)
|
|
}
|
|
}
|
|
|
|
// ForbidSystem forbids System group the n-th operation in ACL.
|
|
func (a *basicACLHelper) ForbidSystem(op eacl.Operation) {
|
|
if n, ok := order[op]; ok {
|
|
resetLeftBit(a, opOffset+n*bitsPerOp+bitSystem)
|
|
}
|
|
}
|
|
|
|
// OthersAllowed returns true if Others group allowed the n-th operation is set in ACL.
|
|
func (a basicACLHelper) OthersAllowed(op eacl.Operation) bool {
|
|
if n, ok := order[op]; ok {
|
|
return isLeftBitSet(a, opOffset+n*bitsPerOp+bitOthers)
|
|
}
|
|
return false
|
|
}
|
|
|
|
// AllowOthers allows Others group the n-th operation in ACL.
|
|
func (a *basicACLHelper) AllowOthers(op eacl.Operation) {
|
|
if n, ok := order[op]; ok {
|
|
setLeftBit(a, opOffset+n*bitsPerOp+bitOthers)
|
|
}
|
|
}
|
|
|
|
// ForbidOthers forbids Others group the n-th operation in ACL.
|
|
func (a *basicACLHelper) ForbidOthers(op eacl.Operation) {
|
|
if n, ok := order[op]; ok {
|
|
resetLeftBit(a, opOffset+n*bitsPerOp+bitOthers)
|
|
}
|
|
}
|
|
|
|
// BearerAllowed returns true if Bearer token usage is allowed for n-th operation in ACL.
|
|
func (a basicACLHelper) BearerAllowed(op eacl.Operation) bool {
|
|
if n, ok := order[op]; ok {
|
|
return isLeftBitSet(a, opOffset+n*bitsPerOp+bitBearer)
|
|
}
|
|
return false
|
|
}
|
|
|
|
// AllowBearer allows Bearer token usage for n-th operation in ACL.
|
|
func (a *basicACLHelper) AllowBearer(op eacl.Operation) {
|
|
if n, ok := order[op]; ok {
|
|
setLeftBit(a, opOffset+n*bitsPerOp+bitBearer)
|
|
}
|
|
}
|
|
|
|
// ForbidBearer forbids Bearer token usage for n-th operation in ACL.
|
|
func (a *basicACLHelper) ForbidBearer(op eacl.Operation) {
|
|
if n, ok := order[op]; ok {
|
|
resetLeftBit(a, opOffset+n*bitsPerOp+bitBearer)
|
|
}
|
|
}
|