git.frostfs.info/TrueCloudLab/frostfs-sdk-go@v0.0.0-20241022124111-5361f0ecebd3/container/acl/acl_basic.go (about) 1 package acl 2 3 import ( 4 "fmt" 5 "strconv" 6 "strings" 7 ) 8 9 // Basic represents basic part of the FrostFS container's ACL. It includes 10 // common (pretty simple) access rules for operations inside the container. 11 // See FrostFS Specification for details. 12 // 13 // One can find some similarities with the traditional Unix permission, such as 14 // 15 // division into scopes: user, group, others 16 // op-permissions: read, write, etc. 17 // sticky bit 18 // 19 // However, these similarities should only be used for better understanding, 20 // in general these mechanisms are different. 21 // 22 // Instances can be created using built-in var declaration, but look carefully 23 // at the default values, and how individual permissions are regulated. 24 // Some frequently used values are presented in exported variables. 25 // 26 // Basic instances are comparable: values can be compared directly using 27 // == operator. 28 // 29 // Note that type conversion from- and to numerical types is not recommended, 30 // use corresponding constants and/or methods instead. 31 type Basic uint32 32 33 // FromBits decodes Basic from the numerical representation. 34 // 35 // See also Bits. 36 func (x *Basic) FromBits(bits uint32) { 37 *x = Basic(bits) 38 } 39 40 // Bits returns numerical encoding of Basic. 41 // 42 // See also FromBits. 43 func (x Basic) Bits() uint32 { 44 return uint32(x) 45 } 46 47 // common bit sections. 48 const ( 49 opAmount = 7 50 bitsPerOp = 4 51 52 bitPosFinal = opAmount * bitsPerOp 53 bitPosSticky = bitPosFinal + 1 54 ) 55 56 // per-op bit order. 57 const ( 58 opBitPosBearer uint8 = iota 59 opBitPosOthers 60 opBitPosContainer 61 opBitPosOwner 62 ) 63 64 // DisableExtension makes Basic FINAL. FINAL indicates the ACL non-extendability 65 // in the related container. 66 // 67 // See also Extendable. 68 func (x *Basic) DisableExtension() { 69 setBit((*uint32)(x), bitPosFinal) 70 } 71 72 // Extendable checks if Basic is NOT made FINAL using DisableExtension. 73 // 74 // Zero Basic is extendable. 75 func (x Basic) Extendable() bool { 76 return !isBitSet(uint32(x), bitPosFinal) 77 } 78 79 // MakeSticky makes Basic STICKY. STICKY indicates that only the owner of any 80 // particular object is allowed to operate on it. 81 // 82 // See also Sticky. 83 func (x *Basic) MakeSticky() { 84 setBit((*uint32)(x), bitPosSticky) 85 } 86 87 // Sticky checks if Basic is made STICKY using MakeSticky. 88 // 89 // Zero Basic is NOT STICKY. 90 func (x Basic) Sticky() bool { 91 return isBitSet(uint32(x), bitPosSticky) 92 } 93 94 // checks if op is used by the storage nodes within replication mechanism. 95 func isReplicationOp(op Op) bool { 96 switch op { 97 default: 98 return false 99 case 100 OpObjectGet, 101 OpObjectHead, 102 OpObjectPut, 103 OpObjectSearch, 104 OpObjectHash: 105 return true 106 } 107 } 108 109 // AllowOp allows the parties with the given role to the given operation. 110 // Op MUST be one of the Op enumeration. Role MUST be one of: 111 // 112 // RoleOwner 113 // RoleContainer 114 // RoleOthers 115 // 116 // and if role is RoleContainer, op MUST NOT be: 117 // 118 // OpObjectGet 119 // OpObjectHead 120 // OpObjectPut 121 // OpObjectSearch 122 // OpObjectHash 123 // 124 // See also IsOpAllowed. 125 func (x *Basic) AllowOp(op Op, role Role) { 126 var bitPos uint8 127 128 switch role { 129 default: 130 panic(fmt.Sprintf("unable to set rules for unsupported role %v", role)) 131 case RoleInnerRing: 132 panic("basic ACL MUST NOT be modified for Inner Ring") 133 case RoleOwner: 134 bitPos = opBitPosOwner 135 case RoleContainer: 136 if isReplicationOp(op) { 137 panic("basic ACL for container replication ops MUST NOT be modified") 138 } 139 140 bitPos = opBitPosContainer 141 case RoleOthers: 142 bitPos = opBitPosOthers 143 } 144 145 setOpBit((*uint32)(x), op, bitPos) 146 } 147 148 // IsOpAllowed checks if parties with the given role are allowed to the given op 149 // according to the Basic rules. Op MUST be one of the Op enumeration. 150 // Role MUST be one of the Role enumeration. 151 // 152 // Members with RoleContainer role have exclusive default access to the 153 // operations of the data replication mechanism: 154 // 155 // OpObjectGet 156 // OpObjectHead 157 // OpObjectPut 158 // OpObjectSearch 159 // OpObjectHash 160 // 161 // RoleInnerRing members are allowed to data audit ops only: 162 // 163 // OpObjectGet 164 // OpObjectHead 165 // OpObjectHash 166 // OpObjectSearch 167 // 168 // Zero Basic prevents any role from accessing any operation in the absence 169 // of default rights. 170 // 171 // See also AllowOp. 172 func (x Basic) IsOpAllowed(op Op, role Role) bool { 173 var bitPos uint8 174 175 switch role { 176 default: 177 panic(fmt.Sprintf("role is unsupported %v", role)) 178 case RoleInnerRing: 179 switch op { 180 case 181 OpObjectGet, 182 OpObjectHead, 183 OpObjectHash, 184 OpObjectSearch: 185 return true 186 default: 187 return false 188 } 189 case RoleOwner: 190 bitPos = opBitPosOwner 191 case RoleContainer: 192 if isReplicationOp(op) { 193 return true 194 } 195 196 bitPos = opBitPosContainer 197 case RoleOthers: 198 bitPos = opBitPosOthers 199 } 200 201 return isOpBitSet(uint32(x), op, bitPos) 202 } 203 204 // AllowBearerRules allows bearer to provide extended ACL rules for the given 205 // operation. Bearer rules doesn't depend on container ACL extensibility. 206 // 207 // See also AllowedBearerRules. 208 func (x *Basic) AllowBearerRules(op Op) { 209 setOpBit((*uint32)(x), op, opBitPosBearer) 210 } 211 212 // AllowedBearerRules checks if bearer rules are allowed using AllowBearerRules. 213 // Op MUST be one of the Op enumeration. 214 // 215 // Zero Basic disallows bearer rules for any op. 216 func (x Basic) AllowedBearerRules(op Op) bool { 217 return isOpBitSet(uint32(x), op, opBitPosBearer) 218 } 219 220 // EncodeToString encodes Basic into hexadecimal string. 221 // 222 // See also DecodeString. 223 func (x Basic) EncodeToString() string { 224 return strconv.FormatUint(uint64(x), 16) 225 } 226 227 // Names of the frequently used Basic values. 228 const ( 229 NamePrivate = "private" 230 NamePrivateExtended = "eacl-private" 231 NamePublicRO = "public-read" 232 NamePublicROExtended = "eacl-public-read" 233 NamePublicRW = "public-read-write" 234 NamePublicRWExtended = "eacl-public-read-write" 235 NamePublicAppend = "public-append" 236 NamePublicAppendExtended = "eacl-public-append" 237 ) 238 239 // Frequently used Basic values. Bitmasks are taken from the FrostFS Specification. 240 const ( 241 Private = Basic(0x1C8C8CCC) // private 242 PrivateExtended = Basic(0x0C8C8CCC) // eacl-private 243 PublicRO = Basic(0x1FBF8CFF) // public-read 244 PublicROExtended = Basic(0x0FBF8CFF) // eacl-public-read 245 PublicRW = Basic(0x1FBFBFFF) // public-read-write 246 PublicRWExtended = Basic(0x0FBFBFFF) // eacl-public-read-write 247 PublicAppend = Basic(0x1FBF9FFF) // public-append 248 PublicAppendExtended = Basic(0x0FBF9FFF) // eacl-public-append 249 ) 250 251 // DecodeString decodes string calculated using EncodeToString. Also supports 252 // human-readable names (Name* constants). 253 func (x *Basic) DecodeString(s string) (e error) { 254 switch s { 255 case NamePrivate: 256 *x = Private 257 case NamePrivateExtended: 258 *x = PrivateExtended 259 case NamePublicRO: 260 *x = PublicRO 261 case NamePublicROExtended: 262 *x = PublicROExtended 263 case NamePublicRW: 264 *x = PublicRW 265 case NamePublicRWExtended: 266 *x = PublicRWExtended 267 case NamePublicAppend: 268 *x = PublicAppend 269 case NamePublicAppendExtended: 270 *x = PublicAppendExtended 271 default: 272 s = strings.TrimPrefix(strings.ToLower(s), "0x") 273 274 v, err := strconv.ParseUint(s, 16, 32) 275 if err != nil { 276 return fmt.Errorf("parse hex: %w", err) 277 } 278 279 *x = Basic(v) 280 } 281 282 return nil 283 }